Codex论文翻译
Abstract
我们引入了 Codex,这是一种在 GitHub 上公开的代码上进行微调的 GPT 语言模型,并研究了它的 Python 代码编写能力。 Codex 的独特生产版本为 GitHub Copilot 提供支持。在我们发布的新评估集 HumanEval 上,用于衡量从文档字符串合成程序的功能正确性,我们的模型解决了 28.8% 的问题,而 GPT-3 解决了 0%,GPT-J 解决了 11.4%。此外,我们发现从模型中重复采样是一种令人惊讶的有效策略,可以为困难的提示提供可行的解决方案。使用这种方法,我们可以通过每个问题 100 个样本解决 70.2% 的问题。对我们的模型的仔细研究揭示了它的局限性,包括描述长操作链的文档字符串以及将操作绑定到变量的困难。最后,我们讨论部署强大的代码生成技术的潜在更广泛影响,涵盖安全性、安保性和经济性。
1.简介
可扩展的序列预测模型(Graves,2014;Vaswani et al. ,2017;Child et al. ,2019)已成为许多领域的生成和表示学习的通用方法,包括自然语言处理(Mikolov et al. ,2013;Sutskever et al. ,2014; Dai & Le,2015;Peters et al. ,2018;Radford et al. ,2018;Devlin et al. ,2018),计算机视觉(Van Oord et al. ,2016;Menick & Kalchbrenner,2018;Chen et al. ,2020;Bao et al. ,2021),音频和语音处理(Oord Etfgall ,2016; 2018; Dhariwal et al. ,2020; Baevski et al. ,2020年),生物学(Alley Etfgall ,2019; Rives et al. ,2021),甚至跨多种模态(Das et al., 2017; Lu et al., 2019; Ramesh et al., 2021; Zellers et al., 2021)。最近,由于大型数据集中代码的存在(Husain et al.,2019;Gao et al. , 2020 )和在这些数据集上训练的语言模型的编程能力(Wang & Komatsuzaki,2021)。流行的语言建模目标,如掩码语言建模(Devlin et al. ,2018)和跨度预测(Raffel et al. ,2020)也已被改编用于训练其编程对应物 CodeBERT(Feng et al. ,2020)和 PyMT5(Clement et al. ,2020)。
同样,我们对 GPT-3 的早期调查(Brown et al. ,2020)表明它可以从 Python 文档字符串生成简单的程序。虽然还很初级,但这种功能很令人兴奋,因为 GPT-3 没有经过明确的代码生成训练。鉴于大型语言模型在其他模式中取得的巨大成功以及大量公开可用的代码,我们假设一种名为 Codex 的专门 GPT 模型可以在各种编码任务上表现出色。本文介绍了几个早期的 Codex 模型,其后代为 GitHub Copilot 和 OpenAI API 中的 Codex 模型提供支持。
图 1. 我们的模型在 HumanEval 数据集上的通过率与模型大小的函数关系。 当为每个问题生成单个样本时,GPT-12B 没有解决任何问题,但 Codex(对代码进行微调)解决了 28.8% 的问题,Codex-S(对正确实现的独立函数进行了进一步微调)解决了 37.7% % 的问题。 从这里开始,可以通过为每个问题生成 100 个样本并选择平均对数概率最高的样本(已解决 44.5%)或选择通过单元测试的样本(已解决 77.5%)来实现进一步的收益。 所有样本均在温度 0.8 下生成。
在这项工作中,我们专注于从文档字符串生成独立的Python函数的任务,并通过单元测试自动评估代码示例的正确性。这与自然语言生成形成鲜明对比,自然语言生成通常通过启发式或人类评估者来评估样本。为了准确地对我们的模型进行基准测试,我们通过单元测试创建了包含 164 个原始编程问题的数据集。这些问题评估语言理解、算法和简单数学,其中一些问题相当于简单的软件面试问题。我们在 https://www.github.com/openai/human-eval 上发布了这些数据以及评估框架。
为了解决测试集中的问题,我们从模型中生成多个样本,并检查其中是否有任何样本通过单元测试。仅使用单个样本,12B 参数 Codex 就解决了其中 28.8% 的问题,而 300M 参数 Codex 则解决了其中 13.2% 的问题。相比之下,6B 参数 GPT-J(Wang & Komatsuzaki,2021)在同一数据集上实现了 11.4%,而所有 GPT 模型都实现了接近 0%。为了提高模型在从文档字符串合成函数的任务中的性能,我们在独立的、正确实现的函数上对 Codex 进行了微调。由此产生的模型 Codex-S 通过单个样本解决了 37.7% 的问题。图 2 显示了我们的数据集中不同难度的问题,以及正确的模型生成的解决方案。
图 2. HumanEval 数据集中的三个示例问题,其中 Codex-12B 中的单个样本通过单元测试的概率为 0.9、0.17 和 0.005。 提供给模型的提示以白色背景显示,模型生成的成功完成以黄色背景显示。 尽管不能保证问题的新颖性,但所有问题都是手写的,而不是从现有来源以编程方式复制的。 随机问题和样本可以在附录B中找到。
现实世界的编程任务通常涉及方法的迭代和错误修复,这可以通过从我们的模型中生成许多样本并选择一个通过所有单元测试的样本来近似。在 100 个样本内,Codex-S 能够为 77.5% 的问题生成至少一个正确的函数。这一结果表明,可以通过启发式排名来选择准确的代码样本,而不是完全评估每个样本,后者在部署中可能是不可能或不切实际的。事实上,我们发现平均对数概率最高的样本通过了 44.5% 问题的单元测试。
最后,我们讨论了这些 Codex 模型以及更广泛的日益强大的代码生成模型的局限性和潜在的更广泛影响。
2.评估框架
在本节中,我们将讨论评估框架的细节。我们首先定义 指标,并解释其与基于标准匹配的指标相比的优势。接下来,我们描述手写问题的数据集,称为“HumanEval”,我们创建它是为了对我们的模型进行基准测试。最后,我们讨论用于安全执行模型生成的代码的沙盒(sandbox)环境。
2.1.功能正确性
代码的生成模型主要通过将样本与参考解决方案进行匹配来进行基准测试,其中匹配可以是精确的或模糊的(如 BLEU 分数)。然而,最近的工作已经暴露出基于匹配的代码指标的缺陷。例如,Ren et al. (2020) 发现 BLEU 在捕获特定于代码的语义特征方面存在问题,并建议对分数进行一些语义修改。
更根本的是,基于匹配的指标无法解释功能上与参考解决方案等效的程序的庞大而复杂的空间。因此,最近在无监督代码翻译(Lachaux et al. ,2020)和伪代码到代码翻译(Kulal et al. ,2019)方面的工作已经转向功能正确性,其中如果样本通过了一组单元测试,则被认为是正确的。我们认为这个指标也应该应用于文档字符串条件代码生成。
也许评估函数正确性最令人信服的原因是它是人类开发人员用来判断代码的。称为测试驱动开发的框架规定,在开始任何实施之前,将软件需求转换为测试用例,成功与否由通过测试的程序来定义。虽然很少有组织采用完整的测试驱动开发,但新代码的集成通常依赖于创建和通过单元测试。
Kulal et al. (2019) 使用 指标评估功能正确性,其中每个问题生成 k 个代码样本,如果任何样本通过单元测试,则认为问题已解决,并报告已解决问题的总分数。然而,以这种方式计算 可能会产生很大的方差。相反,为了评估 ,我们为每个任务生成 n ≥ k 样本(在本文中,我们使用 n = 200 且 k ≤ 100),计算通过单元测试的正确样本 c ≤ n 的数量,并计算无偏样本估计量(estimator)
直接计算该估计量会导致非常大的数字和数值不稳定。在图 3 中,我们包含一个数值稳定的 numpy 实现,它可以简化表达式并逐项评估乘积。人们可能会想用 来估计 ,其中 是 的经验估计,但我们在附录中表明它是有偏差的
图 3. 用于计算 无偏估计的数值稳定脚本。
随后,我们通过证明我们的模型生成的功能不等价的程序(保证在某些输入上与参考解决方案不一致)通常具有比功能相当的程序更高的 BLEU 分数,证明 BLEU 分数可能不是功能正确性的可靠指标。
2.2. HumanEval:手写评估集
我们评估了一组 164 个手写编程问题的功能正确性,我们将其称为 HumanEval 数据集。每个问题都包含函数签名、文档字符串、主体和多个单元测试,每个问题平均有 7.7 次测试。这些任务必须是手写的,这一点很重要,因为我们的模型是在 GitHub 的很大一部分上进行训练的,其中已经包含了来自各种来源的问题的解决方案。例如,有十多个公共存储库包含 Codeforces 问题的解决方案,这些解决方案构成了最近提出的 APPS 数据集的一部分(Hendrycks et al. ,2021)。
HumanEval 数据集中的编程任务评估语言理解、推理、算法和简单数学。我们发布了 HumanEval 数据集,以便其他人可以评估功能正确性并衡量其模型解决问题的能力。该数据集可以在 https://www.github.com/openai/human-eval 找到。
2.3.用于执行生成程序的沙盒
由于公开程序的意图未知,并且生成的程序通常不正确,因此执行这些程序会带来安全风险。事实上,众所周知,GitHub 包含改变或更改其环境的恶意程序(Rokon et al. ,2020)。
因此,我们开发了一个沙盒环境来安全地运行不受信任的程序来进行单元测试。我们的目标是防止这些程序修改、持久化、访问主机或网络上的敏感资源或窃取数据。由于 OpenAI 的训练基础设施是基于 Kubernetes 和云服务构建的,因此我们设计了沙盒来解决这些环境的局限性,同时保持其惯用的使用模式。
我们选择 gVisor 容器运行时(Lacasse,2018)作为主要的主机保护组件。由于像 Docker 这样的容器运行时可以与容器共享主机资源,因此恶意容器可能会危害主机。 gVisor 通过模拟其资源在主机及其容器之间引入安全边界来保护主机。网络相邻的主机和服务受到基于 eBPF 的防火墙规则的保护,这些规则阻止入站和出站连接,实验控制所需的连接除外。
3.代码微调
我们对代码上包含多达 12B 参数的 GPT 模型进行微调以生成 Codex。与 GPT 相比,Codex 在 HumanEval 数据集上显示出非凡的性能。事实上,如果我们为每个问题生成并评估 100 个样本,并选择一个通过单元测试的样本,Codex 就能够解决 HumanEval 中的大部分问题。当预算仅限于每个问题进行一次评估时,使用 Codex 生成多个样本并选择平均对数概率最高的样本可带来显着收益。
3.1.数据采集
我们的训练数据集于 2020 年 5 月从 GitHub 上托管的 5400 万个公共软件存储库中收集,其中包含 179 GB 的独特 Python 文件,大小不到 1 MB。我们过滤掉了可能自动生成、平均行长度大于 100、最大行长度大于 1000 或包含一小部分字母数字字符的文件。过滤后,我们的最终数据集总计 159 GB。
3.2.方法
由于 Codex 是根据自然语言提示进行评估的,我们假设从 GPT-3(Brown et al.,2020)模型系列进行微调将是有益的,该模型系列已经包含强大的自然语言表示。 令人惊讶的是,当从预训练的语言模型开始时,我们没有观察到改进,可能是因为微调数据集太大。 尽管如此,从 GPT 微调的模型收敛得更快,因此我们将这种策略应用于所有后续实验。
我们使用与相应 GPT 模型相同的学习率来训练 Codex,具有 175 步线性预热和余弦学习率衰减。 我们使用 Adam 优化器训练总共 1000 亿个token, ,权重衰减系数为 0.1。
为了最大限度地利用 GPT 的文本表示,我们的代码词法分析器基于 GPT-3 文本标记生成器。由于 GitHub 代码中单词的分布与自然文本的分布不同,因此此分词器对于表示代码不是很有效。效率低下的最大根源在于对空白进行编码,因此我们添加了一组额外的标记来表示不同长度的空白。这使我们能够使用大约少 30% 的标记来表示代码。
为了计算 ,我们将每个 HumanEval 问题组装成一个由标头、签名和文档字符串组成的提示,如图 2 所示。我们从 Codex 中采样token,直到遇到以下停止序列之一:‘\nclass’、‘\ndef’、‘\n#’、‘\nif’ or ‘\nprint’,因为模型将继续生成其他函数或语句。我们使用核采样(Holtzman et al. ,2020),顶部 p = 0.95 进行本工作中的所有采样评估。
3.3.结果
在图 4 中,我们根据 Codex 模型大小绘制了保留验证集上的测试损失。我们发现,正如语言模型测试损失遵循模型大小的幂律一样(Kaplan et al. ,2020),代码微调后的测试损失遵循类似的幂律,函数形式为 (N 5.92×107 ) −0.13,其中 N 是模型中非嵌入参数的数量。
图 4. 在我们的 Python GitHub 代码语料库的保留部分上测量的模型交叉熵测试损失。 即使在代码微调之后,GPT-3 中观察到的性能随模型大小的平滑幂律缩放似乎仍然成立。
在评估 时,针对特定的 k 值优化采样温度非常重要。在图 5 中,我们绘制了 与样本数量 k 和采样温度的关系图。我们发现较高的温度对于较大的 k 是最佳的,因为生成的样本集具有更高的多样性,并且度量仅奖励模型是否生成任何正确的解决方案。
图 5. 在顶部面板中,我们针对不同温度设置绘制了 pass@k 与样本数量 (k) 的关系。 当样本数量较多时,温度越高越好,这可能是由于样本多样性增加。 在底部面板中,我们绘制了每个 k 的最佳温度设置,这是通过顶部面板的上部外壳获得的。
特别是,对于 679M 参数模型,pass@1 的最佳温度为 ,pass@100 的最佳温度为 。在这些温度下,我们发现 pass@1 和 pass@100 作为模型尺寸的函数平滑缩放(图 6)。
图 6. 使用 pass@1 和 pass@100 的最佳温度 0.2 和 0.8,我们将这两个指标绘制为模型大小的函数。 性能看起来像对数参数中的 sigmoid 曲线一样平稳地扩展。
也可以解释为评估 个样本中的最佳样本的结果,其中最佳样本是由具有单元测试先验知识的oracle挑选的。从实际角度来看,我们还对必须从 个样本中选择单个样本而无需访问oracle的设置感兴趣。例如,当模型用作用户提供提示的自动完成工具时,我们没有单元测试,但只想返回单个完成给用户进行评估,以免让他们不知所措。
受语言建模中类似工作的启发,我们发现选择具有最高平均token对数概率的样本优于评估随机样本,而根据总和对数概率选择样本的性能可能比随机选取稍差。图 7 展示了将这些启发法应用于 Codex-12B 样本(温度为 0.8)的好处。
图 7. 我们可以生成多个样本但仅评估一个样本的设置中的模型性能。 通过选择具有最高平均对数概率(红色)或具有最高反向翻译分数(橙色)的解决方案,我们可以比随机选择样本做得更好,如第 2 节中所述。 5. 蓝线代表使用具有单元测试先验知识的oracle获得的理论上的最佳性能。
最后,我们根据参考解决方案计算所有 Codex-12B HumanEval 样本(温度为 0.8)的 BLEU 分数。对于每个问题,当我们绘制正确和错误解决方案的 BLEU 分数分布时,我们注意到显着的重叠(图 8)。由于不正确的解决方案在功能上肯定与参考解决方案不等价,因此我们得出的结论是,BLEU 分数的提高可能并不表明实践中功能正确率的提高。
图 8. 对于 HumanEval 中的 4 个随机任务,Codex-12B 中正确(蓝色)和错误(绿色)解决方案的 BLEU 得分概率密度。 请注意,分布不能完全分离,这表明针对 BLEU 分数进行优化并不等同于针对功能正确性进行优化。
3.4.相关模型和系统的对比分析
最近与 Codex 本质相似的两部作品是 GPT-Neo(Black et al. ,2021)和 GPT-J(Wang & Komatsuzaki,2021),它们在 The Pile(Gao et al. ,2020)上进行训练,The Pile 是一个包含来自各种文本的数据集。源代码以及 8% 的 GitHub 代码。更广泛的研究社区发现,这些模型在定性编程评估方面优于现有的 GPT 系统(Woolf,2021)。
我们使用 HumanEval 数据集证实了这些发现,显示 GPT-Neo 在 上达到了 6.4%,在 上达到了 21.3%,而同等大小的 GPT 模型在这两个指标上都达到了接近 0%。我们看到了功能上的显着进步,GPT-Neo-2.7B 大致相当于 Codex-85M(参数少了 30 倍)。同样,GPT-J-6B 实现了 11.6% 和 27.7% ,大致相当于 Codex-300M(参数少了 20 倍)。通过率是通过对 GPT-Neo 在温度 0.2、0.4 和 0.8 下进行评估以及对 GPT-J 在温度 0.2 和 0.8 下进行评估来获取最佳结果而获得的。多个模型尺寸的详细结果可在表 1 中找到。
表 1. HumanEval 的 Codex、GPT-Neo 和 TabNine 评估。 我们发现 GPT-J pass@1 的性能介于 Codex-85M 和 Codex300M 之间。
最后,我们将 Codex 与 Tabnine(领先的代码自动完成系统)中最大的免费模型进行基准测试,该模型实现了 2.6% (在 T = 0.4 时)和 7.6% (在 T = 0.8 时)。这大致相当于我们套件(suite)中最小的型号之一 Codex-12M。
3.5. APPS 数据集的结果
最近,Hendrycks et al. (2021) 引入了 APPS 数据集来衡量语言模型的编码挑战能力。 APPS 数据集包含 5000 个编码问题的训练示例和 5000 个测试示例,每个示例都有一组单元测试,对于训练数据,还有一组正确的解决方案。与主要 Codex 训练数据相反,大多数 APPS 测试问题不是被表述为单功能综合任务,而是作为全程序综合,从 stdin 读取输入并将输出打印到 stdout。
在介绍 APPS 的论文中,作者对一些语言模型进行了基准测试并报告了两个指标:模型找到正确解决方案的问题的百分比(称为“严格准确性”)和通过单元测试的百分比,即使解决方案是不正确的。报告后一个度量只是为了减少测量的方差,因为第一个度量的结果非常低。我们避免使用这个指标,只关注“严格的准确性”,并且与前面的部分一样,我们报告各种 的 数字(表 2)。我们还考虑了两个在编程竞赛中众所周知的额外因素:
表 2. 上面引用的 APPS 论文中经过微调的 GPT-Neo 数字。 对于 Codex-12B,在某些测试中超时的通过程序数量在括号中。 我们使用温度 0.6 进行采样,以覆盖 中的所有 ,因此原始 结果可以通过较低的温度得到改善。
-
在编码竞赛和 APPS 数据集中,任务描述中包含 3 个输入/输出示例。我们通过从模型中采样 1000 个解决方案并仅筛选出通过这 3 个单元测试的解决方案(如果存在此类解决方案)来利用这一点。然后,我们计算这个过滤集中的通过率,并将其称为“filtered ”。未经过滤的结果以原始 形式呈现。
-
在编码竞赛和 Codex 结果中经常出现这样的情况:找到正确的解决方案,但算法效率不够高,无法被视为通过。虽然这在竞赛中是不可接受的,但我们还报告了 Codex 生成的解决方案的数量,这些解决方案在任何单元测试中都没有失败,但在其中一些测试中超时。我们在评估中使用 3 秒的超时。
为了弥补 Codex 未在 APPS 上进行微调的事实,我们将任务描述中的单个输入/输出示例附加到文档字符串作为格式提示。我们在表 2 中将此设置表示为“1-shot”,并发现 Codex12B 评估的 1-shot 实现了与在 APPS 上微调的 GPT-Neo 模型相当的性能。与我们之前的发现一致,每个任务生成和评估多达 1000 个样本会带来巨大好处,但对于更困难的问题,解决方案通常效率不够高,无法通过时间限制。最后,评估通过每个问题的 3 个公共单元测试的第一个样本会产生比原始 pass@100 个样本更高的性能。
4.监督微调
除了独立函数之外,GitHub 上的 Python 代码还包含类实现、配置文件、脚本,甚至用于存储数据的文件。这段代码似乎与从文档字符串合成函数无关,我们假设分布不匹配会降低 HumanEval 的性能。
为了使 Codex 适应感兴趣任务的分布,我们从正确实现的独立函数构建了一组训练问题,并使用它们进行额外的监督微调。我们描述了两种收集这些示例的方法:从竞争性编程网站和从持续集成的存储库。我们将监督微调模型称为 Codex-S,并表明它们在不同模型大小上产生一致的增益。
4.1.竞争性编程中的问题
编程竞赛和面试准备网站使用隐藏单元测试来自动判断提交内容的功能正确性。这些问题是独立的,带有编写良好的问题陈述,并且通常具有出色的测试覆盖率。此外,这些问题测试了算法推理在广泛的核心技能和困难方面的能力。
我们从几个流行的编程竞赛和面试准备网站收集了问题陈述、函数签名和解决方案。然后,我们使用问题描述作为文档字符串,将它们组装成类似于 HumanEval 的编程任务。由于完整的测试套件通常是隐藏的,因此我们从问题陈述中找到的示例创建了单元测试,或者通过提交不正确的解决方案提取了额外的测试用例。我们总共通过这种方式策划了 10,000 个问题。
4.2.持续集成的问题
接下来,我们整理了开源项目中的编程问题。利用 sys.setprofile,我们能够跟踪和收集集成测试期间调用的所有函数的输入和输出。然后可以使用该数据为功能创建单元测试。
采用持续集成 (CI) 的项目是跟踪的理想选择。我们按照 CI 配置文件中的命令(其中包含构建和测试命令)来设置虚拟环境、安装依赖项并运行集成测试。
我们考虑使用 travis 和 tox 作为 CI 框架的 GitHub 存储库,因为它们是两种最流行的 CI 工具。我们还使用了 python 包索引 (PyPI) 中 pip 包的公开源代码。
由于这些项目包含不受信任的代码,因此在上述沙盒环境中运行集成测试非常重要。
虽然有数百万个潜在函数可以解决问题,但我们只收集了大约 40,000 个,因为并非所有函数都接受输入并返回输出。即使这样做,大多数在运行时捕获的对象也无法在沙盒外进行腌制(pickled)和恢复(restored),除非安装了项目。
由于我们的跟踪方法为所有调用的函数生成输入和输出,甚至项目导入的内置函数和库调用也变成了问题。因此,跟踪函数往往是命令行实用程序的构建块。为了出色地完成这些任务,模型不需要了解高级算法和数据结构。相反,它需要能够遵循说明来实现文档字符串中指定的功能。因此,追踪补充了编码竞争问题的谜题本质,并拓宽了任务的分配。
4.3.过滤问题
在前面的部分中,我们介绍了两种用于自动创建训练问题的方法。但目前尚不清楚如何控制质量。有些提示未指定所实现的功能,在这种情况下,一个完全有效的解决方案可能会受到单元测试的错误惩罚。有些问题是有状态的,后续执行可能会导致不同的结果。
为了解决这些问题,我们使用 Codex-12B 为每个策划的问题生成 100 个样本。如果没有样本通过单元测试,我们会认为该任务不明确或太困难,并将其过滤掉。我们多次重新运行此验证,以消除状态或非确定性问题。
4.4.方法
我们针对这些训练问题对 Codex 进行微调,以生成一组“监督微调”模型,我们将其称为 Codex-S。为了从训练问题中生成示例,我们将问题组装成如图 2 所示的格式。如果批次中存在不同长度的提示,我们会将较短的提示左填充到最长提示的长度,以便参考解决方案在上下文中排列。
我们进行训练以最小化参考解决方案的负对数似然,并掩盖提示中任何标记的损失。我们使用与微调 Codex 一样大的学习率 1/10 进行训练,但遵循相同的学习率计划,并训练直到验证损失达到稳定水平(少于 10B token)。
4.5.结果
与 Codex 一样,我们首先计算在 的情况下评估 的最佳温度。我们发现 Codex-S 对于所有 更喜欢稍高的温度,这可能反映了 Codex-S 比Codex捕获的范围更窄的事实。我们使用 来计算 ,使用 来计算 。
图 9. 最佳采样温度与 Codex 和 Codex-S 生成的样本数量的函数关系。 对于任何特定的 k 值,Codex-S 通常需要更高的温度,这可能是为了补偿它模拟较窄分布的事实。
接下来,我们将 Codex-S 与 和 上的 Codex 进行比较。在整个模型尺寸上,Codex-S 在 pass@1 上比相应的 Codex 平均领先 6.5 个百分点,在 pass@100 上平均领先 15.1 个百分点。
图 10. 根据第 3 节中提出的指标将 Codex-S 与 Codex 进行比较。Codex-S 在 pass@1 和 pass@100 上的参数效率高出一两个数量级,并且对 Codex-S 产量进行对数概率样本排序 与 Codex 的随机抽样相比,具有类似的优势。
我们还绘制了 Codex-S-12B 的不同样本选择启发法与 Codex-12B 的相同启发法的性能。当按平均对数概率对 1 到 100 个样本进行排名时,随机排名的平均效益为 11.6 个百分点,比 Codex 的相应效益高出 2 个百分点以上。
5.文档字符串生成
使用 Codex 可以从文档字符串生成代码,因为代码通常跟在文档字符串之后,但引导 Codex 从代码生成文档字符串并不容易。尽管如此,出于安全原因,我们还是有动力创建一个文档字符串编写模型,因为这样的模型可以用来描述生成代码背后的意图。使用上一节中描述的训练问题,我们可以轻松创建用于代码条件文档字符串生成的训练数据集。
具体来说,对于每个训练问题,我们通过连接函数签名、参考解决方案和文档字符串来组装训练示例。正如我们通过最小化参考解的负对数似然来训练 Codex-S 一样,我们通过最小化文档字符串的负对数似然来训练文档字符串生成模型 Codex-D。
当我们对代码生成模型进行基准测试时,我们在 HumanEval 数据集上测量 ,其中正确性是通过通过一组单元测试来定义的。但是,没有类似的方法来自动评估文档字符串样本。因此,我们手动对示例文档字符串进行评分,如果文档字符串唯一且准确地指定了代码主体,则认为该文档字符串是正确的。由于此过程非常耗时,我们仅对每个问题的 10 个样本进行评分,总共 1640 个问题,来自 Codex-D-12B,温度为 0.8。
Codex-D 通常会生成不正确的单元测试以及文档字符串,但我们在评分过程中会忽略它们。但是,当模型只是将代码主体复制到文档字符串中时,我们并不认为文档字符串是正确的。我们观察到的最常见的失败模式是文档字符串模型遗漏了一个重要的细节(例如“答案必须是小数点后两位”),或者它对函数名称过度控制并发明了与函数体无关的问题。
如表 3 所示,Codex-D 的通过率较低,但与相同温度下 Codex-S 的相应通过率相当。对于哪个方向应该产生更高的通过率,我们没有强有力的假设。虽然生成文档字符串可能更宽容,因为自然语言语法不如代码语法严格,但我们数据集中的文档字符串可能质量较低,因为开发人员倾向于花更少的时间来编写文档字符串。事实上,我们的模型会生成诸如“我刚刚在网上找到这个函数”和“这个测试编写不正确,这不是我的解决方案”之类的文档字符串。
表 3. 我们的文档字符串生成模型 Codex-D 的通过率,由于缺乏真实的自动评估,该模型通过对每个任务的 10 个样本进行手工评分来进行评估。 我们发现与 Codex-S 相比,通过率相似但较低。
最后,通过文档字符串模型,我们还有另一种方法可以从一组 k 个样本中选择单个样本。我们可以选择最大化反向翻译目标 P(真实文档字符串|生成样本)的样本,而不是像前两节中研究的那样选择具有最佳平均对数概率的样本,其中 P 使用 Codex-D 进行评估。不幸的是,在图 7 中,我们表明通过反向翻译对样本进行排序的效果低于平均对数概率排序,尽管它优于随机排序。这种启发式似乎也很快就会过拟合。
6.局限性
虽然 Codex 能够为大多数 HumanEval 问题提供正确的解决方案,但我们发现它有许多局限性。
首先,Codex 的训练样本效率不高。我们的训练数据集包含 GitHub 上公开可用的 Python 代码的很大一部分,总共有数亿行代码。即使经验丰富的开发人员在其职业生涯中也不会遇到如此数量的代码。事实上,完成计算机科学入门课程的优秀学生预计能够解决比 Codex-12B 更大比例的问题。
接下来,我们探讨 Codex 可能失败或显示反直觉行为的提示。虽然评估代码生成已得到充分研究(Xu et al. ,2021;Helmuth & Spector,2015;Pantridge et al. ,2017),但许多现有的度量指标是在严格指定的、受限的问题实例中度量性能(例如,FlashFill 中的字符串操作(Gulwani,2011) )。因此,我们开发了一套定性指标来衡量代码生成模型的能力,同时控制规范的复杂性和抽象级别(附录D)。应用这个框架,我们发现 Codex 可以推荐语法不正确或未定义的代码,并且可以调用未定义或超出代码库范围的函数、变量和属性。此外,Codex 很难解析越来越长、越来越高级别或系统级别的规范。
为了具体说明随着文档字符串长度增加模型性能下降,我们创建了一个由 13 个基本构建块组装而成的综合问题数据集,每个构建块都以确定性方式修改输入字符串。示例构建块是“将字符串转换为小写”或“从字符串中删除每三个字符”(完整列表在附录 C 中描述)。我们发现,随着文档字符串中链式构建块数量的增加,模型性能呈指数下降。这种行为对于人类程序员来说是不寻常的,如果他们能够对长度为 2 的链执行此操作,那么他们应该能够正确地为任意长度的链实现程序。
图 11. Codex-12B 样本的通过率与综合生成的文档字符串中链接组件数量的关系。 每增加一个组件,通过率就会下降大约 2-3 倍。
此外,正如其他模态中的文本条件(text-conditional)生成模型(Ramesh et al. ,2021)难以将属性绑定到对象一样,Codex 在将操作绑定到变量时可能会出错,特别是当文档字符串中的操作和变量数量很大时。例如,在以下提示中,Codex-12B 不会递减变量 w,也无法返回所有数字的乘积。
对Codex有限的系统级综合能力的了解有助于我们评估以生成能力使用它的潜在危险,以及此类系统可能产生的更广泛的社会影响。
7.更广泛的影响和危害分析
Codex 具有在多种方面发挥作用的潜力。例如,它可以帮助用户使用新的代码库,减少经验丰富的编码人员的上下文切换,使非程序员能够编写规范并拥有 Codex 草案实现,并有助于教育和探索。然而,Codex 也带来了重大的安全挑战,并不总是生成符合用户意图的代码,并且有可能被滥用。
为了更好地了解在生成能力方面使用 Codex 的一些危害,我们进行了危害分析,重点是识别可能造成伤害的风险因素(Leveson,2019)。我们概述了以下几个风险领域的一些主要发现。
虽然我们关于代码生成系统潜在社会影响的一些发现是通过负责任地部署面向生产的 Codex 模型(源自本文中描述的面向研究的 Codex 模型)的工作得出的,但本节无意提供任何特定产品安全特性的完整说明。除非另有说明,我们的分析将基于本文描述的模型的具体属性。我们分享这一分析是因为相信其中一些分析可以推广到更广泛的代码生成系统,并鼓励将执行详细影响分析作为主要机器学习研究项目的一部分。
请注意,通过在本节中主要关注风险,我们并不意味着暗示我们预计此类技术的影响将是net-negative;相反,这里的风险值得特别关注,因为它们可能很微妙或需要刻意努力才能解决,而我们预计从大多数用户和受影响的利益相关者的角度来看,好处会更加明显和“自动(automatic)”。
7.1.过度依赖
在实践中使用代码生成模型相关的主要风险之一是过度依赖生成的输出。由于上述限制以及下文所述的对齐问题,Codex 可能会建议表面上看起来正确但实际上并未执行用户预期任务的解决方案。这尤其会影响新手程序员,并且根据具体情况可能会产生重大的安全影响。我们在附录 G 中讨论了一个相关问题,即代码生成模型可能会建议不安全的代码。由于这些原因,为了安全使用 Codex 等代码生成系统,需要人工监督和警惕。
我们在下面有关风险缓解的小节中指出了几种提高安全性的直接方法,尽管我们认为过度依赖尤其值得行业和学术界进一步探讨。虽然从概念上讲,向用户提供文档以提醒他们模型的局限性很简单,但为了确定如何在一系列用户体验级别、UI 设计和任务的实践中可靠地确保警惕,有必要进行实证研究。研究人员应该考虑的一项挑战是,随着能力的提高,防范“自动化偏见(automation bias)”可能会变得越来越困难。
7.2.未对齐
与在下一个token预测目标上训练的其他大型语言模型一样,Codex 将生成与其训练分布尽可能相似的代码。这样做的后果之一是,此类模型可能会做一些对用户没有帮助的事情,尽管它们有能力提供更多帮助(参见图 12)。例如,如果用户的代码中有一些细微的错误,Codex 可能会“故意”建议表面上看起来不错但实际上是不正确的代码。
图 12. 当提示包含细微错误时,Codex 往往会生成比其能力更差的代码。 当提示还包含编写正确代码的说明时,这种情况仍然存在。 这种差距随着模型尺寸的增加而增加。
这是对齐失败——模型与用户的意图不一致。通俗地说,如果我们希望系统执行某些任务 X,并且它“有能力”执行 X 但“选择”不执行,则该系统是未对齐的。相反,如果一个系统因为没有能力而未能做到X,那么这个系统就不是失准的;而是因为它没有能力做到这一点。它只是无能。请参阅附录 E 了解更多详细信息,包括更精确的对齐定义。
研究未对齐非常重要,因为随着我们系统功能的增强,这个问题可能会变得更糟,而不是更好。例如,图 12 中示例的模型大小缩放趋势表明,如果数据、参数和训练时间按比例放大,偏差可能会持续存在,甚至会变得更糟。
虽然我们预计像这样的未对齐行为不太可能在当前模型中造成重大损害,但随着模型功能的增强,它可能会变得更加危险且更难以消除。一个经过用户批准训练的功能强大但严重未对齐的模型可能会产生混淆的代码,即使经过仔细检查,这些代码对用户来说看起来不错,但实际上却做了一些不受欢迎的甚至有害的事情。
7.3.偏见和代表性
与在互联网数据上训练的其他语言模型的情况相似(Bender et al., 2021; Blodgett et al., 2020; Abid et al., 2021; Brown et al., 2020),我们发现 Codex 可能会以产生种族主义、诽谤性和其他有害输出(如代码注释)的方式进行提示,值得采取干预措施,例如下面有关风险缓解的小节中讨论的干预措施。 我们还发现,代码生成模型除了有问题的自然语言之外,还引发了进一步的偏见和表征问题:Codex 可以生成具有反映性别、种族、情感、阶级、名称结构和其他特征刻板印象的结构的代码。 特别是在用户可能过度依赖 Codex 或在没有首先考虑项目设计的情况下使用它的情况下,这个问题可能会产生重大的安全影响,从而进一步阻止过度依赖。 我们在附录 F 中进一步讨论偏见和代表性问题。对生成的输出、文档和其他干预措施进行过滤或调整可能有助于减轻这些风险。
7.4.经济和劳动力市场影响
代码生成和相关功能可能对经济和劳动力市场产生多种影响。虽然 Codex 在其当前的能力水平上可能会通过提高程序员的生产力而在一定程度上降低生产软件的成本,但这种效果的大小可能会受到工程师不会花一整天时间编写代码的事实的限制(O*NET,2021)。其他重要任务包括与同事协商、编写设计规范以及升级现有软件堆栈。 我们还发现 Codex 以不同的速率导入软件包,这可能使某些软件包作者比其他软件包作者更有利,特别是如果程序员和工程师开始依赖 Codex 的建议。从长远来看,随着能力的提高,此类技术对软件相关劳动力市场以及更广泛的经济的影响可能会更加显着。需要对代码生成能力的影响和适当的响应进行更多的研究。我们在附录 H 中更详细地讨论了经济和劳动力市场的影响。
7.5。安全影响
Codex可能会对安全形势产生各种影响。由于 Codex 可能会生成易受攻击或未对齐的代码,在缺乏适当预防措施的情况下,合格的操作员应在执行或信任其之前对其进行审查。未来的代码生成模型可能能够经过训练,生成比普通开发人员更安全的代码,尽管这还远未确定。
Codex 也可能被滥用来帮助网络犯罪。尽管这值得关注,但根据我们的测试,我们认为,在目前的能力水平上,Codex 模型并没有实质性地降低恶意软件开发的进入门槛。我们预计更强大的代码生成模型将带来未来的进步,因此有必要进一步研究缓解措施并继续研究模型能力。
Codex 等系统的不确定性可能会导致更高级的恶意软件。这种非确定性使得创建完成相同任务的不同软件变得更加容易。虽然软件多样性有时可以帮助防御者,但它给传统的恶意软件检测和防病毒系统带来了独特的挑战,这些系统依赖于先前采样的二进制文件的指纹识别和签名匹配。例如,功能更强大的代码生成模型可能会改进生成多态恶意软件的技术。我们相信,应用程序安全和模型部署策略(包括访问速率限制和滥用监控)可以在短期内管理这种威胁;然而,随着功能更强大的模型的开发,这些缓解措施的功效可能会呈次线性扩展。
与大型语言模型类似,Codex 模型可以学习训练数据中存在的模式(Carlini et al. ,2021)。源代码中存在的敏感数据很容易被模型预测。由于 Codex 是在公共存储库上进行训练的,因此我们认为训练数据中存在的任何敏感数据都已被泄露。同样,公共数据通常应被视为不可信,因为之前的工作(Goldblum et al. ,2021;Schuster et al. ,2020)发现攻击者可能能够破坏训练数据以在运行时触发特定的模型行为。我们在附录 G 中进一步讨论安全影响。
7.6。环境影响
与其他大型生成模型一样,Codex 具有来自训练和推理的能力足迹(Schwartz et al. ,2019;Bender et al. ,2021;Patterson et al. ,2021)。 GPT-3-12B 的原始训练消耗了数百 petaflop/sday 的计算量,而对其进行微调以创建 Codex-12B 则消耗了类似的计算量。该训练是在一个平台 (Azure) 上进行的,该平台购买碳信用额并采购大量可再生能源,从而减少其碳足迹。计算消耗在更广泛的供应链中也会产生成本,这些成本可能非常集中在某些地区。查看更多从全球和长期来看,如果使用重要的推理来解决具有挑战性的问题,代码生成的计算需求可能会比 Codex 的训练大得多。
7.7.法律影响
有几个与生成的代码相关的法律考虑因素。首先,人工智能系统在互联网数据(例如公共 GitHub 存储库)上的训练此前已被确定为“合理使用”的一个实例(O’Keefe et al. ,2019)。
我们的初步研究还发现,Codex 模型很少生成与训练数据内容相同的代码。在一项检查与训练数据中的代码片段匹配的代码生成频率的研究中,此类发生率 < 0.1%(Ziegler,2021)。在这些罕见的情况下,生成的代码由编程语言中的常见表达式或约定组成,这些表达式或约定在训练数据中反复出现。我们发现,在某种程度上,生成的代码看起来与训练数据相同,这是由于模型中的预测权重而不是特定代码的保留和复制。
生成的代码还响应用户的输入并进行定制,并且用户保留对生成的代码的编辑和接受的完全控制。这可以使代码生成类似于作为其他作者工具(例如,文档编辑器)的功能而存在的自动建议或自动完成功能,从某种意义上说,完成的工作仍然被视为作者的。
我们对负责任和安全的人工智能的承诺包括持续关注代码生成系统更广泛的知识产权影响。我们打算继续与政策制定者和专家就这些问题进行接触,以便此类系统的用户最终能够充满信心地部署它们。
7.8.风险缓解
最后,鉴于上述情况,应开发、使用像 Codex 这样的模型,并仔细探索其功能,着眼于最大限度地发挥其积极的社会影响,并最大限度地减少其使用可能造成的有意或无意的伤害。上下文方法对于有效的危险分析和缓解至关重要,尽管在任何代码生成模型的部署中都需要考虑一些大类的缓解措施。
仔细的文档和用户界面设计、代码审查要求和/或内容控制(例如,输出过滤)可能有助于减少与过度依赖以及攻击性内容或不安全代码生成相关的危害。在作为服务提供的模型的背景下(例如,通过 API),用户审查、用例限制、监控和/或速率限制等策略也可能有助于减少与恶意使用相关的危害或阻止其使用在模型不太适合的高风险领域。
附录 E、F、G 和 H 提供了本节中描述的风险的更多详细信息,并概述了其他缓解和研究机会。
8.相关工作
深度学习的复兴带动了程序学习领域的强劲进步。神经程序学习的两种流行方法是程序归纳和程序合成。
在程序归纳中,模型直接从潜在程序表示生成程序输出。学习执行(Zaremba & Sutskever,2014)证明模型可以执行简单的任务,例如加法和记忆。后来的程序归纳尝试结合了基于现代计算设备的归纳偏差,例如神经图灵机(Graves et al. ,2014)、内存网络(Weston et al. ,2015;Sukhbaatar et al. ,2015)、神经 GPU(Kaiser & Sutskever,2015) )和可微神经计算机(Graves et al. ,2016)。最近的方法,如神经程序解释器(Reed & de Freitas,2016;Shin et al. ,2018;Pierrot et al. ,2021)和通用Transformer(Dehghani et al. ,2019)发现重现(recurrence)是程序归纳中的一个有用组成部分。
在程序综合中,模型通常根据自然语言规范显式生成程序。最流行的经典方法之一使用概率上下文无关语法(PCFG)来生成程序的抽象语法树(AST)。 Maddison & Tarlow (2014) 通过学习用于条件子节点扩展的状态向量来改进此设置。后来,Allamanis et al. (2015) 将这一想法应用于文本到代码检索,而 Yin & Neubig (2017) 将其应用于文本条件代码生成。 Code2seq(Alon et al. ,2018)发现 AST 也可以用于代码到文本的生成。
程序也可以在不通过 AST 表示的情况下进行合成。 Hindle et al. (2012) 研究了代码的 n-gram 语言模型,发现代码比自然语言更可预测。潜在预测器网络(Ling et al. ,2016)表明,在允许将卡牌属性复制到代码中的潜在模式的帮助下,字符级语言模型可以生成用于在在线竞技场中实现 Magic the Gathering 卡牌的工作代码。 DeepCoder(Balog et al. ,2017)训练了一个模型来预测源代码中出现的函数,该模型可用于指导程序搜索。
随着大型自然语言模型的成功(Devlin et al. ,2018;Radford et al. ,2019;Liu et al. ,2019;Raffel et al. ,2020;Brown et al. ,2020),大规模 Transformer 也被应用于程序合成。 CodeBERT(Feng et al. ,2020)在与函数配对的文档字符串上训练 BERT 目标,并在代码搜索上获得了很好的结果。 PyMT5(Clement et al. ,2020)在精神上与我们的工作相似,并使用 T5 目标来训练一个可以在 {signature, docstring, body} 的非重叠子集之间进行转换的系统。
我们使用功能正确性来对我们的模型进行基准测试,并通过更多采样观察到该指标的改进。 SPoC(Kulal et al. ,2019)考虑了使用固定编译预算从伪代码生成功能正确的代码的问题,这类似于我们的 指标。 TransCoder(Lachaux et al. ,2020)训练了一个系统以无监督的方式在编程语言之间进行翻译,并且还观察到功能正确性比 BLEU 分数更好地捕捉了其模型的功能。事实上,ContraCode(Jain et al. ,2020)利用大量功能正确的程序来训练对比代码模型,从而提高了模型在类型推断等任务上的性能。最后,RobustFill(Devlin et al. ,2017)观察到,找到与输入示例一致的程序的最佳方法是通过集束搜索来合成多个样本。
用于对神经编程系统进行基准测试的两个早期特定领域数据集是 FlashFill(Gulwani,2011;Gulwani et al. ,2012)和 Hearthstone(Ling et al. ,2016),尽管社区已经趋向于更广泛和更困难的数据集。 Barone 和 Sennrich (2017) 提出了一个大型训练和评估数据集,其中包含 Python 声明、文档字符串和从 GitHub 上抓取的正文。 CodeSearchNet 挑战赛(Husain et al. ,2019)使用来自多种流行编程语言的数据,从 GitHub 构建了一个更大的语料库。最近,CodeXGLUE(Lu et al. ,2021)利用最近提出的 CodeBLEU 指标(Ren et al. ,2020)汇总了多个编程基准。与我们的评估工作最相关的是 APPS(Hendrycks et al. ,2021)基准,用于根据竞争性编程网站 Codeforces 的问题来衡量功能正确性。
最后,我们注意到编码是一项广泛的活动,它涉及的不仅仅是从文档字符串合成代码。 Tufano et al. (2020) 使用 Transformer 为性能优于商业产品的代码生成单元测试。 Aye et al. (2021) 为 Facebook 构建了一个内部自动完成工具,并发现对接受的用户完成训练可以提高系统性能。开发还需要定位和修复错误。早期的工作使用静态或动态代码分析(Agrawal et al. ,1995;Korel & Rilling,1997)、学习关联规则(Jeffrey et al. ,2009)和遗传编程(Goues et al. ,2012)来调试错误代码。这些方法依赖于针对测试套件的运行,不仅可以评估建议的正确性,还可以暴露执行跟踪或搜索解决方案中的问题。最近的工作(Tufano et al. ,2019;Drain et al. ,2021)将错误修复视为从有错误的程序到正确程序的神经机器翻译。然而,这些作品使用了与参考的精确匹配而不是功能正确性,引用 Qi et al. (2015) 的发现,即 (Goues et al. , 2012) 中通过基因搜索提出的大多数解决方案都通过了弱测试套件,删除了以下功能:失败的。人类开发人员经常编写覆盖范围有限但有针对性的测试套件,但这并不总是对算法有效,这凸显了评估程序正确性的挑战。
9.结论
我们研究了是否可以训练大型语言模型以从自然语言文档字符串生成功能正确的代码体。通过对 GitHub 上的代码进行 GPT 微调,我们发现我们的模型在人类编写的问题数据集上表现出了强大的性能,其难度级别与简单的面试问题相当。可以通过在与评估集更相似的分布上进行训练以及从模型中生成多个样本来提高模型性能。我们还发现,训练模型来完成从代码体生成文档字符串的反向任务很简单,并且这些模型的性能概况相似。最后,我们扩展了代码生成模型的更广泛影响,并讨论了模型的局限性,发现了重大的改进空间。