程序合成 program synthesis
的目标是使编码过程自动化,并生成一个满足用户指定意图的计算机程序。成功的program synthesis
不仅可以提高有经验的程序员的生产力,还可以让更多人了解编程。
在实现program synthesis
时,有两个关键的挑战:搜索空间的不可控性、正确指定用户意图的困难。
为了使得搜索空间有表达能力,人们需要一个大的搜索空间,这给高效搜索带来了挑战。以前的工作利用 domain-specific language
来限制搜索空间,然而,这限制了 synthesized program
的适用性。相反,通用编程语言(如 C
、Python
)虽然适用性更广,但是引入了一个更大的搜索空间。为了在巨大的 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-code
、input-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 synthesis
( multi-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
研究。
下图中,
为用户提供的 prompt
,为模型返回的 subprogram
。最终的结果是所有的subprogram
组合在一起而形成的。因此,用户提供的prompt
对于最终结果是至关重要的,这是优点也是缺点:优点是用户可以对代码生成过程进行更精细的控制,缺点是需要用户具备一定程度的专业知识(需要知道怎么描述程序的每一步)。①为整个过程的示意图,②为模型生成的过程(以之前的
prompts
和subprograms
为条件),③为最终结果。
论文贡献: 论文与最近同时进行的、使用 single-turn user intent specification
的工作的基本想法一致,即用采用语言模型来执行 program synthesis
。此外:
论文研究了在 scaling law
下自回归模型中的 multi-turn program synthesis
。
论文利用这种能力引入了一个 multi-turn program synthesis
范式。
论文用一个新的 multi-turn programming benchmark
(https://github.com/salesforce/CodeGen/tree/main/benchmark
)对其特性进行定量研究。
论文将开源 model checkpoint
(https://github.com/salesforce/CodeGen
)和自定义训练库:JAXFORMER
(https://github.com/salesforce/jaxformer
)。对于 program synthesis
来说,目前还没有可以与 Codex
竞争的、开源的大型模型。这阻碍了 program synthesis
的发展,因为训练这些模型所需的昂贵的计算资源只有数量有限的机构可以获得。作者的开源贡献允许广泛的研究人员研究和改善这些模型,这可能大大促进研究进展。
相关工作:
Program Synthesis
:虽然 program synthesis
有很长的历史,但两个固有的挑战仍未解决:program space
非常棘手、难以准确表达用户意图。
之前的大量研究试图通过探索随机搜索技术、自上而下的演绎搜索等方法来解决第一个问题,然而,这些方法的可扩展性仍然是有限的。
用户的意图可以用各种方法来表达:正式的逻辑规范、input-output examples
、自然语言描述。完整的和正式的规范需要太多的努力,而非正式的如 input-output examples
往往对问题的规范不足。
由于大规模的模型和数据,well-learned
的条件分布和语言理解能力可以有效地解决这两个挑战。
有几项工作研究将对话意图转换为programmable representation
,如 SQL
或 dataflow graph
。我们提出的 benchmark
要求生成 Python
,这是更通用、更复杂的。
Large Language Model
:Transformer
通过注意力机制捕捉序列的元素之间的依赖关系,并且具有高度的可扩展性。它已被成功地应用于自然语言处理、计算机视觉、以及许多其他领域。之前的工作,如 CuBERT
、CodeBERT
、PyMT5
和 CodeT5
,已经将 Model
(即,Transformer
)应用于 code understanding
,但这些大多侧重于代码检索、分类和程序修复。
最近和同时进行的几项工作探索了使用大型语言模型进行 program synthesis
及其有效性。然而他们关注的是在 single turn
中生成代码,而我们提议将 specification
分解为 multiple turns
,并证明这对提高合成质量非常有效。值得指出的是,《Program synthesis with large language models》
探索了在 multiple iterations
中完善代码的方法,但它本质上是一种 single-turn
方法,因为每个 single turn
都会产生一个完整的程序。
用intermediate information
来 prompting
预训练好的语言模型以提高任务性能已经引起了人们的兴趣。我们提出的 MTPB
也允许模型利用 past turns
作为上下文。
Benchmarks for Program Synthesis
:为了定量分析 program synthesis
模型,人们已经提出了几个具有不同输入形式的 benchmark
。流行的输入形式包括:同一行中的前序代码 preceding code
、伪代码、docstring
和函数签名、problem description
。在大多数 case
中,仅仅向模型提供直接相关的输入信息。
相反,一些以前的工作提出了一些 benchmark
,这些 benchmark
衡量在给定目标程序周围的 program context
(如变量、其它函数、前序的代码块/文本块)的条件下,生成程序的能力,主要的重点是生成目标程序本身。
我们提出一个新的 benchmark
,要求通过 multi-turn prompts
逐步生成子程序。
为了在 scaling law
下评估 multi-turn programming
的emergence
,我们采用了标准的 transformer-based
的自回归语言模型,但是做了一些改变:
模型参数规模:350M, 2.7B, 6.1B, 16.1B
。
训练语料库中 programming language
的 token
的数量。
为了扩大训练规模,我们开发了一个自定义的库 JAXFORMER
用于 TPU-v4 hardware
,并将以开源方式发布,包括训练好的模型权重。
数据集:CODEGEN
模型系列是在 THEPILE, BIGQUERY, BIGPYTHON
这三个数据集上按顺序地训练的。
THEPILE
:自然语言数据集 THEPILE
是由 《The pile: An 800gb dataset of diverse text for language modeling》
为语言建模而收集的 825.18 GB
英语文本语料库(MIT license
)。该数据集由 22
个不同的、高质量的子集构成,其中一个子集是从 GitHub repositories
(repository
的 star
数量超过 100
)中收集的编程语言数据,该子集占数据集的 7.6%
。由于 THEPILE
的大部分内容是英文文本,因此得到的模型被称为 natural language CODEGEN model
(CODEGEN-NL
)。
BIGQUERY
:多语言数据集 BIGQUERY
是谷歌公开的 BigQuery
数据集的一个子集,它由多种编程语言的代码(在 open-source license
下)组成。对于多语言训练,我们选择了以下 6
种编程语言:C, C++, Go, Java, JavaScript, Python
。因此,我们把在 BIGQUERY
上训练的模型称为 multi-lingual CODEGEN model
(CODEGEN-MULTI
)。
BIGPYTHON
:单语言数据集 BIGPYTHON
包含大量的编程语言 Python
的数据。我们在 2021
年 10
月收集了来自 GitHub
的公开的、非个人的信息,这些信息由 Python code
(在 open-source license
下)组成。因此,我们将在 BIGPYTHON
上训练的模型称为 mono-lingual CODEGEN model
(CODEGEN-MONO
)。
预处理过程如下:过滤、数据去重、tokenization
、随机混洗、拼接。
对于 THEPILE
的预处理,我们参考了 《The pile: An 800gb dataset of diverse text for language modeling》
。
对于 BIGQUERY
和 BIGPYTHON
:
过滤:
文件按文件扩展名过滤。
删除平均 line length
小于 100
个字符的文件。
对于很多程序,
line length
小于100
个字符串是很常见的,这种过滤是否过于严格?
删除平均 line length
大于 1000
个字符的文件。
删除超过 90%
的字符是十进制或十六进制数字的文件。
去重:基于文件的 SHA-256 hash
来去重。由于 fork
和 copy
,repository
里面有相当大比例的代码重复。
tokenization
:采用 GPT-2
的 BPE vocabulary
,并且扩展了一些 special tokens
来代表 tab
符和空格符的 repeating tokens
(因为在 python
中,空格符和 tab
符是有语法含义的) 。在 BIGQUERY
中,添加一个前缀从而表示编程语言的名称(因为 BIGQUERY
是多语言的)。
混洗:每一年的数据都是随机混洗的。
拼接:序列被拼接起来,以填充上下文长度达到 2048
个 token
,并以一个 special token
作为分隔符。
数据集的统计信息如下表所示。 CODEGEN-NL
模型被随机初始化并在THEPILE
上进行训练。CODEGEN-MULTI
模型从 CODEGEN-NL
初始化,然后在 BIGQUERY
上训练。CODEGEN-MONO
模型从CODEGEN-MULTI
初始化,然后在BIGPYTHON
上训练。
模型:CODEGEN
模型是自回归 transformer
的形式,以next-token prediction
语言模型为学习目标,在自然语言语料库和从GitHub
裁剪的编程语言数据上训练。这些模型以不同的规模(350M, 2.7B, 6.1B, 16.1B
)进行训练。前三种配置可以与在文本语料库上训练的开源大型语言模型 GPT-NEO
(350M, 2.7B
)和 GPT-J
(6B
)直接比较。
GPT-NEO
和GPT-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-attention
和 feed-forward
,以优化通信开销,即 self-attention
feed-forward
layer normalization
。架构和超参数的选择是为 TPU-v4
的硬件专门优化的。
CODEGEN
模型在数据集上的训练是有顺序的:CODEGEN-NL
首先在 THEPILE
上训练;CODEGEN-MULTI
从 CODEGEN-NL
初始化并在BIGQUERY
上训练;最后,CODEGEN-MONO
从 CODEGEN-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
硬件上进行高效训练。
模型的规格和超参数如下表所示。
训练:大型语言模型的 scaling
需要数据并行和模型并行。为了有效利用硬件,模型的训练是在 JAX
中实现的。我们采用 Adam
优化器,1.0
)。学习率遵从 GPT-3
,使用带预热的余弦退火。总之,我们主要采用了 GPT-3
的参考配置,并对 TPU
的优化做了小的改动。我们没有算力来进一步优化这些超参数。
我们首先使用一个现有的 program synthesis benchmark
来评估我们的 CODEGEN
:HumanEval (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
,其中
人类日常生活中交流的词语并不是语言模型中概率最大的词语,而
Beam Search
会总会选择最符合语言模型的单词,因此生成的文本没有新意。为了解决这个问题,最简单的方法就是引入top-k sampling
:每次解码的时候不是选择概率最大的单词,而是根据单词的输出概率进行采样。然而,的选择是个难点。 为此,
nucleus sampling
换一个思路:给定一个概率阈值,从候选单词集合中选择一个最小的集合 ,使得这些单词出现的概率之和大于等于 ,然后再对 中的单词的概率做一次缩放使得它们出现的概率之和为 1
,最后仅对中的单词进行解码。
baseline
:我们将我们的模型与 Codex
模型( 《Evaluating large language models trained on code》
)进行了比较,后者展示了 HumanEval
上SOTA
的性能。此外,我们的模型还与开源的大型语言模型 GPT-NEO
和 GPT-J
进行比较。这些模型是在 THEPILE
上训练的,因此在训练数据和模型大小方面与我们的 CODEGEN-NL
模型相似。
评估方法:所有的模型都是在温度 pass@k
,其中 Codex
的结果直接比较,我们选择了对每个 pass@k
的温度。
我们使用 Codex
提出的 unbiased estimator
来计算 pass@k
。对每个任务,采样 correct samples
),那么 unbiased estimator
定义为:
表示在所有的 个样本中选择 个结果; 表示错误的 个样本中选择 个结果。 为测试用例的数量。
直接计算这个 estimator
在数值上是不稳定的。我们使用 Codex
引入的数值稳定的 numpy implementation
。
在评估模型输出和预期输出之间的 equivalence
之前,我们进行以下 type-relaxation
:
将 numpy
数组转换为相应的标准类型的Python list
(例如,np.int32
被转换为 int
)。
pandas series
被转换并以 numpy array
格式进行比较。
剩余的情况,模型输出被 cast
为 gold standard output
的数据类型。
浮点数的比较中,采用
HumanEval
的表现随着 model size
和 data size
而 scale
:我们的模型和 baseline
的结果总结在下表中。可以看到:
我们的 CODEGEN-NL
模型(350M, 2.7B, 6.1B
)的表现优于或与对应规模的 GPT-NEO
和 GPT-J
模型相当。
在多语言编程语言数据(BIGQUERY
)上进一步训练CODEGEN-NL
,可以得到 CODEGEN-MULTI
。多语言 CODEGEN
模型的表现远远超过了在 THEPILE
上训练的模型(GPT-NEO, GPT-J, CODEGEN-NL
)。
然后,我们在 Python
数据集(BIGPYTHON
)上对 CODEGEN-MULTI
进行了微调,形成了 CODEGEN-MONO
。program synthesis
能力得到了大幅提高。因此,Python
的 program synthesis
能力随着 Python
训练数据量的增加而增强。
对于几乎所有的模型,正如预期的那样,增加模型的规模可以提高整体性能。
与目前 SOTA
的模型 Codex
相比,我们的 Python-monolingual CODEGEN
模型的性能具有竞争力或有所提高。
当 CODEGEN-MONO 2.7B
的性能低于 CODEX 2.5B
,但当 CODEX 2.5B
。
我们的 CODEGENMONO 6.1B
展示了接近表现最好的 Codex
(CODEX 12B
)的 pass@k
分数,虽然我们的 CODEGEN-MONO 6.1B
只有CODEX 12B
一半的规模。
我们最大的模型 CODEGEN-MONO 16.1B
具有竞争力,或者在某些 CODEX 12B
。
困惑度计算:给定一个问题,假设 prompt
,prompt
集合 token
的总数。
multi-turn prompt
的困惑度:令 prompt
multi-turn prompt
的困惑度为:
single-turn prompt
的困惑度:令 single-turn prompt
的困惑度为:
更好的用户意图理解产生更好的 synthesized program
:一个program synthesis
系统的成功高度依赖于它对用户意图的理解程度。当系统以语言模型为基础时,problem prompt
的困惑度perplexity
可以代表系统对用户意图规范user intent specification
的理解。给定一个模型,意图规范的低困惑度表明:该意图规范与模型从训练数据中学到的知识是兼容的。我们研究了是否更好的 prompt
理解(以更低的 prompt
困惑度来衡量)会导致 functionally
更准确的程序。
我们将所有问题划分为pass
、以及non-pass
:一个pass problem
是指 200
个采样的结果中,至少有一个样本通过了所有的测试用例;而对于non-pass problem
,200
个采样的结果中没有一个通过所有的测试用例。我们根据 CODEGEN-MONO
模型的样本,计算出个pass problem
和non-pass problem
的 problem prompt
的平均困惑度。结果如下表所示。pass problem
的 prompt
比 non-pass problem
的 prompt
具有更低的困惑度。 这一发现意味着,当用户的意图规范被模型更好地理解时,program synthesis
更容易成功。
事实上,一些训练数据包含自然语言注释和程序的交错序列,其中注释描述了紧接着的程序的功能。因此我们推测,类似于这种模式的用户意图规范会被模型更好地理解,从而导致更好的 program synthesis
。受这种模式的启发,我们提出在 multiple turns
中指定用户意图,这样模型就能一次关注 partial problem
,这将使模型更容易理解用户意图。
此外,CODEGEN-NL
和 CODEGEN-MULTI
的困惑度结果:
在本节中,我们提出并研究了一种multi-step program synthesis
范式,其中 program synthesis
被分解成多步,系统在每个步骤中合成一个子程序。为了研究这种范式,我们首先开发了一个Multi-Turn Programming Benchmark: MTPB
。MTPB
包括 115
个由专家编写的问题,每个问题都包括一个自然语言的 multi-step description
(即,prompt
)。为了解决一个问题,一个模型需要合成功能上正确的子程序:遵循当前步骤的 description
、考虑当前的 description
以及前面步骤已经合成的子程序(例如,对前面步骤中定义的函数和/或变量的正确 back-reference
)。下图给出了一个例子。
benchmark
构建:我们( 4
位作者)首先定义了一组 115
个需要不同编程知识的问题,包括数学、数组操作、字符串操作、算法、数据科学以及需要其他知识的问题,使得每一类问题的数量大致平衡。对于每个问题,我们构建一个由 multi-turn prompts
triplet
。
multi-turn prompts
3
个或更多的 turns
、单个 turn
无法解决该问题。
例如,实现一个线性回归模型可以被表述为 "Perform linear regression on x and y"
。由于 main task
在这个 prompt
中得到了充分的表达,所以理解这个 prompt
就足以执行这个任务。我们通过人工检查来避免这种情况,使得多个 turn
才能解决问题。
与 prompt
一起,我们要求问题作者准备 5
组测试用例的输入 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
中,而不是作为函数接口来调用。
问题:
执行环境和解决方案评估:对于执行,prompt
和生成的 completion
组成的 pair
,会被拼接起来从而构成一个独立的程序(如 Figure 1
中的③)。然后遵从 single-turn HumanEval benchmark
在一个孤立的 Python
环境中执行该程序。然而,HumanEval
中的问题中,函数签名是已知的,因此在一组功能性的单元测试下调用生成的代码是很简单的。在我们的multi-turn case
中,无法保证生成这样的入口点(或返回值)。为了避免 missing return signature
,MTPB
中 multi-turn problem
的最后一个 prompt
总是被指定为向终端打印出结果状态。然后,benchmark
执行环境重载了 Python print(args)
函数,并将 args
存储在栈上。
如果一个问题的最后一个prompt
的 sampled code
不包括 print()语句
,那么生成的代码的 AST
将被突变以注入 print()
的调用。最后,针对问题的 pre-defined gold output
,对 args
进行类型放松的等价检查(例如,list
和 tuple
之间的隐式转换),以确定测试的失败或成功。
multi-step
编程能力随模型大小和数据大小的变化而变化:在这个分析中,我们研究了模型大小和数据大小是如何影响 multi-turn
范式下 program synthesis
能力的。在 MTPB
中,每个问题有 5
个测试案例,我们用每个模型为每个测试案例采样 40
个样本,在此基础上计算每个问题的通过率。我们的 CODEGEN
模型、baseline
和 OpenAI Codex
模型的 MTPB
评估结果(平均通过率)如下表所示。
很明显,MTPB
的性能随着模型大小和数据大小的变化而提高。这表明,multi-step program synthesis
的能力随着模型大小和数据大小的变化而扩大。这些模型只是用 autoregressive language modeling objective
进行训练。当模型和数据规模 scale up
时,multi-turn program synthesis
的能力就涌现了,也就是以 multi-turn
方式合成程序的能力。
用 multi-trun factorization
更好地理解用户规范:我们假设, multi-trun factorization
增强了模型对用户意图规范的理解,这反过来又导致了更高的 program synthesis
能力。为了测试这个假设,我们通过将每个规范拼接成 single turn
,形成 multi-turn specification
对应的 single-turn
版本。如前所示,我们采用 prompt perplexity
作为用户意图理解的代理。因此,我们比较了四种 CODEGEN-MONO
模型下的 multi-turn prompt
和 concatenated single-turn prompt
的困惑度。
这里比较了相同的
prompt
对应于multi-turn
和single-turn
之间的效果差异:
对于
multi-turn
,直接使用原始的多个prompt
。对于
single-turn
,将多个prompt
拼接起来形成单个长的prompt
。
下表的左侧显示了 MTPB
中所有问题的平均困惑度。对于所有的模型,single-turn specification
比 multi-turn specification
的平均困惑度高。这意味着 multi-turn
用户规范可以被模型更好地理解。我们注意到,在较大的模型下,multi-turn
和single-turn
的意图规范的平均困惑度都略低于较小的模型,这说明较大的模型比小的模型更能理解用户意图。
我们比较了使用 multi-turn prompt
的 program synthesis
通过率、以及使用 concatenated single-turn prompt
的 program synthesis
通过率。结果显示如下表右侧所示。在所有的模型规模中,multi-turn specification
都接近或超过了 single-turn specification
的 10
个百分点。结合上面的困惑度分析,似乎将用户规范分解成多个步骤,并利用大型语言模型的涌现能力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
。
定性的例子:为了进一步了解模型行为在模型规模上的差异,我们研究了大型模型与小型模型具有不同性能的案例。我们特别选择了CODEGEN-MONO 16.1B
和 CODEGEN-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
)。
我们还在 Mostly Basic Python Problems: MBPP
上评估了我们的模型。结果如下表所示。遵从 Codet
的做法,我们从 sanitized MBPP
中为我们所有的模型采样 program
,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
。
生成的程序长度和通过率的关系:
生成的程序长度和 prompt
长度之间的关系: