Evaluating Large Language Models Trained on Code

  • 关联论文:2107.03374
  • 作者:Tom
  • 更新:2026-07-29

一句话结论

OpenAI 将 GPT 模型在 GitHub 代码上微调得到 Codex,发现重复采样(repeated sampling)是一种出乎意料地有效的代码生成策略:单个样本只能解决 28.8% 的编程问题,但用 100 个样本时即可解决 70.2%;同期 GPT-3 完全无法通过 HumanEval 的任何题目。

解决什么真问题

在 Codex 之前,代码生成模型的评估缺乏统一标准——常用指标(如 BLEU)无法衡量生成代码的功能正确性。更根本的问题是:LLM 能否真正理解人类意图并写出可执行的程序?本文发布了 HumanEval 数据集(164 道带 docstring 的编程题,每题附有单元测试),并证明仅靠自回归语言模型微调代码,就能解锁有实用价值的代码生成能力,这直接催生了 GitHub Copilot。

核心方法

HumanEval 数据集

每道题由三部分组成: 1. Docstring:描述函数行为的自然语言说明 2. 函数签名:类型注解完整的 Python 函数头 3. 单元测试:验证函数正确性的 assert 语句

评估指标为 pass@k

$$ \text{pass}@k := \mathbb{P}\left[\text{at least one of }k\text{ samples passes all tests}\right] $$

实际操作中使用不偏估计: $$ \text{pass}@k = \frac{1}{n}\sum_{i=1}^{n}\mathbb{1}\left[\text{cat }k_i \geq c\right],\quad c = \lceil T/k \rceil $$ 其中 $T$ 为总采样数,$k_i$ 为第 $i$ 题通过测试的样本数。

Codex 模型

  • 架构:GPT 架构,在 GitHub 代码上微调(Codex-12B 最大)
  • 关键发现:从头训练的代码模型(GPT-Neo)几乎无效,但微调GPT 权重后能力急剧涌现
  • Codex-S:在 Codex 基础上进一步在「正确实现独立函数的代码」上微调,pass@1 从 28.8% 提升至 37.7%

关键实验与数据

模型 pass@1 pass@100
GPT-Neo-2.7B(代码微调) 6.4% 21.3%
GPT-J-6B(代码微调) 11.6% 27.7%
Codex-12B 28.8% 70.2%
Codex-S-12B 37.7% ——
GPT-3(baseline,无微调) ≈0% ≈0%

另一个关键发现:100 次采样下,70.2% 的问题能被解决,说明重复采样+测试过滤是工程落地的可行路径。

亮点与局限

亮点

  1. HumanEval 成为代码 LLM 评估事实标准,后续几乎所有代码生成论文都报告此指标
  2. pass@k 指标设计精妙:解决了采样评估的不偏估计问题
  3. 首次证明「LLM 可以在代码上涌现能力」,为 Copilot 奠定基础
  4. 对采样策略的系统分析,直接影响后续如 AlphaCode、FIM 等工作

局限

  1. 难以处理长链操作依赖(docstring 描述复杂多步逻辑时性能骤降)
  2. 变量绑定问题:描述操作与变量绑定关系时容易出错
  3. 测试用例无法覆盖所有边界情况,安全关键场景仍有风险
  4. 没有解决代码的「意图理解」问题——模型只是在拟合 GitHub 分布

对工程落地的启发

  1. 采样+测试过滤是工程可行路径:与其追求更高的 pass@1,不如部署多次采样+自动测试的 pipeline(这成为后续 Code Runner / Copilot 的核心技术)
  2. ** HumanEval 可作为代码 LLM 的入门评估集**:快速验证模型基础能力
  3. 代码补全类产品应设计多候选结果展示+轻量测试机制,而非仅返回单一结果
  4. 依赖代码生成的产品的风险评估:本文提出的安全分析框架(Hazard Analysis)值得参考

与同方向工作的关系

工作 关系 差异点
AlphaCode(2022) 后继 引入竞赛级评测,专注推理能力
CodeGeeX 同代 多语言支持,但未建立类似 HumanEval 的标准
PaLM-Coder 后继 更大模型,更多采样
StarCoder 后继 开放权重,The Stack 数据集
GPT-4 代码能力 后继 多模态输入,更强推理

HumanEval 的意义超越了 Codex 本身——它定义了代码 LLM 评估的元问题:不是「生成的代码像真代码吗」,而是「生成的代码能通过测试吗」。这一思路持续影响 2024-2026 年的代码 Agent 评测设计。

适合谁读

  • LLM/代码生成方向研究人员:必读,理解 pass@k 设计和 HumanEval 范式
  • AI 产品经理/工程师:理解代码 LLM 的能力边界与采样策略
  • 安全/合规团队:理解代码生成的潜在风险评估框架
  • 对代码 Agent 感兴趣的人:理解 Code Generation → Code Reasoning → Code Agent 的演进起点

工程落地与核查(Jay)

事实核查

  • "164 道带 docstring 的编程题":原文(2107.03374)确实说明 HumanEval 包含 164 个人工编写的编程题,此数字有据可查。
  • "pass@1 28.8%,pass@100 70.2%":原文 Table 1 给出 Codex-12B 的具体数字,此处引述正确。
  • "GPT-3 baseline ≈0%":原文数据与描述吻合,GPT-3 未在代码上微调,此数字合理。
  • "Codex-S pass@1 37.7%":原文 Table 1 有 Codex-S 的 pass@1 数字,引述正确。
  • "OpenAI 将 GPT 模型在 GitHub 代码上微调":原文明确,GPT-3 初始版与 Codex 为同一时期工作,此描述正确。

工程落地路径与坑

当前价值定位(2026年)

HumanEval 作为基准已严重饱和——GPT-4o / Claude-3.5 / Gemini-2.5 在 HumanEval 上均达 90%+,pass@1 已无区分度。但作为快速入口评估仍有价值,尤其在评测新开源模型(7B~13B 参数量)时。

采样+测试 pipeline 工程实践

输入:问题描述 + n(采样数)
1. 用 LLM 采样 n 个代码完成
2. 对每个完成运行单元测试(超时设 5~10s)
3. 任意一个通过 → pass;全部失败 → fail
4. 收集 fail 样例用于分析

关键工程参数: - n=100 是原文数字,实际生产中可用成本-质量曲线选 n(如 n=10 达 50% 覆盖,n=50 达 65%,边际收益递减) - 超时设置:单次运行超时太短会误杀正确解(递归/复杂算法),太长影响吞吐;建议默认 10s,可配置 - 沙盒执行:代码执行必须隔离,推荐 Docker container + 网络禁用 + 内存限制,防止恶意代码

pass@k 不偏估计的实际坑

原文不偏估计公式在 $T$(总采样数)不够大时方差大。工程上: - 若 $c = \lceil T/k \rceil = 0$,则 pass@k = 1.0(除非 T=0),这是公式边界,不是真实能力 - 建议用 tatsu-lab/alpaca_eval 的 "pass@k by sampling without replacement" 实现,比原文无偏估计方差更小

HumanEval 之外的工程评测组合

2024-2026 年新基准: - MBPP(Microsoft Programming Prompts):比 HumanEval 简单,适合快速初筛 - LiveCodeBench:动态更新,持续测新题,防止 overfit 到固定题库 - SWE-bench:真实 GitHub issue → 代码修复,难度高,适合 agent 评测 - BigCodeBench:更复杂的指令,区分度更好

已知局限与坑

  1. HumanEval 过拟合:2023-2024 年大量模型在 HumanEval 上刷榜,真实编程能力被高估;评测新模型建议用 held-out 集
  2. docstring 质量依赖:HumanEval 题目由人类编写但仍可能有歧义,模型可能对特定表述模式过拟合
  3. 多轮对话/跨文件上下文:HumanEval 只测单函数生成,真实代码助手需要多轮修改+跨文件理解,HumanEval 完全测不到这个维度
  4. 安全风险:生产环境跑 LLM 生成的代码执行必须有沙盒,未隔离的执行历史上已有多个 RCE 案例(2023 GitHub Copilot 社区报告)

推荐验证清单

  • [ ] 用 HumanEval + MBPP + LiveCodeBench 三合一快速评测新模型,不用单一基准
  • [ ] 采样 pipeline 测通过率曲线,找到成本-质量拐点(通常是 n=20~50)
  • [ ] 生产代码执行必须走沙盒,禁止在主进程直接 eval/exec
  • [ ] 分析 fail 样本:若是 "差一点就对了"(边界条件)vs "完全跑不通"(语义理解错误),两类失败处理策略完全不同