原文:
towardsdatascience.com/llms-coding-software-development-artificial-intelligence-68f195bb2ad3
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6bdf5bb5eaa3bc463054d27af6866c00.png
自制图像。
在发布本系列的第一篇文章“为什么 LLMs 不适合编码”后,我在社交媒体上收到了一些评论,例如:
“我正在用 ChatGPT 进行编码,它工作得非常完美。”
“你错了。大型语言模型是有用的编码助手。”
我对这种反应感到惊讶,因为这篇文章系列的目的是不是要阻止任何人使用大型语言模型(LLMs)进行编码,而是要确定需要改进的关键领域,以将 LLMs 转化为更有效的编码助手。
虽然 ChatGPT 等 LLM 在某些情况下可能有所帮助,但它们通常生成的代码可能在语法上是正确的,但不是最优的,甚至可能在功能上不正确。
在上一篇文章中,我们讨论了分词器、应用于代码时上下文窗口的复杂性以及训练本身的性质如何影响这些模型在编码任务中的性能。
在这篇文章中,我们将更深入地探讨这些模型用于编码任务所经历的训练类型,以及为什么LLMs 天生不擅长“开箱即用”的编码:保持与最新库和代码功能同步的挑战。
编码模型的训练
由 LLM 驱动的编码助手已经成为现实。GitHub Copilot是今天最知名的产品之一,在我们的开发环境中提供代码补全和聊天助手。
正如开发者所声称的,“GitHub Copilot 使用概率确定来生成建议”。仔细查看他们的文档提供了更多关于产品工作原理的细节:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0c2995b22bb9ea1939663056b8b24dca.png
自制 GitHub Copilot 官方网站 FAQ 部分的截图。GitHub Copilot 网站。
也就是说,无论我们在哪里放置光标,我们都会得到一个建议。
但等等。
通用 LLMs 的训练是为了预测给定一系列标记的下一个标记,这意味着只有光标前的行被用于推理(从左到右生成)。
有双向模型使用左右上下文进行预测。然而,在实践中,ChatGPT 这样的单向模型使用了一些变通方法,以便在代码中有效地使用。
准备基础 LLM 进行编码任务的常见技术是在代码数据集上执行自适应微调,例如在将模型专门化到自然语言中的具体主题时。DeepMind 的 Yujia Li 在文章“Competition-Level Code Generation with AlphaCode”中描述了这一过程:
<…/Images/541a4d44612c8e61c5a1619640e0ed1a.png>
[source] Li, Y., Choi, D., Chung, J., Kushman, N., Schrittwieser, J., Leblond, R., … & Vinyals, O. (2022).Competition-level code generation with AlphaCode. Science, 378(6624), 1092–1097.
如上图(A)部分所示,用于编码的通用 LLM 是从在自然语言上训练的基础模型开始的,并在代码库上进行预训练。例如,给定上下文print(", 模型被训练来预测补全hello)` 使用从左到右的生成。
然后,模型使用一系列编码问题和它们的解决方案进行微调,如图(B)所示。因此,给定一个编码问题,模型被训练来生成解决方案。
通过在代码数据集上预训练大型语言模型(LLM),这些模型可以学习特定于编程语言的模式、风格和结构。此外,微调数据集应包括各种编码任务,如代码补全和填充,这将帮助模型学会根据前面的上下文预测适当的代码片段。
一旦模型训练完成,确保模型了解正确上下文的另一种策略是在推理过程中将其作为提示的一部分传递。
例如,对于代码填充,提示可以包括周围的代码作为上下文,有效地将任务重新表述为与模型的单向能力相一致。
作为编码助手的 LLM 的挑战
在本系列的 第一篇文章中,我们探讨了大型语言模型(LLM)在生成代码方面的局限性以及这些局限性产生的原因。
然而,有一个重要的局限性我们没有提到:保持与最新包和功能同步。
在软件开发中,这对于生成有效和安全的代码至关重要,但对于 LLM 来说实际上是非常具有挑战性的,原因有两个:
静态知识库:GitHub Copilot,作为任何 LLM,都是在特定时间点对数据——代码和文档——的快照进行训练的。因此,它可能不知道在它们最后一次训练更新之后发布的软件库和框架中的最新功能、已弃用功能或安全补丁。
版本特定性:软件开发严重依赖于特定版本的库和框架。由于 LLM 没有实时更新,它们可能提供过时的代码片段,导致兼容性问题或过时方法的使用。
接口,如 API,可能会频繁更改,新功能可能会添加或旧功能可能会删除。基于旧数据的 LLM 可能不会意识到新的安全风险,这可能导致代码被破坏。
此外,在现代软件开发中管理依赖项是复杂的,如果 LLM 缺乏最新的兼容性和版本信息,可能不会提供最佳建议。
每个问题都有一个解决方案
集成开发环境(IDE)和其他编码工具可以集成实时更新并获取最新的文档或库版本,类似于 ChatGPT-4 的 Bing 浏览功能,以扩展其知识库。
就我所知,GitHub Copilot 的聊天功能具有浏览能力。然而,正如讨论的那样,LLM 依赖于其预训练模型来生成响应,GitHub Copilot 在其文档中也对此进行了警告:
GitHub Copilot 提供由 OpenAI 从数十亿行开源代码构建的模型建议。因此,GitHub Copilot 的训练集可能包含不安全的编码模式、错误或对过时 API 或习语的引用。当 GitHub Copilot 基于这些训练数据生成建议时,这些建议也可能包含不希望的模式。
当使用 LLM 作为编码助手时,我们应该意识到动态咨询外部数据库以获取软件更新和文档的能力可能有限。
最后的想法
尽管大型语言模型在生成代码的骨干作为起点和帮助处理语法和基本概念方面可能很有用,但我们应该意识到它们的局限性,并避免过度依赖这些产品。
每个编码项目可能需要高度特定的解决方案,以适应特定的业务规则或用户需求——这些细微差别对于 LLM 来说非常难以捕捉,因为它们被训练来重现训练数据中发现的通用模式。
然而,我们可以采用针对代码定制的提示工程策略来引导 LLM 朝着我们期望的输出方向。如果您感兴趣,可以在以下文章中了解更多信息:
编码任务的提示工程
⚠ 警告 ⚠
编写能够正确运行的代码是一回事;编写针对性能优化的代码则是另一回事。
认识到LLMs 可能并不总是提供最有效的算法或为特定硬件或软件环境优化代码是很重要的。此外,在执行 AI 生成的代码时始终考虑安全性至关重要。
最后,大型语言模型本质上依赖于最大似然估计,而高效的软件开发需要性能感知的代码生成策略。
那就结束了!非常感谢阅读!
我希望这篇文章能帮助您在使用 LLMs 进行编码时!
您也可以订阅我的通讯,以便及时获取新内容。
特别是,如果您对关于大型语言模型和 ChatGPT 的文章感兴趣:
为什么 LLMs 不适合编码
ChatGPT moderation API:输入/输出控制
ChatGPT API 的自定义内存