人工智能对 Python 的严重偏爱:大语言模型偏爱一种语言的问题

大语言模型非常喜欢 Python。这并不一定是件好事。

如今,如果你说自己从未使用过大语言模型 (LLMs) 生成过任何代码,尤其是 Python 代码,那么你可能来自火星。

人工智能正在改变我们构建软件的方式。ChatGPT、Claude 或 Gemini 等工具现已成为我们日常工作流程的一部分。我们通过“氛围编码”来完善我们的工作。

然而,越来越多的研究提出了一个担忧:

人工智能存在严重的偏见,甚至在编程方面也是如此。

伦敦国王学院最近发表的一篇论文揭示,大语言模型(LLMs)在 90% 至 97% 的基准编程任务中使用了 Python,即使其他语言可能更适合。对于某些Python并非最佳选择的项目类型,模型仍以58%的概率选择Python。更令人惊讶的是,Rust语言一次未被采用。

元素周期表

简而言之,AI工具对某种编程语言存在强烈偏好,而这种语言就是Python。

这对Python开发者意味着什么?

作为一名拥有10年以上经验的Python开发者,读完这篇论文后,我的第一反应是,与使用其他编程语言的开发者相比,我的工作可能最容易被AI取代。

暂且不谈就业安全问题,众所周知,每种编程语言都有其优缺点。某种语言可能更适合特定任务。但如果AI几乎为所有任务生成Python代码,我们通过代码编写构建健壮软件的机会可能会降低。

没有完美的编程语言。

为什么Python在AI生成的代码中占据主导地位

十多年来,Python一直是数据科学、机器学习和深度学习领域的统治性语言。正如GitHub的官方博客所说,Python是GitHub上使用最广泛的语言。

由于基于 Python 的开源项目非常多,大语言模型(LLMs) 接收到了大量 Python 示例。因为这些示例是免费的训练数据。

由于它们主要由 Python 提供,因此毫无疑问,它们希望生成 Python 代码来解决您的问题。

就像您花大部分时间学习 Python 一样,当您的老板要求您做一个新项目时,您可能会抓住机会使用 Python。

“对于拿着锤子的人来说,每个问题都像钉子一样。”——查理·芒格

根据 KCL 的研究,不同的大语言模型(LLMs) 在库和语言选择方面存在高度相关性,这表明偏见源于共同的训练偏见,而不是个别架构的差异。

因此,这是训练数据的问题。

另一方面,选择 Python 示例来训练大语言模型(LLMs) 是一个明智之举。

我们仍处于人工智能时代的初期。Python 语法简洁、类型松散、抽象程度高,且解释器容错性强,因此是 LLM 训练数据的自然之选。就像初学者学习 Python 比学习 C++ 容易得多一样。

人工智能反馈循环问题

LLMs 从大量开源 Python 代码中学习。因此,它们主要生成 Python 代码。需要更多编码经验的新手和初级开发人员将在大语言模型的帮助下编写更多的 Python 代码,其中一部分将是开源的。然后,人工智能模型会使用新的免费数据来改进自己,这可能会强化偏见。

随着时间的推移,这个无限循环可能会导致一种生态系统,即某些编程语言及其生态系统被低估,仅仅是因为人工智能工具没有推荐它们,即使某些语言更适合某些任务。

这至少在潜在层面会阻碍特定领域的创新。

研究所提,以性能和安全性著称的Rust语言在测试中从未被选中。

这确实是个问题。

开发者如何应对偏见

我们开发者应在语言选择中发挥更积极的作用。

毕竟,我们使用AI,而非被AI主导。

以下是我认为有效的技巧:

  • 在提示中明确指定所需的编程语言。
  • 要求AI列出多种语言在特定任务中的优缺点。
  • 要求AI用几种不同语言实现同一程序,然后你选择最佳方案。

最后但同样重要的是,养成学习并实践至少一种编译型语言(与Python并行)的习惯,对所有Python工程师都大有裨益。

结论

Python在AI生成的代码中占据主导地位并非本质上不好。它降低了编程的入门门槛。

然而,让人工智能偏见主导所有语言选择,可能会错失更合适的解决方案,而人工智能和氛围编码的无限反馈可能导致重要语言及相关技术失去人气。

随着人工智能在软件开发中日益深入,开发者需要记住,语言选择仍然是_人类的决策_。

目前而言,最佳的氛围编码方式是:你引导人工智能构建软件,而非跟随人工智能的指引。

本文文字及图片出自 AI’s Serious Python Bias: Concerns of LLMs Preferring One Language

共有 63 条讨论

  1. 问题是,大语言模型(LLMs)喜欢过度设计Python。我正在对一个旧的Django项目(基于Python)进行重构,但不知为何,它一直坚持使用存储库模式,尽管Django已经提供了一个基本上就是这种模式的自定义管理器。

    在实现服务模式时,它一直建议使用静态方法,而这些方法完全没有必要,这是“聪明”的代码,初学者往往会喜欢。

    问题是,如果你不知道某件事,你会认为它非常聪明和有用。

    1. 问题是,如果你不知道某件事,你会认为它非常聪明和有用。

      “AI”的一个大问题是,它非常擅长让你相信它的输出质量很好,即使它实际上是垃圾。

      1. 垃圾代码也能卖出去。所以如果垃圾代码能用,没人会在乎。

        1. 一如既往。一次性代码是存在的。

      2. 而这正是大问题。我喜欢编程与软件工程的区别:编程是关于生成代码,AI在这方面表现出色,而软件工程远不止于写代码,它涉及考虑代码的持久性、可扩展性、性能、团队协作及其他更广泛的问题,而AI在这方面并不擅长。

      3. 然后你指出这一点,人工智能就会说:“啊,现在我明白了,我为造成的混淆道歉,你试图做[你说的原话])。在这种情况下[重复相同的答案,但添加了奇怪的错误]

    2. 这似乎是一个普遍问题,尤其是在这些模型所谓的“思维模式”下,无论使用哪种语言。在C++中,我需要使用大量冗长的“做”和“不要做”来推动它达到某种程度的有用性,即使如此,它仍然无法理解基本的语言概念。

    3. SQL也是如此。它拒绝在不为每个新增列添加索引的情况下创建迁移。

    4. 我更偏向于DevOps/SRE/云工程领域。因此,虽然熟悉Python,但不像标准后端开发人员那样经常深入研究Django等细节。

      最近,我一直在尝试重新投入功能开发工作,并正在处理我们的 Django 代码库。我天真地尝试使用 Cursor 以及 VS Code/Copilot 来重构一些代码、添加新模型和变异等,结果真是太糟糕了。我真应该直接跳过尝试使用大语言模型(LLMs),因为正如你所说,这确实浪费了很多时间。即使对于相对基本的查询之类的事情也是如此。

      现在,有人可能会说我使用工具的方法不对,或者提示不够好,这可能在某种程度上是正确的,但对我这个对这些东西生疏的人来说,在完全放弃大语言模型(LLM)之后,用老方法做这项工作所花费的时间要少得多。

    5. 如果你不知道某件事,你会觉得它非常聪明和有用。

      我指出了大语言模型(LLMs)在2023年存在的操纵技术,但没有人听我的。

    6. 我很少说“ffs”。但大语言模型(LLMs)即使你告诉它们不要这样做,也会坚持朝一个方向走。我几乎被迫使用它(至少是为了缓解挫败感)。

    7. 如果你指的是静态方法,也就是纯函数,你可能需要再仔细看看。

    8. 昨天它一直试图为函数添加向后兼容性。我正在将魔术字符串改为传递对象。突然间,它到处添加联合类型和大型if/else块,同时保留所有旧代码。

      我劝它不要这样做,它说:“哦,是的,你告诉我不要担心向后兼容性。好吧”。然后,当它去编写测试时,它看到了旧流程的测试,直接回到尝试添加向后兼容性,以便与测试兼容。😅

    9. 哪个大语言模型(LLM)?它们之间的行为往往略有不同。

      1. Claude sonnet 4.0然后我要求 ChatGPT 5,它也感到困惑。

        1. 嗯。我还没有在任何项目中遇到过这些问题,但我会保持警惕。感谢您提供的信息。

    10. 这听起来好像大语言模型(LLM) 采用了旧知识并试图应用它。

      我们需要更多地研究人工智能——它们可能只是试图重新复制旧模式。

  2. 是的,这很搞笑,ChatGPT喜欢Python和JavaScript。对于其他语言它会挣扎,如果你使用强类型编译语言,那可就麻烦了。

    1. 我发现,强类型编译语言在指导AI方面要有效得多。它可能会生成看起来不错的Python代码,但在运行时却会做一些非常奇怪的事情。至少Rust编译器能捕获大量错误,并为AI提供如何修复的指导。不过,无论如何,这些工具在处理你已经理解的、界限清晰的任务时效果最佳,这样当出现问题时你可以及时纠正。我使用大语言模型(LLMs)的大部分时间只是作为打字加速器。

      1. 我想知道人工智能是否可以与rust-analyzer整合,以提供反馈循环。

        1. 这已经存在了,至少在 Meta 内部是这样。大语言模型(LLM)只是连接到一个标准工具,该工具可以运行以对正在编辑的任何文件进行通用检查/类型检查。它也可能只是附着在 vscodes 问题标签上。

        2. 使用 claude 代码,你可以获得通用钩子。我已经设置好了我的代码,在对文件进行任何更改后,类型检查器和代码检查器就会运行,并根据反馈采取行动。效果很好。

      2. 我们中的一些人打字很快,还有一个可以快速编辑的编辑器,过度使用 AI 只会加速大脑的衰竭!

      3. AI对我工作几乎毫无用处,因为业务逻辑和代码库过于庞大,但我倾向于认同这一观点。它在类型化语言中表现稍好(但仍不够理想),因为至少在这种情况下,智能体可以识别错误并进行修复

    2. 强类型系统在发现代码出现完全离谱的问题时非常有用。

    3. 我正在做一个C++项目,实际上发现它还算不错

      1. 是的,还算不错。我也是C++开发者,但目前正在涉足网页开发,它生成的JS/HTML代码水平完全不同。

        1. 我是PL/SQL开发者。问题是,你看到它在你的语言中表现不错,几乎和你一样水平,然后你看到它完美地处理了一堆React组件。

          我并不担心我的工作,但如果我是Python或React程序员,我可能会担心。

    4. 我用C和Bash得到了一些奇怪的结果。这些事情甚至一个初级开发者都不会做。

    5. 稍等,我去让ChatGPT把一些Haskell代码重写成Malbolge。

  3. 更令人惊讶的是,Rust一次也没被使用。

    天啊,我希望研究人员在听到这个炸弹消息时已经准备好了晕倒的沙发。没有Rust?!这次AI真的走得太远了!

    文章接着提到,解决人工智能偏爱 Python 的一个方法就是直接告诉它使用什么语言。想象一下吧。

    1. 大语言模型(LLMs)认为,锈会因接触氧气而削弱物体。最好避免使用。/s

      1. 它们只是想避免将植物病原体引入可能无法适应它们的生态系统。

    2. 无论如何,当我一年前要求提供 Rust 代码示例时,它会偷偷加入 numpy 和各种其他 Python 内容。smh。

    3. 大语言模型(LLM)显然对毛茸茸的东西有偏见。/s

    4. 实际上,当我询问一些低级编程概念时,我多次看到GPT使用Rust。

    5. 它们在Rust方面的表现有所提升,但大约一年前我第一次尝试时,情况相当有趣。它在编译错误循环中试图修复问题,而随着修复进程,错误列表反而越变越长而非缩短。

  4. 我不明白作者为何没有提到这一点,但这其实不是训练数据偏见的问题,而是构建这项技术的人以及他们用于构建和支持评估工具的知识和技能。

    大多数从事机器学习的人都熟悉Python。因此,他们为生成的Python代码构建了大量评估工具,比其他语言更多。

    在ChatGPT等网页界面中,工具可以将代码发送到容器中运行,观察结果,并相应调整响应。Python是实现这一功能的理想语言,因为它支持数值分析、图表和可视化,以及许多其他你希望聊天机器人处理的用例。由于上述原因,确保一定质量水平的基础已经打好。

    这只是网络效应。

  5. 量化专业人士在保护自己的工作

  6. 这是英特尔的4D棋局计划,旨在从AI热潮中获利……对高性能单核处理器的市场需求将激增,以运行所有用我们目前最慢、主要单线程的语言编写的代码。😂

    1. 要不是那个该死的克里斯·拉特纳,他们本可以得逞的!

  7. 我确实记得一年前它似乎更倾向于推荐Python,但(可能是因为内存功能)现在几乎不再推荐Python了。我主要使用Zig、C、Go和Julia编程,因此这些语言通常是它最常推荐的。如果是我的IDE代理,它会根据当前正在处理的内容进行推荐(最近主要是自定义DSL,尽管没有参考示例,但它处理得相当不错)

    我必须说,如果我只是使用“编写此脚本”提示,它通常会默认选择Python,除非它知道我正在使用Bash或其他语言。

  8. 此外,如果我们继续沿着这种低效编程的路径前进,例如在Rust更适用且能让应用程序运行更快、占用更少内存的情况下使用Python,这将对全球能源消耗产生影响。

    如果所有使用AI驱动编程构建的应用程序效率降低5%,那么将消耗更多电力。放大这一影响,它将成为一个巨大问题。对于你和朋友使用的简单应用程序来说这不是问题,但对于广泛应用或甚至像Windows这样的操作系统使用低效代码时,这将成为一个问题。

  9. 我惊讶地听到它偏向于Python,我本以为会是Next.js或React。

    它在Python方面确实非常出色

  10. 很快,Python的核心设计师将被AI取代。

  11. 我尝试用它来学习Minecraft的模组制作,结果毫无用处,它会混用已废弃的函数和新函数。我猜它需要针对特定任务进行更精细的调优。

  12. 老实说,需要讨论的是,大语言模型(LLMs)正在形成一种编程“元”形式。当大语言模型(LLMs)精通 react、js、python、fastapi 等时,很难推荐或开始使用像 rust 这样的不会手把手教你的东西。

    最终,人们希望更快地交付,这意味着更频繁地使用元,最终导致其他语言、库、技术等停滞不前。

  13. python 是大语言模型(LLMs) 工作最糟糕的语言之一

    • 与 deno 不同,依赖冲突是一个巨大的问题

    • 合理的虚拟环境管理并非易事

    • 与类型化语言不同,类型是可选的

    • 与 rust 不同,没有借用检查器

    • 与ada不同,没有正式的验证

    • 与kotlin或java相比,网络框架尚不成熟

    我认为deno和rust是最好的大语言模型(LLM)语言;deno是因为依赖关系可以在运行时解决,并且它是一个沙盒,因此可以在执行时设置安全保护措施;rust是因为它有借用检查器,并且未来有可能进行静态验证。

    1. 为什么 Python 需要借用检查器?

      1. 借用检查器有助于大语言模型(LLMs)编写内存安全、线程安全的代码。需要借用检查器的是大语言模型(LLMs),而不是 Python。

        1. Python 虽然有 GC,但已经实现了内存安全。Rust 的内存安全本身并不特殊,特殊之处在于它能在编译时静态实现。

          1. Python 提供内存安全,但线程安全需要自行处理。

            1. GIL 仅意味着一次只能有一个线程执行 Python 代码。这与线程安全不同。如果情况如此,单核处理器上就不会有线程安全问题,因为一次只能有一个线程执行。

              然而,要编写线程不安全的代码,让两个线程依次执行,非常简单,例如:

              示例:两个线程都想将一个整数加 1。

              假设整数 x = 0

              • 线程一:获取整数值并存储在临时变量中。(temp_1 = 0)
              • 线程一:将临时变量加 1。(temp_1 = 1)
              • 线程一:将控制权交给另一个线程,或操作系统接管控制。
              • 线程二:获取整数值并存储在临时变量中。(temp_2 = 0)
              • 线程二:将临时变量加1。(temp_2 = 1)
              • 线程二:用临时变量覆盖原始变量。(temp_1 = 1)因此(x=1)
              • 线程二:将控制权交还给其他线程,或操作系统接管控制权。
              • 线程一:用临时变量覆盖原始变量。(temp_2 = 1)因此(x=1)。

              两次递增操作导致 x=1。哎呀!注意每次只有一个线程处于控制状态。

              别让获得的赞声蒙蔽了你。我认为你最好再多学习一些线程知识,因为你目前对线程的理解还不够深入,无法编写线程安全的代码。如果你能掌握这一点,你很快就会比同龄人更具价值。

              (来源:我为单核处理器编写了自己的小型线程操作系统,并且在 Python 中使用线程。)

      1. 真的嗎?你可以使用 uvpoetry 來管理依賴項
      2. 參見 1)
      3. 類型並非可選,它們只是動態的。所有現代 Python 專案都會透過 mypy 或管道中的其他工具在一定程度上強制執行類型提示
      4. 在解釋型垃圾回收語言中,借用檢查器是沒有意義的。即使有,我确信大语言模型(LLMs)也会难以应对借用检查器
      5. 如果你需要一种经过正式验证的语言,你可能不会使用大语言模型(LLMs)这样的容易出错的工具
      6. 我不确定这与python有什么关系,它是一种通用语言。我确信,如果你从大语言模型(LLMs)请求网络内容,它会给你Js代码
      1. 我基本上同意你的观点,但第2点有点荒谬。你说类型不是可选的,只是动态的,然后说所有现代项目都强制类型。A) “所有”在这里承担了太多责任。B) 类型在Python中定义上是可选的,说否则只是无意义的语义争论。类型提示是明确可选的,实际上强制类型提示也是完全可选的。你的代码可能通过所有已知的类型检查器,但仍然可以正常运行。

        Python本身根本没有类型概念。

        1. 我同意这有点语义上的争论,但我不同意措辞。Python中的每个对象都有类型,只是Python默认不强制静态类型。而且说Python没有类型概念是不正确的。你可以使用 isinstance 检查类型,如果类型不支持操作,你会得到 TypeError 异常。

        2. 第一段是正确的,但第二段显然是错误的:打开 Python 解释器,输入 ‘a’ + 1,你会得到

          Traceback (most recent call last):
            File “<python-input-0>”, line 1, in <module>
              ‘a’ + 1
              ~~~~^~~
          TypeError: can only concatenate str (not “int”) to str
          

          Python 运行时知道类型是什么,并在某些情况下会抛出 TypeError

          可以想象一种在编译为字节码之前检查类型的 Python,但鉴于类型检查长期以来都是可选的,而且仍然有大量未类型化或类型错误的库在使用,这种过渡可能会相当痛苦。也许可以将这个想法放在 Python 4 的议程上?

      2. 真的不行吗?你可以使用 uv 或 poetry 来管理依赖项

        Deno 可以在同一运行时中导入同一模块的两个不同版本,因为它将模块视为具有独立依赖关系图的完全隔离的 URL。

        这意味着我可以在一个文件中导入 foo@1.0.0,在另一个文件中导入 foo@2.0.0,而不会发生冲突。

        这意味着大语言模型(LLM)无需解决 Python 中出现的复杂的同级依赖冲突。

        在解释型垃圾回收语言中,借用检查器毫无意义。即使有借用检查器,我确信大语言模型(LLMs)也会难以应对。

        关键是,与没有借用检查器相比,大语言模型(LLMs)在借用检查器的指导下可以更轻松地生成正确的并行化代码。这是根据经验得出的结论。

        如果您需要正式验证的语言,那么您可能不会使用大语言模型(LLMs)这样的易出错工具。

        这并不是我需要什么的问题,而是大语言模型(LLM)需要什么来编写正确的代码的问题。正式方法对大语言模型(LLM)生成的代码更有效。

        不确定这与 Python 有什么关系,它是一种通用语言。我确信,如果你向大语言模型(LLM)请求网络内容,它会给你 Js 代码。

        我是在谈论 Python,所以这与 Python 有关系。

  14. 偏好是可接受的,只要它指向正确的选择。说真的,那些在这里抱怨 Python 的人从未处理过遗留的 C++ 或 Fortran 代码。

    我看到有些人只是对好的事物感到厌倦,因为他们不知道更好的选择。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

你也许感兴趣的: