一、CodeGen[2022]

  1. 程序合成 program synthesis 的目标是使编码过程自动化,并生成一个满足用户指定意图的计算机程序。成功的program synthesis不仅可以提高有经验的程序员的生产力,还可以让更多人了解编程。

    在实现program synthesis时,有两个关键的挑战:搜索空间的不可控性、正确指定用户意图的困难。

    • 为了使得搜索空间有表达能力,人们需要一个大的搜索空间,这给高效搜索带来了挑战。以前的工作利用 domain-specific language 来限制搜索空间,然而,这限制了 synthesized program 的适用性。相反,通用编程语言(如 CPython )虽然适用性更广,但是引入了一个更大的搜索空间。为了在巨大的 program space 中搜索,论文 《CodeGen: An Open Large Language Model for Code with Multi-Turn Program Synthesis》 将任务公式化为语言建模 language modeling :给定前序 tokens 的条件下,学习 next token 的条件分布,并利用 Transformer 和大规模的自监督预训练。这种方法在各种模式中都取得了成功。同样,之前的工作也为 programming language understanding 开发了预训练好的语言模型。

    • 为了成功地实现program synthesis,用户必须采用一些手段将他们的意图传达给模型,如逻辑表达式logical expression (指定程序的输入和输出之间的逻辑关系)、伪代码pseudo-codeinput-output examples 、或以自然语言方式的口头规范。

      • 一方面,完整的正式的规范 specification 受益于用户意图的精确规范 exact specification ,但可能需要领域的专业知识、以及用户的努力来将意图转化为这样的形式。

      • 另一方面,仅仅基于 input-output examples 的规范,其成本较低,但可能对意图的规范不足 under-specify ,导致不准确的解决方案。

      以前的工作得益于各种方法(及其组合)作为 program synthesis model 的输入,包括伪代码、程序的一部分及其文档、或带有 input-output examples 的自然语言段落。然而,论文 《CodeGen: An Open Large Language Model for Code with Multi-Turn Program Synthesis》 认为:真正用户友好的意图的形式是自然语言文本。

    为了克服这些挑战,论文 《CodeGen: An Open Large Language Model for Code with Multi-Turn Program Synthesis》 提出了一种多轮program synthesismulti-turn program synthesis )方法:用户通过逐步提供自然语言的规范与合成系统 synthesis system 进行交流,同时从系统中接收以 synthesized subprogram 为形式的响应。这样,用户与系统一起在 multiple steps 中完成 program 。以下两点考虑是这种方法的动机:

    • 首先,作者推测,将一个潜在的长而复杂的规范分解成多个步骤,会使模型更容易理解,从而改善program synthesis。在 multi-turn 方法中,模型可以专注于与一个子程序相关的规范,而避免艰难地追踪子程序之间复杂的依赖关系。这除了方便指定用户意图外,还有效地减少了搜索空间。事实上,作者的推测在论文的实验中得到了证实,通过 multi-turn 方法合成的程序的质量更高。

    • 其次, code 表现出一种弱模式 weak pattern:自然语言和编程语言交错。这种模式可以被利用。这种模式是由程序员用注释comment 来解释程序的 functionality 而形成的。在 language modeling objective 下,作者假设交错模式为模型提供了一个监督信号,用于在 multiple turn 中生成给定的自然语言描述的程序。这个信号是高度噪音的或微弱的,因为只有一部分数据会表现出这样的模式,注释可能是不准确的、或没有信息 uninformative 的,有些注释甚至可能被放置在不相关的位置。然而,扩大模型和数据规模可能会克服这种弱监督,使模型能够发展出 multi-turn program synthesis 的能力。这使得用户的意图可以用 multiple turn 来表达,也就是说,意图可以被分解并逐一实现,而每个 turn 可以很容易地用自然语言表达。

    在这项工作中,论文开发了一个 multi-turn programming benchmark 来为 multi-turn program synthesis 衡量模型的能力。为了解决 benchmark 中的问题,一个模型需要在多个步骤中合成一个程序,其中用户用自然语言指定每个 turn 的意图。如下图所示,该模型合成了一个程序来提取电子邮件地址的用户名。benchmark 的性能是通过专家编写的测试用例的通过率来衡量的。据作者所知,这是第一个 multi-turn program synthesis benchmark ,它允许对 multi-turn program synthesis 进行定量分析。随着大型语言模型中 multi-turn program synthesis 的涌现 emergence ,作者相信这个 benchmark 将促进未来的program synthesis 研究。

    下图中,pi 为用户提供的 promptsi 为模型返回的 subprogram 。最终的结果是所有的 subprogram 组合在一起而形成的。因此,用户提供的 prompt 对于最终结果是至关重要的,这是优点也是缺点:优点是用户可以对代码生成过程进行更精细的控制,缺点是需要用户具备一定程度的专业知识(需要知道怎么描述程序的每一步)。

    ①为整个过程的示意图,②为模型生成的过程(以之前的 promptssubprograms 为条件),③为最终结果。

    论文贡献: 论文与最近同时进行的、使用 single-turn user intent specification 的工作的基本想法一致,即用采用语言模型来执行 program synthesis 。此外:

    • 论文研究了在 scaling law 下自回归模型中的 multi-turn program synthesis

    • 论文利用这种能力引入了一个 multi-turn program synthesis 范式。

    • 论文用一个新的 multi-turn programming benchmarkhttps://github.com/salesforce/CodeGen/tree/main/benchmark)对其特性进行定量研究。

    • 论文将开源 model checkpointhttps://github.com/salesforce/CodeGen)和自定义训练库:JAXFORMERhttps://github.com/salesforce/jaxformer)。对于 program synthesis 来说,目前还没有可以与 Codex 竞争的、开源的大型模型。这阻碍了 program synthesis 的发展,因为训练这些模型所需的昂贵的计算资源只有数量有限的机构可以获得。作者的开源贡献允许广泛的研究人员研究和改善这些模型,这可能大大促进研究进展。

  2. 相关工作:

    • Program Synthesis:虽然 program synthesis 有很长的历史,但两个固有的挑战仍未解决:program space 非常棘手、难以准确表达用户意图。

      • 之前的大量研究试图通过探索随机搜索技术、自上而下的演绎搜索等方法来解决第一个问题,然而,这些方法的可扩展性仍然是有限的。

      • 用户的意图可以用各种方法来表达:正式的逻辑规范、input-output examples 、自然语言描述。完整的和正式的规范需要太多的努力,而非正式的如 input-output examples 往往对问题的规范不足。

      由于大规模的模型和数据,well-learned 的条件分布和语言理解能力可以有效地解决这两个挑战。

      有几项工作研究将对话意图转换为programmable representation ,如 SQLdataflow graph 。我们提出的 benchmark 要求生成 Python ,这是更通用、更复杂的。

    • Large Language ModelTransformer 通过注意力机制捕捉序列的元素之间的依赖关系,并且具有高度的可扩展性。它已被成功地应用于自然语言处理、计算机视觉、以及许多其他领域。之前的工作,如 CuBERTCodeBERTPyMT5CodeT5,已经将 Model(即,Transformer )应用于 code understanding ,但这些大多侧重于代码检索、分类和程序修复。

      最近和同时进行的几项工作探索了使用大型语言模型进行 program synthesis 及其有效性。然而他们关注的是在 single turn 中生成代码,而我们提议将 specification 分解为 multiple turns ,并证明这对提高合成质量非常有效。值得指出的是,《Program synthesis with large language models》探索了在 multiple iterations 中完善代码的方法,但它本质上是一种 single-turn 方法,因为每个 single turn 都会产生一个完整的程序。

      intermediate informationprompting 预训练好的语言模型以提高任务性能已经引起了人们的兴趣。我们提出的 MTPB 也允许模型利用 past turns 作为上下文。

    • Benchmarks for Program Synthesis:为了定量分析 program synthesis模型,人们已经提出了几个具有不同输入形式的 benchmark 。流行的输入形式包括:同一行中的前序代码 preceding code、伪代码、docstring 和函数签名、problem description 。在大多数 case 中,仅仅向模型提供直接相关的输入信息。

      相反,一些以前的工作提出了一些 benchmark,这些 benchmark 衡量在给定目标程序周围的 program context (如变量、其它函数、前序的代码块/文本块)的条件下,生成程序的能力,主要的重点是生成目标程序本身。

      我们提出一个新的 benchmark ,要求通过 multi-turn prompts逐步生成子程序。

1.1 模型训练

  1. 为了在 scaling law 下评估 multi-turn programmingemergence ,我们采用了标准的 transformer-based 的自回归语言模型,但是做了一些改变:

    • 模型参数规模:350M, 2.7B, 6.1B, 16.1B

    • 训练语料库中 programming languagetoken 的数量。

    为了扩大训练规模,我们开发了一个自定义的库 JAXFORMER 用于 TPU-v4 hardware ,并将以开源方式发布,包括训练好的模型权重。

  2. 数据集:CODEGEN 模型系列是在 THEPILE, BIGQUERY, BIGPYTHON 这三个数据集上按顺序地训练的。

    • THEPILE :自然语言数据集 THEPILE 是由 《The pile: An 800gb dataset of diverse text for language modeling》 为语言建模而收集的 825.18 GB 英语文本语料库(MIT license )。该数据集由 22 个不同的、高质量的子集构成,其中一个子集是从 GitHub repositoriesrepositorystar 数量超过 100 )中收集的编程语言数据,该子集占数据集的 7.6% 。由于 THEPILE 的大部分内容是英文文本,因此得到的模型被称为 natural language CODEGEN modelCODEGEN-NL)。

    • BIGQUERY:多语言数据集 BIGQUERY 是谷歌公开的 BigQuery 数据集的一个子集,它由多种编程语言的代码(在 open-source license 下)组成。对于多语言训练,我们选择了以下 6种编程语言:C, C++, Go, Java, JavaScript, Python 。因此,我们把在 BIGQUERY 上训练的模型称为 multi-lingual CODEGEN modelCODEGEN-MULTI)。

    • BIGPYTHON:单语言数据集 BIGPYTHON 包含大量的编程语言 Python 的数据。我们在 202110 月收集了来自 GitHub 的公开的、非个人的信息,这些信息由 Python code (在 open-source license 下)组成。因此,我们将在 BIGPYTHON 上训练的模型称为 mono-lingual CODEGEN modelCODEGEN-MONO)。

    预处理过程如下:过滤、数据去重、tokenization 、随机混洗、拼接。

    • 对于 THEPILE 的预处理,我们参考了 《The pile: An 800gb dataset of diverse text for language modeling》

    • 对于 BIGQUERYBIGPYTHON

      • 过滤:

        • 文件按文件扩展名过滤。

        • 删除平均 line length 小于 100 个字符的文件。

          对于很多程序, line length 小于 100 个字符串是很常见的,这种过滤是否过于严格?

        • 删除平均 line length 大于 1000 个字符的文件。

        • 删除超过 90% 的字符是十进制或十六进制数字的文件。

      • 去重:基于文件的 SHA-256 hash 来去重。由于 forkcopyrepository 里面有相当大比例的代码重复。

      • tokenization:采用 GPT-2BPE vocabulary,并且扩展了一些 special tokens 来代表 tab 符和空格符的 repeating tokens(因为在 python 中,空格符和 tab 符是有语法含义的) 。在 BIGQUERY 中,添加一个前缀从而表示编程语言的名称(因为 BIGQUERY 是多语言的)。

      • 混洗:每一年的数据都是随机混洗的。

      • 拼接:序列被拼接起来,以填充上下文长度达到 2048token ,并以一个 special token 作为分隔符。

    数据集的统计信息如下表所示。 CODEGEN-NL 模型被随机初始化并在THEPILE 上进行训练。CODEGEN-MULTI 模型从 CODEGEN-NL 初始化,然后在 BIGQUERY 上训练。CODEGEN-MONO 模型从CODEGEN-MULTI初始化,然后在BIGPYTHON 上训练。

  3. 模型:CODEGEN 模型是自回归 transformer 的形式,以next-token prediction 语言模型为学习目标,在自然语言语料库和从GitHub 裁剪的编程语言数据上训练。这些模型以不同的规模(350M, 2.7B, 6.1B, 16.1B )进行训练。前三种配置可以与在文本语料库上训练的开源大型语言模型 GPT-NEO350M, 2.7B )和 GPT-J6B)直接比较。

    GPT-NEOGPT-J 都是 GPT 的开源版本。

    模型遵循标准的transformer decoder ,具有从左到右的 causal masking 。对于 positional encoding,我们采用 rotary position embedding《Roformer: Enhanced transformer with rotary position embedding》)。对于 forward pass ,我们遵从 《GPT-J-6B: A 6 Billion Parameter Autoregressive Language Model》 的方法,并行执行 self-attentionfeed-forward ,以优化通信开销,即 xt+1=xt+mlp(ln(xt+attn(ln(xt)))) 被修改为 xt+1=xt+attn(ln(xt))+mlp(ln(xt)),其中 self-attention attn()feed-forward mlp() 是同步进行的,ln()layer normalization 。架构和超参数的选择是为 TPU-v4 的硬件专门优化的。

    CODEGEN 模型在数据集上的训练是有顺序的:CODEGEN-NL 首先在 THEPILE 上训练;CODEGEN-MULTICODEGEN-NL 初始化并在BIGQUERY 上训练;最后,CODEGEN-MONOCODEGEN-MULTI 初始化,并在 BIGPYTHON 上训练。

    以自然语言描述为条件的program synthesis 的涌现可能源于模型和数据的大小、训练目标、训练数据本身的性质。这被称为涌现emergence ,因为我们没有显式地在 comment-code pair 上训练模型。类似的现象在广泛的自然语言任务中被观察到,一个大规模的无监督语言模型能够以 zero-shot 的方式解决未见过的任务(《Language models are few-shot learners》)。涌现的现象或令人惊讶的 zero-shot 泛化通常被归因于模型和数据的大规模。

    虽然我们的重点不是揭示为什么 program synthesis 能力会从简单的语言建模中涌现的根本机制,但鉴于我们的建模方法和训练数据的性质,我们试图提供一个解释。数据由 GitHub 上的常规代码组成(无人工选择),其中一些数据表现出自然语言和编程语言交错的模式,我们认为这为program synthesis 能力提供了一个噪音的监督信号,这是由于 next-token prediction 的预测训练目标。然而,我们强调,这样的数据模式是高度嘈杂的、弱的,因为只有一部分数据表现出这样的模式,例如,注释可能是不准确的或没有信息的,其中一些注释甚至可能被放在不相关的位置。因此,我们认为有两个主要因素导致了program synthesis 能力:模型规模和数据规模的 large scale 、训练数据中的 noisy signal

    这种大型语言模型的 scaling 需要数据和模型的并行。为了解决这些要求,我们开发了一个训练库 JAXFORMER ,用于在谷歌的TPU-v4 硬件上进行高效训练。

    模型的规格和超参数如下表所示。

  4. 训练:大型语言模型的 scaling 需要数据并行和模型并行。为了有效利用硬件,模型的训练是在 JAX 中实现的。我们采用 Adam 优化器,(β1,β2,ϵ)=(0.9,0.999,1e8) ,采用全局梯度范数裁剪(阈值为 1.0)。学习率遵从 GPT-3,使用带预热的余弦退火。总之,我们主要采用了 GPT-3 的参考配置,并对 TPU 的优化做了小的改动。我们没有算力来进一步优化这些超参数。

1.2 Single-Turn Evaluation

  1. 我们首先使用一个现有的 program synthesis benchmark 来评估我们的 CODEGENHumanEval (MIT license)HumanEval 包含 164 个手写的 Python 编程问题。每个问题都提供了一个 prompt ,包括要生成的函数的描述、函数签名、以及断言形式的测试用例。模型需要根据 prompt 完成一个函数,使其能够通过所有提供的测试用例,从而通过功能正确性functional correctness 来衡量性能。由于用户的意图是在一个 prompt 中指定的,并仅仅提示模型一次,我们将 HumanEval 上的评价视为 single-turn evaluation,以区别于我们在下一节介绍的 multi-turn evaluation 。遵循 《Evaluating large language models trained on code》 的做法,我们使用 top-p 的核采样 nucleus sampling ,其中 p=0.95

    人类日常生活中交流的词语并不是语言模型中概率最大的词语,而 Beam Search 会总会选择最符合语言模型的单词,因此生成的文本没有新意。为了解决这个问题,最简单的方法就是引入 top-k sampling:每次解码的时候不是选择概率最大的单词,而是根据单词的输出概率进行采样。然而,k 的选择是个难点。

    为此,nucleus sampling 换一个思路:给定一个概率阈值 p ,从候选单词集合中选择一个最小的集合 Vp ,使得这些单词出现的概率之和大于等于 p ,然后再对 Vp 中的单词的概率做一次缩放使得它们出现的概率之和为 1 ,最后仅对 Vp 中的单词进行解码。

1.2.1 实验比较

  1. baseline:我们将我们的模型与 Codex 模型( 《Evaluating large language models trained on code》 )进行了比较,后者展示了 HumanEvalSOTA 的性能。此外,我们的模型还与开源的大型语言模型 GPT-NEOGPT-J 进行比较。这些模型是在 THEPILE上训练的,因此在训练数据和模型大小方面与我们的 CODEGEN-NL模型相似。

  2. 评估方法:所有的模型都是在温度 t{0.2,0.6,0.8} 的情况下进行评估的,我们为每个模型计算 pass@k ,其中 k{1,10,100} 。 为了与 Codex 的结果直接比较,我们选择了对每个 k 产生最佳 pass@k 的温度。

    我们使用 Codex 提出的 unbiased estimator 来计算 pass@k 。对每个任务,采样 nk 个样本。具体而言,我们选择 n=200k100 。假设 c 为通过所有单元测试的样本的数量(即,correct samples),那么 unbiased estimator 定义为:

    (1)pass@k=EProblems[1CnckCnk]

    Cnk 表示在所有的 n 个样本中选择 k 个结果;Cnck 表示错误的 nc 个样本中选择 k 个结果。k 为测试用例的数量。

    直接计算这个 estimator 在数值上是不稳定的。我们使用 Codex 引入的数值稳定的 numpy implementation

    在评估模型输出和预期输出之间的 equivalence 之前,我们进行以下 type-relaxation

    • numpy 数组转换为相应的标准类型的Python list (例如,np.int32 被转换为 int )。

    • pandas series 被转换并以 numpy array 格式进行比较。

    • 剩余的情况,模型输出被 castgold standard output 的数据类型。

    • 浮点数的比较中,采用 ϵ=106 作为阈值。

  3. HumanEval 的表现随着 model sizedata sizescale :我们的模型和 baseline 的结果总结在下表中。可以看到:

    • 我们的 CODEGEN-NL模型(350M, 2.7B, 6.1B)的表现优于或与对应规模的 GPT-NEOGPT-J 模型相当。

    • 在多语言编程语言数据(BIGQUERY)上进一步训练CODEGEN-NL,可以得到 CODEGEN-MULTI 。多语言 CODEGEN 模型的表现远远超过了在 THEPILE 上训练的模型(GPT-NEO, GPT-J, CODEGEN-NL )。

    • 然后,我们在 Python 数据集(BIGPYTHON)上对 CODEGEN-MULTI 进行了微调,形成了 CODEGEN-MONOprogram synthesis 能力得到了大幅提高。因此,Pythonprogram synthesis 能力随着 Python 训练数据量的增加而增强。

    • 对于几乎所有的模型,正如预期的那样,增加模型的规模可以提高整体性能。

    • 与目前 SOTA 的模型 Codex 相比,我们的 Python-monolingual CODEGEN 模型的性能具有竞争力或有所提高。

      • k=100 时,CODEGEN-MONO 2.7B 的性能低于 CODEX 2.5B ,但当 k{1,10} 时,则优于 CODEX 2.5B

      • 我们的 CODEGENMONO 6.1B 展示了接近表现最好的 CodexCODEX 12B )的 pass@k 分数,虽然我们的 CODEGEN-MONO 6.1B 只有CODEX 12B 一半的规模。

      • 我们最大的模型 CODEGEN-MONO 16.1B 具有竞争力,或者在某些 k 的情况下超越了 CODEX 12B

1.2.2 用户意图理解

  1. 困惑度计算:给定一个问题,假设 {pi}i=1n 为该问题的一组 prompt{si}i=1n 是模型 Pθ 合成的 n 个子程序,m 为所有 prompt 集合 {pi}i=1n 包含的所有 token 的总数。

    • multi-turn prompt 的困惑度:令 ci1=[p1;s1;;pi1;si1] ,其中 [;] 为拼接操作。那么生成 prompt pi 的条件概率为:Probi=Pθ(pici1) 。则 multi-turn prompt 的困惑度为:

      (2)PPLmulti-trun=exp(1mi=1nlogProbi)
    • single-turn prompt 的困惑度:令 c=[p1;s1;;pn;sn] ,那么该文本序列被生成的概率为 Prob=Pθ(c) 。那么 single-turn prompt 的困惑度为:

      (3)PPLsingle-trun=exp(1mlogProb)
  2. 更好的用户意图理解产生更好的 synthesized program :一个program synthesis 系统的成功高度依赖于它对用户意图的理解程度。当系统以语言模型为基础时,problem prompt 的困惑度perplexity 可以代表系统对用户意图规范user intent specification 的理解。给定一个模型,意图规范的低困惑度表明:该意图规范与模型从训练数据中学到的知识是兼容的。我们研究了是否更好的 prompt 理解(以更低的 prompt 困惑度来衡量)会导致 functionally 更准确的程序。

    我们将所有问题划分为pass 、以及non-pass :一个pass problem 是指 200 个采样的结果中,至少有一个样本通过了所有的测试用例;而对于non-pass problem200 个采样的结果中没有一个通过所有的测试用例。我们根据 CODEGEN-MONO 模型的样本,计算出个pass problemnon-pass problemproblem prompt 的平均困惑度。结果如下表所示。pass problempromptnon-pass problemprompt 具有更低的困惑度。 这一发现意味着,当用户的意图规范被模型更好地理解时,program synthesis 更容易成功。

    事实上,一些训练数据包含自然语言注释和程序的交错序列,其中注释描述了紧接着的程序的功能。因此我们推测,类似于这种模式的用户意图规范会被模型更好地理解,从而导致更好的 program synthesis 。受这种模式的启发,我们提出在 multiple turns 中指定用户意图,这样模型就能一次关注 partial problem ,这将使模型更容易理解用户意图。

    此外,CODEGEN-NLCODEGEN-MULTI 的困惑度结果:

1.3 Multi-Turn Evaluation

  1. 在本节中,我们提出并研究了一种multi-step program synthesis 范式,其中 program synthesis 被分解成多步,系统在每个步骤中合成一个子程序。为了研究这种范式,我们首先开发了一个Multi-Turn Programming Benchmark: MTPBMTPB 包括 115 个由专家编写的问题,每个问题都包括一个自然语言的 multi-step description(即,prompt )。为了解决一个问题,一个模型需要合成功能上正确的子程序:遵循当前步骤的 description 、考虑当前的 description 以及前面步骤已经合成的子程序(例如,对前面步骤中定义的函数和/或变量的正确 back-reference )。下图给出了一个例子。

  2. benchmark 构建:我们( 4 位作者)首先定义了一组 115 个需要不同编程知识的问题,包括数学、数组操作、字符串操作、算法、数据科学以及需要其他知识的问题,使得每一类问题的数量大致平衡。对于每个问题,我们构建一个由 multi-turn prompts P 、测试用例输入 I、测试用例输出 O 组成的 triplet

    • multi-turn prompts P 的设计遵循两个约束条件:问题被分解成 3 个或更多的 turns 、单个 turn 无法解决该问题。

      例如,实现一个线性回归模型可以被表述为 "Perform linear regression on x and y" 。由于 main task 在这个 prompt 中得到了充分的表达,所以理解这个 prompt 就足以执行这个任务。我们通过人工检查来避免这种情况,使得多个 turn 才能解决问题。

    • prompt 一起,我们要求问题作者准备 5 组测试用例的输入 I 和输出 O ,以评估模型输出的功能正确性。为了减少错误地奖励那些给出无意义程序、但通过测试的 false positive 方案,我们检查并修改这些案例以确保测试质量。

    HumanEval 中,模型要补全一个部分定义的函数。 与HumanEval 不同的是,MTPB 问题只提供 prompt ,因此模型必须从头开始生成解决方案。虽然自由形式的生成可能允许更多潜在的解决方案,但缺乏一个入口来提供测试用例的输入,因此使得在不同的测试用例上测试生成的代码具有挑战性(因为自由生成的情况下,函数签名可能都不是固定的,因此难以提供测试接口)。为了克服这一挑战,我们在 prompt 中嵌入了测试用例的输入。具体而言,prompt 是用 Python 的格式化字符串编写的,当一个特定的测试用例应用于问题时,输入值会被替换成变量名。例如,一个 prompt"Define a string named ’s’ with the value {var}." ,连同测试用例输入 var = 'Hello' 将被格式化为 "Define a string named ‘s’ with the value 'Hello'."。参考 Figure1 的①。

    这里将测试用例的输入嵌入到 prompt 中,而不是作为函数接口来调用。

    问题:

  3. 执行环境和解决方案评估:对于执行,prompt 和生成的 completion 组成的 pair ,会被拼接起来从而构成一个独立的程序(如 Figure 1 中的③)。然后遵从 single-turn HumanEval benchmark 在一个孤立的 Python 环境中执行该程序。然而,HumanEval 中的问题中,函数签名是已知的,因此在一组功能性的单元测试下调用生成的代码是很简单的。在我们的multi-turn case 中,无法保证生成这样的入口点(或返回值)。为了避免 missing return signatureMTPBmulti-turn problem 的最后一个 prompt 总是被指定为向终端打印出结果状态。然后,benchmark 执行环境重载了 Python print(args) 函数,并将 args 存储在栈上。

    如果一个问题的最后一个promptsampled code 不包括 print()语句 ,那么生成的代码的 AST 将被突变以注入 print() 的调用。最后,针对问题的 pre-defined gold output ,对 args 进行类型放松的等价检查(例如,listtuple 之间的隐式转换),以确定测试的失败或成功。

  4. multi-step 编程能力随模型大小和数据大小的变化而变化:在这个分析中,我们研究了模型大小和数据大小是如何影响 multi-turn 范式下 program synthesis 能力的。在 MTPB 中,每个问题有 5 个测试案例,我们用每个模型为每个测试案例采样 40 个样本,在此基础上计算每个问题的通过率。我们的 CODEGEN 模型、baselineOpenAI Codex 模型的 MTPB 评估结果(平均通过率)如下表所示。

    很明显,MTPB 的性能随着模型大小和数据大小的变化而提高。这表明,multi-step program synthesis 的能力随着模型大小和数据大小的变化而扩大。这些模型只是用 autoregressive language modeling objective 进行训练。当模型和数据规模 scale up 时,multi-turn program synthesis 的能力就涌现了,也就是以 multi-turn 方式合成程序的能力。

  5. multi-trun factorization 更好地理解用户规范:我们假设, multi-trun factorization 增强了模型对用户意图规范的理解,这反过来又导致了更高的 program synthesis 能力。为了测试这个假设,我们通过将每个规范拼接成 single turn ,形成 multi-turn specification 对应的 single-turn 版本。如前所示,我们采用 prompt perplexity 作为用户意图理解的代理。因此,我们比较了四种 CODEGEN-MONO 模型下的 multi-turn promptconcatenated single-turn prompt 的困惑度。

    这里比较了相同的 prompt 对应于 multi-turnsingle-turn 之间的效果差异:

    • 对于 multi-turn,直接使用原始的多个 prompt

    • 对于 single-turn,将多个 prompt 拼接起来形成单个长的 prompt

    下表的左侧显示了 MTPB 中所有问题的平均困惑度。对于所有的模型,single-turn specificationmulti-turn specification 的平均困惑度高。这意味着 multi-turn用户规范可以被模型更好地理解。我们注意到,在较大的模型下,multi-turnsingle-turn 的意图规范的平均困惑度都略低于较小的模型,这说明较大的模型比小的模型更能理解用户意图。

    我们比较了使用 multi-turn promptprogram synthesis 通过率、以及使用 concatenated single-turn promptprogram synthesis 通过率。结果显示如下表右侧所示。在所有的模型规模中,multi-turn specification 都接近或超过了 single-turn specification10 个百分点。结合上面的困惑度分析,似乎将用户规范分解成多个步骤,并利用大型语言模型的涌现能力emerged capacity ,使他们更容易理解规范,更成功地合成程序。

    此外,我们根据问题的平均通过率按难度分类(低于 30% 表示"难",大于 70% 表示 "易"),并研究问题难度和模型大小对 multi-turn factorization 的改进的影响。如 Figure2所示。

    在几乎所有的模型大小和难度级别中,multi-turn prompt 都会比single-turn prompt 带来明显的改善,而且大多数改善接近或高于 10 个百分点。有趣的是,更大的模型(6.1B and 16.1B )对容易的问题的 multi-turn factorization 是不变的(见 Figure 2 中的两个短条,0.19%-0.25% )。这意味着,当问题可以很容易地被模型理解时(由于问题的简单性和较大模型的高容量的综合影响),对规范进行分解是没有必要的,也没有收益的。这实际上与我们的动机假设是一致的,即把 complicated specification 进行分解,会使问题容易理解并改善 program synthesis

  6. 定性的例子:为了进一步了解模型行为在模型规模上的差异,我们研究了大型模型与小型模型具有不同性能的案例。我们特别选择了CODEGEN-MONO 16.1BCODEGEN-MONO 2.7B 在性能上表现出明显差异的问题。在 CODEGEN-MONO 16.1B 表现明显较差的问题上(与 CODEGEN-MONO 2.7B 相比),我们观察到,由于按字面意思理解 prompt ,更大的模型变得不灵活。例如:

    • 初始化一个数字的结果总是一个整型,prompt 提示要求 cast 成一个字符串(Figure 3 )。

    • prompt 中的 "return" 关键字触发了一个函数定义,而其用户意图是直接生成一个可执行程序(Figure 4 )。

    然而一般来说,较大规模的模型克服了由于小模型对 prompt 的误解而导致的错误,包括同时赋值多个变量(Figure 5 )或理解任何 comparison 的概念(Figure 6 )。

  7. 我们还在 Mostly Basic Python Problems: MBPP 上评估了我们的模型。结果如下表所示。遵从 Codet 的做法,我们从 sanitized MBPP 中为我们所有的模型采样 programn=100 ,温度为 0.8 。最后四行来自于原始论文。

    总的来说,我们观察到在不同的版本(NL, Multi, Mono )上性能提高的一致趋势,我们最大的 CODEGEN-MONO 16.1B 接近于code-cushman-001 的结果。

    我们不知道 OpenAI 模型中是否是 《Evaluating large language models trained on code》报告的 "Codex 12B" ,但我们相信我们的模型在 MBPP 上也取得了合理的结果。我们还注意到,我们的 CODEGEN-MONO 6.1B 的表现明显优于 INCODER 6B

  8. 生成的程序长度和通过率的关系:

  9. 生成的程序长度和 prompt 长度之间的关系: