导语
- 会议:ICLR 2023
- 链接:arxiv.org/abs/2207.05…
1 简介
现存的代码生成模型要么直接从作为训练数据提供的输入-输出对中学习,或从交织在一起的自然语言和代码的自然语料库中隐式地学习输入和输出之间的映射。然而,所有这些工作都假设所有的库和函数调用都在训练数据中;在测试时,经过训练的模型只需要生成可见的库和函数调用。然而,新的函数和库一直在被引入,甚至一个可见的函数调用也可能有训练数据中没有使用的参数。因此,现有的模型本质上不能泛化以生成这种看不见的用法。
相比之下,人类开发者在面对从未见过或者使用过的库、函数时擅长查阅代码的手册或文档,从而快速掌握其用法。受到这个过程的启发,本文提出了DocPrompting方法,其整体流程如图1所示:
- 首先,使用一个文档检索器对输入的自然语言意图进行检索,得到相关的文档集合{d1,d2,d3};
- 接着,一个代码生成器利用这些文档作为prompt,生成最终的代码c
文档池充当外部数据存储,可以频繁地使用新内容更新(例如,新发布库的文档),而无需重新训练任何模型组件。通过这种方式,DocPrompt可以利用新添加的文档,它可以生成包含不可见和未使用的函数和库的代码。
实验结果表明,DocPrompt在两个NL2Code数据集任务(tldr和CoNaLa)上取得了最先进的表现。
2 通过阅读文档来生成代码
尽管模型可以使用文档D的整个集合,但D中只有少数文档与任何特定意图相关。因此,首先要让模型选择一部分相关文档子集Dn,它们在给定自然语言n时是潜在相关的,并在生成c时参考这个子集。
整个DocPrompting模型分为两部分:一个检索器R和一个生成器G。R用于计算每个文档di和用户的自然语言n之间的相似度分数s(di, n),并返回前Top-K个得分最高的文档。在给定这些文档和用户自然语言意图n后,生成器G输出最终的代码。如图1所示。
3 DocPrompting的实际应用方式
3.1 检索器的建立
对于检索器,总共有两种类型:
- Sparse Retrievers:即利用文档的稀疏特征,如BM25、TF-IDF等,具体作者使用ElasticSearch进行部署。
- Dense Retrievers:即利用模型编码得到文档的稠密向量表示,这里作者使用类似于SimCSE模型的方式(启发式方法来的标签);
3.2 生成器的建立
本文实验了GPT-Neo-125M、GPT-Neo-1.3B、CodeX作为生成器,检索得到的文档拼接后作为prompt输入给模型。同时,作者也尝试了T5和CodeT5,由于他们的输入长度限制(512,实际上也没有这个限制?),作者采用了Fusion-in-Decoder策略(参考zhuanlan.zhihu.com/p/564043932)。
4 实验建立
4.1 Shell脚本
作者整理了一个bash脚本的数据集名为tldr,其示例如图2所示,共引入了4个评价指标:
- command name accuracy (CMD Acc) ,即衡量前面的命令是否匹配上
- exact match (EM) ,即是否精准匹配
- token-level F1;
- character-level BLEU (charBLEU)
4.2 Python编程
作者重新整理了CoNaLa数据集,保证验证、测试中的函数在训练集中从未出现过。评价指标采用BLEU、Recall。
5 实验结果
5.1 Shell脚本结果
可以看到,通过DocPrompting的加入,各种模型性能都有了很大的提升。
表2展示了作者对比检索文档还是检索样例的结果,可以看到,检索文档的提升远大于检索样例。
5.2 Python编程结果
如下图所示,通过DocPrompting的加入,各种模型性能都有了很大的提升。
作者还比较了执行准确率的结果(图3),可以看到docprompt不仅提高了所生成代码表面形式的质量,而且还提高了其执行正确性。
6 分析
6.1 为什么阅读文档有助于生成更准确的代码?
作者认为主要原因之一是文档简化了NL意图和代码之间的映射,因为文档包含了NL描述和函数签名。为此,作者计算了NL意图与其对应代码片段之间的n-gram重叠(NL←→code),以及NL意图与ground truth文档及其代码片段之间的重叠((NL+docs)←→code)。如图4所示,添加文档显著增加了n-gram之间的重叠,例如,将tldr中的单格重叠从12%提高到68%。也就是说,检索文档有助于生成准确代码的原因之一是,文档弥合了“意图术语”和“代码术语”之间的鸿沟。
6.2 消融实验
表4显示了不同检索器及其设置之间的比较。首先,BM25的性能在不同的数据集之间有所不同。作者认为这种差异源于这些数据集创建的方式:tldr意图是基于现有的Bash命令和手册编写的;而CoNaLa的例子是从StackOverflow的帖子中挖掘出来的,在那里,用户提出的问题没有上下文或有限制。因此,CoNaLa中的NL意图需要与文档更好的语义对齐,从而受益于密集检索器。
其次,在目标编程语言上预训练的检索器通常更强。例如,在CoNaLa中,用Python预训练的CodeT5是一个更好的现成检索器,也是一个比RoBERTa更好的优化检索器,RoBERTa主要是对文本进行预训练的。相比之下,tldr基于Bash, CodeT5和RoBERTa都没有明确地在Bash上进行预训练。因此,tldr主要受益于BM25和RoBERTa,而不是CodeT5作为检索器。
最后,使用对文档池的弱监督来训练检索器(第3.1节)极大地改善了检索器(没看懂)。
6.3 案例分析
7 相关工作
略
8 总结
本文提出了DocPrompting,这是一种通过检索相关文档来生成代码的简单而有效的方法。DocPrompt在两个任务的编程语言和多个基准模型中持续改进NL2Code模型。这些结果为NL2Code生成开辟了一个有前景的方向。作者认为,通过对长文档的结构化特性进行更巧妙的编码,并使用检索器和生成器的联合训练,结果可以进一步改进,这有望避免级联错误。