Home / 大语言模型 / Codex:代码生成必须测“能运行”,也必须说明采样预算

048 · Codex:代码生成必须测“能运行”,也必须说明采样预算

返回目录 · 上一篇:LoRA · 下一篇:TruthfulQA

论文:Mark Chen等,Evaluating Large Language Models Trained on Code,2021。原始论文v2 · HumanEval官方数据与评估代码。本篇讨论2021研究模型,不把它等同于后来同名产品。

先接住前作的问题

GPT-3提供文本生成骨干,但代码可运行且有边界条件,词面相似不足以判对。本篇继续训练代码域并引入HumanEval执行评价;未解问题同时包括候选能否生成正确程序,以及系统能否从中选出来。

五个前置概念

五个前置概念:自回归代码模型逐token预测程序;功能正确性由程序行为判断;pass@k测候选集合至少一个通过;采样温度调节分布多样性;候选排序决定实际返回哪段代码。最后两个环节与模型权重一起决定系统表现。

一、问题设定:代码文本相似之外,怎样衡量实现是否满足函数规格

HumanEval给出函数签名、docstring和必要上下文,要求生成实现;164道手写题覆盖算法、数学和语言理解。不同写法可能功能相同,近似照抄也可能漏边界,因此采用执行测试;单函数合成仍不代表跨文件仓库修复。

基础Codex从GPT系列权重开始,对GitHub Python代码继续做下一token预测。作者也实验从头训练,最终质量没有观察到明确收益差,但预训练初始化收敛更快,所以后续采用它。不能把“从语言模型开始”写成已证明最终编程能力必需的条件。

Codex-S再使用独立函数及说明做监督适配:约10K竞赛/面试题与约40K从持续集成运行中收集的函数问题是过滤前来源。训练只在参考实现token计算损失;测试用于筛选训练问题质量和评估生成结果,原文没有以测试奖励做在线策略优化。

二、由候选组合数推导pass@k覆盖估计

代码继续训练仍最小化:

Lcode=−∑tlog⁡pθ(ct∣c<t).L_{\rm code}=-\sum_t\log p_\theta(c_t\mid c_{<t}).

Codex-S改为条件实现损失 −∑tlog⁡pθ(yt∣x,y<t)-\sum_t\log p_\theta(y_t\mid x,y_{<t}),其中 xx 为说明,yy 为参考代码。目标是模仿训练分布,功能正确由外部测试度量,两者不完全等价。

假设一道题采样 nn 个实现,其中 cc 个通过测试,估计从其中抽 kk 个时至少一个通过的概率:

pass@k^=1−(n−ck)(nk).\widehat{\mathrm{pass@}k} =1-\frac{\binom{n-c}{k}}{\binom nk}.

分式是“全部抽到失败实现”的概率,最后跨题求平均。论文用每题200个样本估计 k≤100k\le100,减少直接每题只抽 kk 次的方差。对每题成功率先做简单估计,再代入 1−(1−p^)k1-(1-\hat p)^k 会产生偏差;先把所有题合并成一个成功率,还会丢掉难度差异。

pass@k估计的是候选里有没有,并不负责选出来

n次采样有c次通过测试,从这n个样本均匀取k个而全错的组合数为 (n−ck)\binom{n-c}{k},总组合数为 (nk)\binom nk;一减便得到论文的估计量。它需要固定问题、采样协议和测试判定。用经验pass@1直接代入 1−(1−p^)k1-(1-\hat p)^k 会引入非线性估计偏差;跨题还应先分别计算再平均,不能把所有题的样本混成一个成功率。

教学算例。 n=10、c=2、k=3时,估计值为 1−(83)/(103)=1−56/120≈53.3%1-\binom83/\binom{10}3=1-56/120\approx53.3\%;代入法得到 1−0.83=48.8%1-0.8^3=48.8\%。即使候选集含正确程序,部署时若无法识别它,实际交付成功率仍可能低。通过有限测试也不是满足所有输入规格的证明。

再看一个估计示例:n=10,c=2,k=2n=10,c=2,k=2,则得分为 1−(82)/(102)=17/45≈0.3781-\binom82/\binom{10}2=17/45\approx0.378。这是从有限样本估计候选成功的教学计算,不是某个HumanEval题的实测值。

把候选覆盖和最终交付写成两个事件

设100道题中有70道的候选池包含正确程序,而实际选择器只在其中50道选对,最终成功率是50%,选择器在可解候选池上的条件成功率为50/70。把70%报给单提交用户,就等于偷偷给了oracle选择。测试预算变化时,覆盖和条件选中率应各画一条曲线。

三、代码域训练后固定采样、测试与候选选择协议

输入:待测模型、独立函数题及隐藏测试、温度 T、n、k
每道题:
  只把允许公开的签名和说明作为提示
  独立生成 n 个候选,记录温度、top-p与停止规则
  在隔离执行环境中运行测试并记录失败类型
  c = 通过全部测试的候选数量
  若 n-c < k:该题分数 = 1
  否则:该题分数 = 1 - C(n-c,k)/C(n,k)
输出:所有题分数均值与采样预算
另行报告:无隐藏测试时,候选选择器返回单一答案的成功率

代码围栏是评估流程,不是建议直接在工作环境执行未知代码。原文将隔离执行作为评估基础设施,原因是运行、超时和依赖失败本来就会影响指标。

四、区分raw、filtered、oracle与实际单提交成绩

候选覆盖、基于概率的排序和知道测试结果的oracle要分线读;过滤后pass@1仍需记原始采样预算。

项目 原始设置与含义
代码数据 2020年5月收集的公共GitHub仓库,179GB唯一Python文件,规则过滤后159GB
模型与预算 最高12B,代码阶段训练100B token;Adam、175步预热、余弦学习率衰减
tokenizer 增加不同长度空白串token,代码表示约减少30%token;因此比较token预算时需注意编码差异
Codex-S 进一步监督适配,学习率为代码阶段的1/10,验证损失平台后停止,少于10B token
HumanEval 164个手写问题,每题200样本,估计pass@1/10/100;top-p=0.95
采样温度 按k选择;基础模型常用pass@1温度0.2、pass@100温度0.8,而部分图固定0.8
APPS 另测5000测试问题,包含完整程序和输入输出格式,最多采样1000候选
重复边界 大量采样降低生成估计方差,不等同于多次独立预训练;主表没有每模型训练种子的完整置信区间

人类手写减少直接复制基准的风险,但“手写”并不证明所有算法和题型前所未见。测试通过意味着符合这些测试,不是形式化证明所有可能输入均正确。

自构例子: 函数要求返回不大于 nn 的偶数,模型写 range(n),大多数奇数输入测试可能通过,但偶数边界会漏掉 nn。参考答案的BLEU可能很高;补一个边界测试才发现问题。若5个候选中1个正确,pass@5为成功,但没有可靠测试时选择器仍可能返回另4个之一。

证据一:表1。 Codex-12B的pass@1为28.81%,pass@10为46.81%,pass@100为72.31%;GPT-J 6B为11.62%、15.74%、27.74%。这是专门代码训练后更强功能合成能力的证据,但模型大小、代码量与训练分布都不同,并非只改变一个变量的消融。

证据二:图1与图5、图6。 图1明确所有样本温度0.8,摘要和部分展示使用的基础模型100样本数值约70.2%;表1在相应采样配置下为72.31%。不能把不同温度口径的数字当成相互矛盾的同一次实验,也不能把各个k最优配置说成固定一套采样策略。图5说明大k通常更受益于多样性,而单样本更需要高概率正确实现。 pass@k 图中的 k 是候选数;单提交选择图的 oracle 已知道测试是否通过。可部署排序线与 oracle 覆盖线之间的差距才是选择器问题。

Codex模型参数量与pass@1、pass@100的关系
原文图形摘引:Mark Chen等,2021,图6,PDF第5页;核对原文。原版权保留。

Codex与Codex-S在不同模型规模和候选排序方法下的通过率
原文图形摘引:Mark Chen等,2021,图1,PDF第2页;核对原文。原版权保留。

Codex采样温度、候选数量与pass@k之间的关系
原实验图摘引:Mark Chen等,2021,图5;核对原文。原版权保留。

证据三:图1与图7、图10。 固定图1口径下,Codex-S单样本约37.7%,100候选中按平均对数概率选择约44.5%,若用测试挑出正确候选则约77.5%。44.5与77.5之间的差距就是选择能力缺口;潜在正确代码已经存在于集合,不表示系统能无测试地识别它。

Codex-S与Codex在模型规模及候选排序上的两组对照
原文图形摘引:Mark Chen等,2021,图10,PDF第9页;核对原文。原版权保留。

Codex候选数量增加时五种候选排序方法的通过率
原文图形摘引:Mark Chen等,2021,图7,PDF第6页;核对原文。原版权保留。

证据四:图8。 正确与错误程序的BLEU分布明显重叠,支持文本相似度不适合作为唯一代码正确性指标。换变量名或改写循环可能不改变功能,漏掉一个等号却可能改变边界行为,因此需要执行式评价。不过测试自身也要覆盖边界,不能把BLEU的局限变成测试集完美的结论。

四个HumanEval问题中正确与错误程序的BLEU分数分布
原文图形摘引:Mark Chen等,2021,图8,PDF第6页;核对原文。原版权保留。

证据五:表2,APPS。 Codex在入门题raw pass@1为4.14%,raw pass@1000为25.02%;经过题面公开样例过滤后的pass@1为22.78%。这里“filtered pass@1”已经花费1000候选预算,不是只生成一个答案。更难竞赛题即使raw pass@1000也仅3.23%,说明HumanEval成绩不能代表所有编程任务。

五、有限测试和选择器限制仍留下交付失败

贡献包含领域训练、独立函数监督数据整理、可执行基准和低方差pass@k估计。它没有提出全新Transformer结构。更长期的思想是将“生成分布覆盖”和“验证选择能力”拆开衡量,这对后续推理时扩展与代码Agent都重要。

作者讨论长操作链、变量绑定和说明理解的困难;多个局部合理步骤不一定组合成正确程序。Code-S的训练问题还会剔除模型100次都解不出的题,因而可能偏向当前模型能够覆盖的分布。这是过滤设计带来的选择效应,不应被称为自动得到均匀难度的理想数据。

六、从单函数执行走向仓库修复与选择协议

单函数通过测试之后,SWE-bench把问题扩展到真实仓库定位和回归;PAL把代码当作解题中间表示。二者借用执行能力,但任务成功条件不同。

自测与答案

1. pass@100为70%能否理解为实际推荐代码有70%正确率?

不能。它表示100候选集合里至少一个通过的题目比例,需要知道哪个通过才能达到该水平。实际只返回一项时必须评价选择器;论文平均概率排序明显低于测试oracle。

2. 为何提高温度可能降低pass@1,却提高pass@100?

低温度集中在高概率候选,单次更稳,但多次容易重复同类错误。高温度增加探索不同实现的机会,在大预算下更可能覆盖正确解,也会产生更多坏候选。最优温度随预算变化,应连同k报告。

3. 公开样例过滤后的pass@1为什么必须注明原始候选数?

过滤前已经生成并测试了许多程序,最终只留下一个不代表只用一次计算。若拿它与单次raw pass@1直接比较,会把搜索预算收益错误归为模型单次能力。还应确保隐藏测试没有参与公开选择流程。