HumanEval 是 OpenAI 于 2021 年 7 月在论文 《Evaluating Large Language Models Trained on Code》(Chen et al., 2021)中提出的代码生成基准测试。它包含 164 道手写 Python 编程题,专门用于评估大型语言模型的函数级代码生成能力。
与传统的代码评估基准不同,HumanEval 不是要求模型完成一个完整的项目或回答编程知识问答,而是要模型根据函数签名 + 自然语言描述(Docstring)独立生成完整的函数实现,然后通过预定义的测试用例验证正确性。
HumanEval 的出现标志着一个重要转折——在此之前,代码生成的评估主要依赖于匹配率(BLEU、准确率匹配等)或简单的语法检查,而 HumanEval 采用功能正确性(functional correctness) 作为衡量标准,这更接近真实的编程要求。
截至 2026 年,前沿模型(如 GPT-4o、Claude 3.5 Sonnet、DeepSeek-V3 等)在 HumanEval 上普遍达到 90%-96% 的 pass@1,基准本身已趋于饱和,但其方法论对后续的代码评估产生了深远影响。
此页面是 AI Benchmark 体系 的一部分。
在 HumanEval 诞生之前,代码生成的评估主要面临两个问题:
| 问题 | 传统方法 | HumanEval 的改进 |
|---|---|---|
| 评估指标 | BLEU、准确率匹配(只检查 token 级相似度) | 功能正确性(实际运行测试用例) |
| 任务类型 | 代码补全(给定前半段生成后半段) | 函数级生成(从自然语言到完整函数) |
| 数据来源 | 自动从 GitHub 抓取(含大量噪声) | 手写题目(精准可控) |
| 语言支持 | 主要评估 Python | Python(但已扩展到多语言) |
传统方法的一个典型问题是:模型生成的代码可能在语法上与参考答案很像,但实际运行时却不正确。 例如:
HumanEval 通过手写题目 + 功能测试的方式,从根本上解决了这些缺陷。
OpenAI 在设计 HumanEval 时遵循了三项关键原则:
| 属性 | 数值 |
|---|---|
| 总题目数 | 164 |
| 平均每道题测试用例数 | 7.7 个 |
| 平均函数长度 | 6.8 行 |
| 难度级别 | 入门到中等(相当于 LeetCode Easy/Easy-Medium) |
| 题目来源 | 人类专家手工编写 |
| 语言 | Python 3 |
| 平均题目描述长度 | 约 30 个 token |
每道题目由三部分组成:
1. 函数签名(Function Signature)
def solution(x: int, y: int) -> int:
2. Docstring(自然语言描述)
"""Return the sum of two integers."""
3. 测试用例(Test Cases,隐藏)
assert solution(1, 2) == 3
assert solution(-1, 1) == 0
assert solution(0, 0) == 0
模型的输入是函数签名 + Docstring,输出是完整的函数体。评估时,将生成的函数与隐藏的测试用例一起执行,判断是否全部通过。
下面是 HumanEval 中的几道真实题目示例,展示不同难度和类型:
示例 1:简单类型 — 两数求和
def add(x: int, y: int) -> int:
"""Return the sum of two integers."""
return x + y
难度:极简单 | 测试用例:5 个
示例 2:字符串操作 — 字符串翻转
def reverse_string(s: str) -> str:
"""Return the reversed version of the input string."""
return s[::-1]
难度:简单 | 测试用例:6 个
示例 3:列表操作 — 找出缺失数字
def find_missing(numbers: list) -> int:
"""
Given an array of size n containing numbers from 0 to n,
find the missing number.
"""
n = len(numbers)
expected_sum = n * (n + 1) // 2
actual_sum = sum(numbers)
return expected_sum - actual_sum
难度:中等 | 测试用例:8 个
示例 4:算法 — 判断括号是否有效
def is_valid_parentheses(s: str) -> bool:
"""
Given a string containing just the characters '(', ')', '{', '}', '[' and ']',
determine if the input string is valid.
A string is valid if:
1. Open brackets must be closed by the same type of brackets
2. Open brackets must be closed in the correct order
"""
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping:
top = stack.pop() if stack else '#'
if mapping[char] != top:
return False
else:
stack.append(char)
return not stack
难度:中等 | 测试用例:12 个
HumanEval 的 164 道题目大致可分为以下类别:
| 类别 | 占比 | 示例 |
|---|---|---|
| 基本运算和字符串操作 | ~25% | 字符串翻转、字符计数、子串查找 |
| 列表和数组操作 | ~20% | 数组去重、排序、求和、筛选 |
| 数学计算 | ~20% | 最大公约数、素数判断、斐波那契 |
| 数据结构操作 | ~15% | 树遍历、链表反转、栈/队列操作 |
| 基础算法 | ~15% | 二分查找、排序实现、贪心算法 |
| 位运算和特殊运算 | ~5% | 奇偶判断、二进制表示、位计数 |
HumanEval 采用 pass@k 作为核心评估指标,其含义是:
模型生成 k 个候选答案,其中至少有一个能通过所有测试用例的概率。
这个指标的设计反映了代码生成的一个核心现实:一次生成完美代码是困难的,但生成多次后选一个对的相对容易。
pass@k 的数学定义如下:
其中:
为了理解这个公式,让我们看一个具体的例子:
场景:对于一个问题,我们让模型生成 个候选答案,其中 个是正确的。
计算 pass@1(只生成 1 次,正确的概率):
即模型一次生成就正确的概率是 30%。
计算 pass@10(生成 10 次,至少 1 个正确的概率):
因为 且 ,所以 10 个样本中必然包含正确的一个。
现在考虑另一种情况:(只有 1 个正确样本):
再考虑极端情况:(没有一个正确的):
这意味着无论采样多少次,正确概率始终为 0。
| pass@k | 含义 | 典型值(优秀模型) |
|---|---|---|
| pass@1 | 一次就能搞定 | 80%-96% |
| pass@10 | 试 10 次能有一对 | 95%-99% |
| pass@100 | 试 100 次能有一对 | 98%-100% |
重要提示:pass@10 并不是简单地等于 (其中 是 pass@1),因为 pass@k 是基于多次采样的无偏估计,实际计算要考虑样本间的相关性。
在实际评估中,为了避免过高的方差,通常的做法是:
下面是 HumanEval pass@1 得分随模型发展的完整演变史:
| 模型 | 发布时间 | HumanEval pass@1 | 备注 |
|---|---|---|---|
| GPT-3 (175B) | 2020-05 | ~0% | 几乎无法生成功能性代码 |
| Codex (12B) | 2021-07 | 28.81% | HumanEval 提出时就是如此 |
| Codex (12B) S | 2021-07 | 37.70% | 加大采样次数 |
| Codex (12B) 重排 | 2021-07 | 47.00% | 使用重排序策略 |
| GPT-Neo 2.7B | 2021-03 | 6.40% | EleutherAI 开源模型 |
| GPT-J 6B | 2021-06 | 11.60% | 使用 OneFlow 优化 |
| CodeGen 16B | 2022-03 | 29.28% | Salesforce 多阶段训练 |
| CodeGen 16B Mono | 2022-03 | 35.98% | 在 Python 上单阶段微调 |
| PaLM 540B | 2022-04 | 18.60%* | *在 HumanEval 上的早期结果 |
| LaMDA 137B | 2022-05 | 14.00% | 对话模型 |
| Codex (12B) | 2022-06 | 72.30% | 使用 self-debug + feedback |
| InCoder 6.7B | 2022-04 | 15.20% | Meta 的填充式代码生成 |
| CodeGen 16B Multi | 2022-03 | 18.38% | 多语言训练 |
| PaLM 540B | 2022-10 | 33.60% | 代码数据训练后的结果 |
| StarCoder 15B | 2023-05 | 33.57% | BigCode 开源模型 |
| Code LLaMA 34B | 2023-08 | 53.70% | Meta 代码专用 LLaMA |
| GPT-4 | 2023-03 | 87.00% | 一次重要突破 |
| Code LLaMA 34B | 2023-08 | 74.80% | Python 持续训练 |
| DeepSeek-Coder 33B | 2023-11 | 75.00% | 开源突破 |
| Mixtral 8x7B | 2023-12 | 40.20% | 混合专家模型 |
| Gemini Ultra | 2023-12 | 74.40% | Google 旗舰 |
| Claude 3 Opus | 2024-03 | 84.90% | Claude 的代🐭第一次 |
| GPT-4 Turbo | 2024-04 | 90.20% | 突破 90% |
| DeepSeek-V2 | 2024-05 | 85.00% | MoE 架构 |
| Qwen2-72B | 2024-06 | 86.60% | 阿里巴巴 |
| Claude 3.5 Sonnet | 2024-06 | 92.00% | 成本大幅降低 |
| GPT-4o | 2024-05 | 90.50% | 原生多模态 |
| Llama 3.1 405B | 2024-07 | 89.00% | Meta 最大开源 |
| DeepSeek-Coder-V2 | 2024-06 | 92.70% | 开源新标杆 |
| DeepSeek-V3 | 2024-12 | 93.40% | 671B MoE |
| Gemini 2.0 Flash | 2024-12 | 91.50% | 速度快/准 |
| Claude 3.5 Haiku | 2025-02 | 94.00% | 小模型也突破 93% |
| GPT-4.1nano | 2025-04 | 95.50% | 最新前沿 |
| Claude 4 Sonnet | 2025-05 | 96.20% | 当前最高水平 |
从上表可以清晰地看到 HumanEval 上的关键突破:
除了 pass@1,High-pass 指标的收敛速度更快:
| 模型 | pass@1 | pass@10 | pass@100 |
|---|---|---|---|
| Codex (12B) | 28.81% | 46.81% | 72.31% |
| CodeGen 16B | 29.28% | 51.51% | 74.47% |
| Code LLaMA 34B | 53.70% | 76.50% | 91.20% |
| GPT-4 | 87.00% | 95.00% | 99.00% |
| DeepSeek-Coder-V2 | 92.70% | 98.80% | 99.80% |
| Claude 4 Sonnet | 96.20% | 99.50% | ~100% |
这说明:对于前沿模型,只要给它多次机会,几乎总能生成正确的代码。
HumanEval 的评估流程如下:
输入: 模型的代码生成 API
问题集 (164 道)
采样参数 (temperature, top_p, n_samples)
Step 1: 对每个问题,用模型生成 n 个候选样本
Step 2: 解析每个样本,提取函数体
Step 3: 将函数体 + 预定义的测试用例拼接成完整 Python 脚本
Step 4: 运行 Python 脚本,检查是否通过所有测试
Step 5: 统计通过数 c,用无偏估计公式计算 pass@k
Step 6: 对 164 个问题求平均
输出: pass@1, pass@10, pass@100
典型采样参数:
temperature = 0.8(较高的温度增加多样性)top_p = 0.95n = 200 到 1000 个样本/问题HumanEval 使用 Python 3 标准库运行,不依赖第三方包。评估环境的软硬件要求很低:
# 运行 HumanEval 评估
python3 evaluate_functional_correctness.py path/to/samples.jsonl
# 输出格式
# {
# "pass@1": 0.9280,
# "pass@10": 0.9815,
# "pass@100": 0.9988
# }
对于 164 个问题 × 200 个样本的评估,在单台没有 GPU 的机器上大约需要 30-60 分钟完成测试用例执行。
| 变体 | 作者 | 年份 | 改动 |
|---|---|---|---|
| HumanEval+ | EvalPlus 团队 | 2023 | 扩充测试用例,提升难度 |
| HumanEval-X | 清华/智谱 | 2023 | 拓展到多种编程语言 |
| MultiPL-E | University of Illinois | 2022 | 拓展到 10+ 语言 |
| HumanEval-XL | Facebook AI | 2023 | 题目数扩充到 1000+ |
| HumanEval-Plan | MSR | 2024 | 要求先生成计划再写代码 |
HumanEval+ 是 EvalPlus 项目的重要组成部分,它对 HumanEval 的 164 道题补充了 80× 到 100× 数量的额外测试用例:
| 指标 | HumanEval | HumanEval+ |
|---|---|---|
| 总测试用例数 | ~1,260 | ~20,000+ |
| 每道题平均测试数 | 7.7 | ~120 |
| 覆盖情况 | 基础功能 | 边界条件、性能压力 |
| GPT-4 pass@1 | 87.0% | 82.0% |
为什么 HumanEval+ 的分数更低?
因为原始 HumanEval 的测试用例过于简单,很多模型可以通过「表面正确」的代码骗过测试。例如:
# 原始问题:找出列表中第 k 大的数
def find_kth_largest(nums, k):
# 作弊方案——只处理了排序
return sorted(nums)[-k]
# 原始测试用例只检查简单的 [3,2,1,5,6,4], k=2 → 5
# 作弊方案通过了,因为它恰好能处理这个简单情况
# HumanEval+ 的额外测试用例:
# find_kth_largest([1], 1) → 1
# find_kth_largest([3,2,3,1,2,4,5,5,6], 4) → 4
# 作弊方案在这里仍然可能通过,但更复杂的问题会暴露缺陷
HumanEval+ 对模型的区分度更好,许多在原始 HumanEval 上拿到 90%+ 的模型在 HumanEval+ 上会下降 5-10 个百分点。
MultiPL-E 将 HumanEval 的问题集翻译成 10+ 编程语言,包含:
| 语言 | 可用题目数 | 用途 |
|---|---|---|
| Python | 164 | 原始基准 |
| JavaScript | 163 | Web 开发评估 |
| TypeScript | 158 | 类型化编程 |
| Java | 160 | 企业开发 |
| C++ | 156 | 系统级编程 |
| Go | 162 | 并发编程 |
| Rust | 148 | 安全系统编程 |
| Ruby | 155 | Web 开发 |
| PHP | 152 | Web 后端 |
| Swift | 138 | Apple 生态 |
| Julia | 112 | 科学计算 |
| R | 120 | 数据科学 |
MultiPL-E 的评估发现一个重要结论:擅长 Python 的模型不一定擅长其他语言,这为多语言代码模型的开发提供了方向。
| 局限 | 说明 | 影响程度 |
|---|---|---|
| 题目数量少 | 仅 164 题,统计意义有限 | ⭐⭐⭐ |
| 难度偏低 | 多为入门级算法,与实际工程差距大 | ⭐⭐⭐⭐⭐ |
| 语言单一 | 仅支持 Python(原始版) | ⭐⭐⭐ |
| 测试用例简单 | 边界条件覆盖不足,易被"碰巧正确"的代码欺骗 | ⭐⭐⭐⭐ |
| 函数级粒度 | 不测试类设计、模块组织、代码可维护性 | ⭐⭐⭐⭐ |
| 无错误信息 | 代码错误时不给出反馈,不测试调试能力 | ⭐⭐⭐ |
| 数据泄露风险 | 题目简单,可能出现在训练数据中 | ⭐⭐⭐ |
HumanEval 的一个著名问题是模型可以通过硬编码答案来"欺骗"评估。因为测试用例是有限且公开的,模型可以记住或猜出正确的输出:
# 题目要求:返回两个数字的和
def add(x, y):
# 作弊方案:不计算,直接返回常见测试值
if x == 1 and y == 2:
return 3
elif x == 0 and y == 0:
return 0
elif x == -1 and y == 1:
return 0
elif x == 100 and y == 200:
return 300
else:
return 0 # 剩下情况全返回 0
虽然在 164 道题中大规模硬编码不太现实,但模型在训练时见过类似题目会导致「虚假高分」。这也是后来 EvalPlus 等变体增加更多随机边界测试的原因之一。
HumanEval 评估的是函数级代码生成,而真实软件开发涉及更多能力:
| 能力 | HumanEval | 实际工程 |
|---|---|---|
| 单个函数生成 | ✅ 核心评估 | ✅ |
| 多个函数协同 | ❌ | ✅ |
| 类/模块设计 | ❌ | ✅ |
| 错误处理 | ❌ | ✅ |
| 代码审查 | ❌ | ✅ |
| 调试修复 | ❌ | ✅ |
| 系统设计 | ❌ | ✅ |
| 依赖管理 | ❌ | ✅ |
| API 调用 | ❌ | ✅ |
| 测试编写 | ❌ | ✅ |
这也解释了为什么 HumanEval 分数高的模型在实际编码任务中表现可能并不出色。
截至 2026 年,HumanEval 已从「核心评估基准」转变为:
对于 2026 年的模型评估,推荐使用以下更具挑战性和实际意义的基准:
| 基准 | 评估内容 | 推荐理由 |
|---|---|---|
| SWE-bench | 真实 GitHub Issue 修复 | 端到端工程能力 |
| LiveCodeBench | 最新编程竞赛题 | 防止数据泄露 |
| HumanEval+ | HumanEval 增强版 | 更好的区分度 |
| BigCodeBench | 大规模代码生成 | 更全面的覆盖 |
| Abstention & Avoidance | 模型何时应该拒绝回答 | 安全性评估 |
根据 2026 年的观察,HumanEval 分数与实际编码能力的大致对应关系:
| HumanEval pass@1 | 编码能力等级 | 典型应用场景 |
|---|---|---|
| < 50% | 初学者 | 简单的代码补全工具 |
| 50% - 70% | 入门级 | 基本的代码助手,能处理常见算法题 |
| 70% - 85% | 熟练级 | 能编写常见函数,需人工审核复杂逻辑 |
| 85% - 92% | 专业级 | 可靠生成大部分函数,偶有边界失误 |
| 92% - 96% | 专家级 | 函数级代码基本可靠,需评估工程级任务 |
| > 96% | 前沿 | 函数级代码高度可靠,关注更复杂场景 |
不要只依赖 HumanEval 一个指标,建议建立多维度的代码评估体系:
代码评估体系
├── 基础能力(HumanEval / MBPP)
│ └── 函数级代码生成正确性
├── 工程能力(SWE-bench / LiveCodeBench)
│ └── 真实 Issue 修复、复杂编码
├── 多语言能力(MultiPL-E / BigCodeBench-ML)
│ └── 不同编程语言的生成质量
├── 安全能力
│ └── 是否生成漏洞代码、是否能识别恶意请求
├── 测试能力
│ └── 是否能自动生成测试用例
└── 工具使用
└── 是否能正确调用 API、使用库
在对比不同模型的代码能力时,建议:
对于实际使用场景,HumanEval 的成绩可以作为参考,但不能替代真实的评测:
# 代码助手场景:HumanEval good → can generate correct function
# HumanEval bad → consider other solutions
# 但实际还需要检查:
# - 代码风格是否符合项目规范
# - 错误处理是否完善
# - 性能是否可接受
# - 是否易于维护和扩展
HumanEval 作为第一个采用功能正确性评估的代码生成基准,在 AI 代码生成领域具有里程碑意义。它简单、清晰、可复现,推动了整个领域从「语法级匹配」转向「功能级验证」。
然而,截至 2026 年,HumanEval 已基本完成其历史使命:
对于一个合格的当代代码评估体系,建议将 HumanEval 作为起点而非终点,结合 SWE-bench、LiveCodeBench 和 HumanEval+ 来全面评估模型的实际编码能力。
此页面是 AI Benchmark 体系 的一部分。