为什么大语言模型不适合编码?

为什么大语言模型不适合编码?

在过去的一年里,大型语言模型(LLM)凭借其自然语言理解能力展现出了惊人的能力。这些先进的模型不仅重新定义了自然语言处理的标准,而且还填充了应用程序和服务。

人们对使用大语言模型进行编码的兴趣迅速增长,一些公司努力将自然语言处理转化为代码理解和生成。这项任务已经强调了使用大语言模型进行编码时尚未解决的几个挑战。尽管存在这些障碍,这一趋势还是带动了人工智能代码生成器产品的发展。

虽然它在某些情况下很有帮助,但通常很难生成高效且高质量的代码。在本文中,我们将探讨大语言模型本质上不擅长“开箱即用”编码的三个原因:分词器、应用于代码时上下文窗口的复杂性以及训练本身的性质。

确定需要改进的关键领域对于将大语言模型转变为更有效的编码助手至关重要!

1.LLM 分词器

LLM 分词器负责将用户输入的自然语言文本转换为 LLM 可以理解的数字格式。

分词器通过将原始文本分解为标记来处理原始文本。标记可以是整个单词、单词的一部分(子词)或单个字符,具体取决于标记器的设计和任务的要求。

由于 LLM 对数字数据进行操作,因此每个标记都会被赋予一个 ID,该 ID 取决于 LLM 词汇表。然后,每个 ID 进一步与 LLM 潜在高维空间中的向量相关联。为了完成最后的映射,大语言模型使用学习嵌入,这些嵌入在训练过程中进行微调,并捕获数据中的复杂关系和细微差别。

如果你有兴趣尝试不同的 LLM 分词器并了解它们的性能,那么文章《释放 ChatGPT 分词器》非常适合你!

使用最初为文本生成训练的通用大语言模型进行编码的一个主要挑战在于自然文本中的单词分布与编码中的单词分布之间的差异。自然语言拥有丰富的词汇和多种多样的语法,反映了各种各样的想法、情感和细微差别。相比之下,编程代码具有特定于每种编程语言的更严格的词汇表,并遵循严格的语法。

此外,代码经常包含重复的结构和模式,例如循环、条件和函数调用,这些在自然语言中不太常见。逻辑结构与自然文本中观察到的主题和文体模式显着不同。

此外,代码中的轻微拼写错误或语法错误也可能导致无法正常工作。由于其概率性质,大语言模型很难生成高精度的代码。

使用通用分词器进行编码时效率低下的最大原因之一在于处理空白,特别是代码缩进。与空格的语义意义较小的自然语言不同,编程语言中的缩进对于定义结构至关重要。

传统的分词器经常忽视缩进的结构重要性,将其视为纯粹的空格,这会导致基本信息丢失、歧义和代码解释错误。

为了说明这一点,我们可以使用 Python 库tiktoken并使用不同的标记器通过文档字符串对简单的函数定义进行编码:

正如我们所观察到的,Codex 和 GPT4 模型背后的分词器保留了缩进,而 GPT 文本分词器则将缩进分解为多个空格。

2.上下文窗口

有限的上下文窗口仍然是大语言模型的一个常见问题,当使用大语言模型进行编码时,这个问题变得尤其明显。

上下文窗口是指模型在处理过程中的任何给定时间可以考虑的标记数量。这种限制影响了大语言模型有效理解和生成代码的能力,因为模型无法看到程序的整体情况。

尽管文本生成模型也受到有限上下文窗口的影响,但由于各种原因,编码对此限制更加敏感:

  1. 复杂的代码依赖性:编程通常涉及复杂的依赖性,其中一段代码的功能或行为取决于文本中可能不直接相邻的其他部分。函数可能会调用其他地方定义的其他函数,并且变量可能会在程序的不同部分中使用。有限的上下文窗口意味着模型可能无法访问准确理解或预测下一段代码所需的所有相关信息。
  2. 长期逻辑结构:软件开发经常需要维护长期逻辑结构,例如嵌套条件、循环和函数调用,这些结构可能跨越几行甚至文件。具有有限上下文窗口的大语言模型很难保持这些结构的一致性,这可能会导致生成的代码中出现语法错误或逻辑不一致。

一般来说,有限的上下文窗口使得生成与整个代码库一致的代码具有挑战性。在自然语言生成中,有限上下文窗口通常通过使用摘要来管理,这不是编码任务的选项。

3.培训的性质

一般大语言模型经过训练,可以在给定标记序列的情况下预测下一个标记。这被称为从左到右生成,这使得它们在代码生成等任务中的功能不那么强大,右侧的内容也应该被考虑来完成编码任务,例如代码填充(建议)、修复错误、添加注释、重命名变量、文档字符串生成、返回类型预测。

代码填充涉及生成适合现有代码的代码片段,就像 GitHub Copilot 所做的那样。这需要从插入点之前(左)和之后(右)理解上下文。尽管 GPT 模型具有单向性质,但其处理此类任务的能力可归因于以下几个关键因素和技术:

  • 代码数据集上的自适应微调:通过在代码数据集上微调 GPT 模型,这些模型可以学习特定于编程语言的模式、风格和结构。此过程包括接触各种编码任务,包括代码完成和填充,这有助于模型学习根据前面的上下文预测适当的代码片段。
  • 即时工程:向模型呈现任务的方式会显着影响其性能。对于代码填充,提示可以包含周围的代码作为上下文,本质上是重新制定任务以使其与模型的单向功能更加兼容。

尽管这些技术确实提高了大语言模型在编码方面的表现,但要从根源上解决问题,我们需要改变培训策略。

采用双向训练的模型的一个例子是 InCoder [1],它经过训练以最大化代码语料库的可能性。它利用了填充以任意左右上下文为条件的代码块的概念。

在训练过程中,代码块被屏蔽,模型的任务是根据屏蔽部分两侧提供的上下文填充这些块。这种方法意味着 InCoder 接触到了必须理解和生成代码片段的场景并从中学习,不仅要根据前面的上下文(左),还要考虑间隙后面的内容(右)。因此,InCoder 的训练不仅可以根据先前的标记来预测下一个标记,还可以预测屏蔽块中丢失的标记,从而提供对代码结构和逻辑的更全面的理解。

InCoder训练过程中的代码屏蔽示例

后来的模型(例如 CodeCompose [2])也遵循这种方法,同时修改掩码的不同方面。

在本文中,我们探讨了三个重大挑战,这些挑战使得 ChatGPT 等大语言模型在“开箱即用”编码方面效率较低。这些挑战包括从标记化等初始处理步骤,到有限上下文窗口等架构限制,再到从左到右标记生成的固有训练。如果你想了解更多关于ChatGPT的相关内容,可以阅读以下这些文章:
在新研究的支持下,从ChatGPT获得深入响应的9种技巧
ChatGPT又蠢又没用?请提出正确的问题!
ChatGPT越来越傻了吗?我们一起聊聊“AI Drift”
掌握ChatGPT的反向提示

虽然 GPT 模型在较新的迭代中编码越来越好,但它们是否直接解决上述问题并不明显。正如我们所看到的,他们通常采用传统的编码器-解码器变换器架构,并在代码库上进行预训练,以获得类人编码模式的稳健先验。此外,随后使用较小的数据集进行特定于任务的微调可以增强其在编码任务中的性能。

尽管微调技术和附加组件(例如 ChatGPT 代码解释器)的集成可以产生有希望的结果,但一些学术研究人员主张从根本上解决这些挑战。这种方法旨在超越传统的大语言模型,从仅仅依赖最大似然估计到采用性能感知的代码生成策略。

感谢阅读!你还可以订阅我们的YouTube频道,观看大量大数据行业相关公开课:https://www.youtube.com/channel/UCa8NLpvi70mHVsW4J_x9OeQ;在LinkedIn上关注我们,扩展你的人际网络!https://www.linkedin.com/company/dataapplab/

原文作者:Andrea Valenzuela
翻译作者:诗彤
美工编辑:过儿
校对审稿:Jason
原文链接:https://towardsdatascience.com/llms-coding-chatgpt-python-artificial-intelligence-4ea7a7bbdd93