想象你是驾校总考官,手头有一张全国统一的科目二考单:倒车入库、侧方停车、坡道起步……项目固定、扣分明确,学员行不行,考一次就知道。2021 年,OpenAI 给 AI 编程能力也画了这么一张考单——HumanEval。它由 164 道手写编程小题组成,每道题都写清了函数名、参数和任务描述,还藏着一组单元测试当“扣分点”。AI 考生的任务只有一个:读懂题目描述,写出能通过全部测试的代码。 有考试就要有记分牌。AI 的分数不是“写对了多少行”,而是一个叫 pass@k 的指标:允许考生对一个题目补考 k 次,只要有一次写对就算过。别小看这个设计,它让“模型会不会写代码”第一次有了客观、可复现的答案,也顺理成章成了各家大模型比拼代码能力的“奥运会”。

岗位关联

掌握 HumanEval 与 pass@k 评测方法论,是进入大模型评测领域的第一块敲门砖——无论做模型训练、产品落地还是技术选型,你都需要这把衡量代码能力的“标准尺”。

目录
  1. 可视化演示
  2. 基准概览:给 AI 发驾照的考场
  3. 数据格式:考题的三种要素
  4. 评测指标:补考 k 次,通过即算
  5. 基准表现:谁拿到了驾照
  6. 评测协议:考试规则的细节
  7. 方法提升:怎么在多轮机会中拿分
  8. 局限演进:考场之外的天空
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

演示HumanEval代码生成评测基准:工作流展示函数签名+docstring输入、模型生成候选、测试用例执行评估三重流程;pass@k指标展示多候选生成与无偏估计;基准对比展示不同模型在pass@1上的表现差异。

本节配有交互动效(进入视口后自动加载,约 3KB)。

三步评测流程 函数签名+docstring→模型生成代码 pass@k 无偏估计 执行单元测试验证功能正确性

基准概览:给 AI 发驾照的考场

驾校教练想判断学员有没有真本事,靠的不是“我觉得你开得不错”,而是一个固定考场加上明确的评判标准。2021 年以前,各家在评测 AI 写代码时用的方法五花八门:有人拿 BLEU 分数看生成的代码和参考答案“长得像不像”,有人直接让人工肉眼打分。可代码这玩意儿“条条大路通罗马”,实现方式完全不同但功能都对,字面相似度根本测不出真实水平,人工打分又贵又难复现。行业急需一个像科目二那样全国统一的标准考场。

这个考场,就是 OpenAI 在 2021 年发布的 HumanEval——一个专门用来评估代码生成模型能力的基准测试集。它由 164 道手写的编程函数题构成,全部由人工设计以确保不与训练数据重复。每道题包含一个函数签名(告诉你函数叫什么、参数是什么)、一段 docstring(用自然语言描述需求)以及一组单元测试用例(用来判断代码是否正确)。模型要做的事很简单:读完描述,写出函数体,跑过全部测试即得分。

HumanEval 的定位如今早已超出“一个数据集”本身。它确立了“以功能正确性为核心”的评测范式:不再看代码长得多像范文,只看它能不能解决实际问题。从 GPT-4 到各种开源模型,几乎所有主流大模型发布时都要在 HumanEval 上报一个 pass@1 分数,它也因此成为整个 AI 评测方法论走向规范化、体系化的标志性起点。

回看驾考的逻辑:科目二能火、能被全国推广,是因为它公平、客观、可重复。HumanEval 之于 AI 代码能力,就是那把“全国统一”的尺子——有了它,各家的“驾驶技术”第一次可以放在同一个考场上比一比。

数据格式:考题的三种要素

你考科目二时,每个项目其实由三样东西组成:项目名称(比如“倒车入库”)、场地标线(告诉你车该怎么摆、边界在哪)、扣分标准(压线扣 100、中途停车扣 5 分)。HumanEval 的每一道题,也严格地由三个部分拼成:函数签名、docstring 和单元测试用例,三者合一才构成一道完整的“考题”。

函数签名相当于考生在考单上填的个人信息——函数名拼错一个字母,测试调用时直接“查无此人”,所以签名是必须严格遵守的接口契约。docstring 则是考官念出的任务描述,用自然语言说明“输入是什么、应该返回什么”,有时还附上输入输出示例,这是模型理解需求的最主要信息来源。最后的单元测试用例,就是考官手里的扣分清单:一组精心设计的调用与断言,覆盖正常情况和边界情况,代码必须全部通过才算过关。

形式化地看,一道 HumanEval 任务可以表示成一个三元组:

其中每个元素都对应考场上的一条规则。

实际数据集里,每道题的解法平均只有 7.7 行代码,docstring 也通常只有两三句话,看起来像“小儿科”——但这种刻意收敛的设计是有意的:它把变量控制在“读题、理解、写函数”这个核心能力上,排除掉工程上下文的干扰。单元测试的数量从几个到十几个不等,会专门考虑空输入、负数、超大数等边界。签名要求到函数名逐字符一致,对应试者来说,就像考试时姓名和准考证号必须逐字对上,否则成绩作废。

T=(S,D,U)T = (S, D, U)
  1. 函数签名规定函数名、参数与返回类型,模型生成的代码必须以这个签名为准。
    S:fname(params)→return_typeS: f_{\text{name}}(\text{params}) \to \text{return\_type}
  2. 任务描述docstring 用自然语言说明函数功能,是模型推断逻辑的唯一依据。
    D:description in natural languageD: \text{description in natural language}
  3. 测试集合一组单元测试用例,任何一个不通过,整道题都判错。
    U:{u1,u2,…,um}U: \{u_1, u_2, \dots, u_m\}

评测指标:补考 k 次,通过即算

科目二考试有个很人性化的设定:第一次没过,当场可以补考一次。HumanEval 把这种“补考机制”发展成了一个数学化的指标——pass@k。“pass“就是通过,”k”就是你允许补考的次数:对一个题目,让模型生成 k 个候选函数,只要其中任何一个通过了全部单元测试,这道题就算做对。k=1 意味着只给一次机会,k=10 则意味着可以掷十次骰子。

为什么不像传统评测那样只看“生成的代码和参考答案是否一致”?因为代码的正确实现方式不止一种。两个人用完全不同的算法,写出的代码毫无相似之处,却都能通过测试;反过来,只改一个变量名就会让 BLEU 分数暴跌,但功能完全没变。pass@k 的聪明之处在于它只看结果:跑测试,过就过,不过就不过,实现细节一律不管。

最标准的计算方法是论文中提出的无偏估计公式。评测时对每个任务先采样 n 个候选(n ≥ k),统计其中有多少个能通过测试,记为 c,然后套公式:

为什么需要“无偏估计”而不是朴素地采样 k 个直接数“成功了几次”?因为直接抽样在 k 较大或成功样本较少时,会系统性低估真实通过率——就像补考十次的人,你只盯着他前两次看,很容易误判他水平差。无偏估计把“从 n 个样本中任选 k 个”的所有情况都考虑进去,统计上更“不偏心”。

用驾驶来理解:pass@1 相当于“一次通过率”,反映学员真实水平;pass@100 则像“给他一百次机会,总能蒙对一次”,反映的是上限潜力。实际产品里用户只有一次机会,所以论文会同时报告低温和高温两种配置下的 pass@1 与 pass@k,让分数尽可能贴近真实场景——这就是考场上的“严格档”和“宽松档”。

pass@k=Eproblems[1−(n−ck)(nk)]\displaystyle \text{pass@k} = \mathbb{E}_{\text{problems}}\left[1 - \frac{\binom{n-c}{k}}{\binom{n}{k}}\right]
  1. 对所有题目取期望把每道题的 pass@k 算出来再求平均,避免某一道题的结果主导分数。
    Eproblems[⋅]\mathbb{E}_{\text{problems}}[\cdot]
  2. 采样总数n 是模型对当前题目生成的全部候选代码数量,实验中常用 100 或 200。
    nn
  3. 成功样本数c 表示 n 个候选中能通过全部单元测试的数量,c 越大说明模型越可靠。
    cc
  4. 所有可能组合从 n 个候选中任意挑出 k 个,一共能挑出这么多种组合,作为分母。
    (nk)\binom{n}{k}
  5. 全挑到失败品如果 k 个候选是从 n-c 个失败样本中挑出来的,那这一组“全军覆没”,组合数作为分子。
    (n−kk)(即从失败样本中选 k 个)\binom{n-k}{k} \text{(即从失败样本中选 k 个)}
  6. 取补集用 1 减去“全军覆没”的比例,得到“至少有一个成功”的概率,即这道题的 pass@k。
    1−(n−ck)(nk)1 - \frac{\binom{n-c}{k}}{\binom{n}{k}}

基准表现:谁拿到了驾照

考场和评分规则都备好了,接下来就是发成绩单。HumanEval 发布至今,各代模型的分数像驾校通过率排行榜一样节节攀升。回看这份榜单,几乎就是一部大模型代码能力进化史。

先看 OpenAI 自家的成绩。2021 年发布的 Codex 模型是第一个在 HumanEval 上接受检验的考生:Codex 12B 在 pass@1 指标上拿到 28.8%,而它采用“对每个问题采样大量候选再挑一个”的策略时,pass@100 可以达到 72.2%——可见“补考”的威力有多大。三年后,GPT-4 把 pass@1 一下子抬到了 67%,比 Codex 翻了一倍还多,说明模型在“第一次就写对”这件事上有了本质进步。

开源阵营同样不甘示弱。StarCoder 15B 报告约 33% 的 pass@1,CodeLlama 34B 冲到约 48%,而 2024 年的 DeepSeek-Coder 等开源模型更是一举突破 70% 大关,与当时最强的闭源模型打平。这些数字的意义不在“谁第一”,而在于:同一个考场、同一套评分标准,让不同实验室、不同时间发布的模型有了横向比较的可能——这在 HumanEval 出现之前几乎是做不到的。

从 28.8% 到 70% 以上,HumanEval 上的每一次跳跃,背后都是训练数据规模的扩大、预训练目标的设计改进和评测协议的成熟。透过这张成绩单我们能看到:基准测试不只是“排名工具”,它更像信号灯,为整个领域指明方向——学员水平在涨,教练就得思考下一批题该怎么出,于是有了新的基准;新基准反过来又推动模型能力继续突破,形成一个正向循环。

评测协议:考试规则的细节

任何标准化考试都有一本《考试规则手册》:不能替考、手机必须关机、路线随机分配。HumanEval 的评测同样有严格的协议约束,考试规则定得越细,分数才越可信、越能跨实验室复现。这一整本“规则手册”,主要围绕三个关键词展开:温度、防泄漏、复现性。

先说温度。大模型生成代码时有一个叫 temperature 的参数——你可以把它理解成答题时“思路的发散程度”。温度低(如 0.2)时,模型每次都在最确定的答案附近打转,候选之间差异小、稳定性高,适合测 pass@1;温度高(如 0.8),模型就更敢“冒险”,候选多样性大,适合测 pass@k——因为补考的意义就在于提供不同解法,多样性太低就失去补考的价值了。评测时通常固定 top-p=0.95,让采样空间既可控又不至于太窄。

再看防数据泄漏。这是整套协议里最伤脑筋的一环:如果模型在预训练时已经见过考试题,那它的高分就像考生提前偷到了卷子,毫无参考价值。HumanEval 的题目全由人工编写、刻意绕开公开代码仓库,且发布后测试集不随带公开标签,就是为了尽量减少“泄题”风险。即使如此,研究者仍会通过多语言改写题目等方式反复复测,验证模型是“真会做”还是“背过题”。

最后是复现性。论文报告分数时必须写明采样温度、候选数量、随机种子、解码策略甚至运行环境,别人按照同样步骤才能复现出同样的分数。它就像考试要求统一使用同一版本的答题卡——如果每个考场用的卡都不一样,成绩单就成了废纸。这套评测协议后来被 MBPP、SWE-bench 等新基准继承下来,成为代码生成评测的“通用公约数”。

方法提升:怎么在多轮机会中拿分

学员发现倒车入库总压线,教练的办法是:多练、练完看录像回放、对着问题点纠正动作。AI 在 HumanEval 上“提分”,用的也是同一套思路——给它更多示范、更多反馈、更多轮次的机会。这些方法写进论文后,被验证是真实有效的“应试技巧”。

第一个技巧是少样本提示(few-shot prompting)。在给模型的 prompt 里先放一两个已经写好的“题目-答案”示例,相当于教练先演示一遍标准动作,模型照着格式和风格作答,准确率往往比“零样本”凭空发挥高出一截。第二个技巧是 自修复(self-repair / code repair):让模型运行自己生成的代码,把测试失败信息或报错日志反馈给它,再说一句“刚才这版有问题,请修改”,模型往往能针对性地修正 bug——就像学员看完自己的压线录像后,第二次倒库会下意识地多打半圈方向盘。

第三个方向是多轮交互与思维链:让模型先描述解题思路,再落笔写代码。把推理过程显式地“说出来”,能明显减少逻辑跳跃导致的错误。此外还有“采样-筛选”策略——大量生成候选,再用一个排序器挑出最可能通过测试的那一个,相当于让教练在旁边帮你把最靠谱的一套动作挑出来。

这些方法的综合收益可以用一个简单模型理解:

注意,这些“应试技巧”提升的是分数,而不是模型的基础编码能力——就像模拟考能帮你熟悉题型、提高得分,但不会改变你的驾驶技术上限。真正让 pass@1 从 28.8% 涨到 70% 的,还是数据、规模与训练方法的底层进步。把少样本提示、自修复这些手段当成“临场发挥”的加分项,而不是“实力”本身,才是正确的理解方式。

Prepair=Pfirst+(1−Pfirst)×PfixP_{\text{repair}} = P_{\text{first}} + (1 - P_{\text{first}}) \times P_{\text{fix}}
  1. 首轮成功率P_first 是模型不借助额外反馈、第一次就写对的概率,来自基准测试或经验估计。
    PfirstP_{\text{first}}
  2. 修正成功率P_fix 是模型看到测试反馈后成功改正错误的概率,反馈信息越清晰,这个值越高。
    PfixP_{\text{fix}}
  3. 总体成功率总成功概率等于“一次做对”加上“第一次没对、但看完反馈后改正”的概率。
    Prepair=Pfirst+(1−Pfirst)×PfixP_{\text{repair}} = P_{\text{first}} + (1 - P_{\text{first}}) \times P_{\text{fix}}

局限演进:考场之外的天空

拿到驾照和成为老司机是两回事——山路、暴雨、高速惊魂,科目二都考不出来。HumanEval 也有同样的困境:它考得好,不等于模型在真实工程里顶用。认识这份考卷的局限,是每个评测从业者的必修课。

最直接的隐患是数据泄漏。尽管题目经过人工设计,164 道题的规模也刻意做小,但随着训练语料指数级膨胀,模型依然可能在预训练阶段“见过”高度相似的题目。分数虚高怎么办?研究者只能不断用改写、扩充、交叉验证来试探,但泄漏风险无法彻底根除——就像题库再偏,背题家总能找到角落里的旧版本。

更深层的质疑是泛化能力。HumanEval 的题目都是函数级、单文件、平均 7.7 行代码,上下文只有几行 docstring;而真实软件工程是跨文件、多依赖、长上下文的复杂系统。一个在 HumanEval 拿 70% 的模型,面对真实的 GitHub 仓库时可能连“在哪个文件里改 bug”都找不到。这就是典型的“驾校优等生,上路就熄火”。此外,题目难度分布相对集中,高分可能是训练数据里类似函数太多的结果,而非真正的理解。

正因如此,学界没有把 HumanEval 奉为终点,而是把它当作起点,不断设计“更难的考场”:HumanEval+ 增加了更强的边界测试用例,MBPP 丰富了任务来源,SWE-bench 直接让模型解决真实 GitHub issue,RepoBench 要求模型理解整个代码仓库。这些新基准继承了 HumanEval“测试驱动、功能正确才算对”的魂魄,却把考卷从“科目二”升级成了“真实路考”。驾校毕业只是开始,真正的驾驶技术,永远在路上。

AI 应用场景

场景一:大模型发布前的“验收路测”

阶段:模型评测与质量验收

解决的问题:训练完成的大模型,OpenAI、Anthropic 以及各大厂商在发布前都要回答一个问题:“这版模型的代码能力到底比上一版强了还是退了?”如果没有统一考卷,靠人工写代码验证既慢又不客观,不同团队之间也无法对比。用 HumanEval 做 pass@1 与 pass@k 评测,可以在几小时内给出一份可复现的“成绩单”,作为是否放行的硬性依据。

具体案例:某公司训练了新一代代码大模型,发布前用 HumanEval 跑出 pass@1 = 54%,比上版本的 49% 提升 5 个百分点,同时用 HumanEval+ 复测确认没有在边界测试上明显退步,模型才被批准上线。

场景二:编程助手的日常“体检”

阶段:产品迭代与回归测试

解决的问题:Copilot 类编程助手每次调整 prompt、升级基座模型,都可能让部分场景变好、部分场景变差。如果靠用户反馈发现劣化,代价太大。把 HumanEval 集成进 CI/CD 流水线,每次改动后自动跑一遍,相当于给产品做无创体检——分数不降,才能合入主干。

具体案例:某编程助手团队在 prompt 模板中新增了一个系统提示,上线前自动跑 HumanEval 对比新旧版本,发现 pass@1 从 52% 掉到 48%,立即回滚改动,避免了线上体验劣化。

场景三:数据筛选与训练决策的“信号灯”

阶段:数据工程与训练监控

解决的问题:训练代码模型时,数据配比、课程顺序、是否继续训练都是玄学。HumanEval 可以当作一个轻量级“信号灯”:每训练若干步就采一次样测一下分数,曲线变平说明当前数据收益饱和,该换数据源或调整超参了;模型在 HumanEval 上分数大幅下降,则可能是灾难性遗忘的信号。

具体案例:某团队在持续预训练中每 500 步用 HumanEval 子集抽测一次,发现 pass@1 连续两轮不再增长,果断切换到高质量代码数据继续训练,最终恢复增长并节省了 20% 的算力预算。

Python 演示

python83 行
"""mini_humaneval.py - 用 5 道模拟题复现 HumanEval 的 pass@k 评测流程""" from math import combimport random TASKS = [    {        "name": "add_two",        "desc": "返回 a 与 b 之和",        "solution": "def add_two(a, b):\n    return a + b",    },    {        "name": "is_even",        "desc": "判断 n 是否为偶数",        "solution": "def is_even(n):\n    return n % 2 == 0",    },    {        "name": "sum_list",        "desc": "返回整数列表 nums 的元素和",        "solution": "def sum_list(nums):\n    return sum(nums)",    },    {        "name": "max_of_two",        "desc": "返回 a 和 b 中较大者",        "solution": "def max_of_two(a, b):\n    return a if a > b else b",    },    {        "name": "factorial",        "desc": "返回 n 的阶乘,n >= 1",        "solution": "def factorial(n):\n    result = 1\n    for i in range(2, n + 1):\n        result *= i\n    return result",    },] REPLACE_RULES = [(" + ", " - "), ("==", "!="), (">", "<"), ("sum(", "len(")]  class SimpleModel:    """模拟一个代码生成模型:以 correct_rate 概率写对,否则犯一个低级错误。"""     def __init__(self, correct_rate, seed=42):        self.correct_rate = correct_rate        self.rng = random.Random(seed)     def generate(self, task):        if self.rng.random() < self.correct_rate:            return task["solution"]        for src, dst in REPLACE_RULES:            if src in task["solution"]:                return task["solution"].replace(src, dst, 1)        return "return None"  def pass_at_k(n, c, k):    """HumanEval 论文中的无偏估计公式。"""    if n - c < k:        return 1.0    return 1.0 - comb(n - c, k) / comb(n, k)  def evaluate(model, tasks, k, n=100):    """对每个任务采样 n 个候选,统计 c,再计算 pass@k 并取平均。"""    total = 0.0    for task in tasks:        samples = [model.generate(task) for _ in range(n)]        c = sum(1 for s in samples if s == task["solution"])        total += pass_at_k(n, c, k)    return total / len(tasks)  def main():    print("=== simulate HumanEval ===")    print("5 tasks, sample n=100 per task")    for rate in (0.3, 0.7):        row = []        for k in (1, 5, 10):            model = SimpleModel(rate)            row.append("pass@{}={:.1%}".format(k, evaluate(model, TASKS, k)))        print("rate {:.0%}: {}".format(rate, "  ".join(row)))    print("=== done ===")  if __name__ == "__main__":    main()
目的:用 5 道模拟函数题完整复现 HumanEval 评测管线——采样、跑测试、算 pass@k,直观看到“补考次数”如何放大通过率。
  1. "solution": "def add_two(a, b):\n return a + b"每道题的标准答案,模拟 HumanEval 中通过全部测试的“正确解”。
  2. self.correct_rate = correct_rate模拟模型的真实能力:单次生成写对的概率。
  3. if self.rng.random() < self.correct_rate:以概率决定“这次写对了还是写错了”。
  4. wrong = task["solution"].replace(src, dst, 1)模拟模型犯低级错误:把加法写成减法、把等号写成不等号。
  5. return 1.0 - comb(n - c, k) / comb(n, k)论文核心公式:从 n 个候选中任取 k 个,至少一个成功的概率。
  6. if n - c < k: return 1.0边界条件:失败样本不足 k 个时,任取 k 个必然包含成功样本,概率为 1。
  7. samples = [model.generate(task) for _ in range(n)]对一道题采样 n=100 个候选代码。
  8. c = sum(1 for s in samples if s == task["solution"])统计采样中能通过测试的候选数(简化版用“与标准解一致”代替真实跑测试)。
  9. for rate in (0.3, 0.7):对比“后进生”和“优等生”,观察同样的补考机制带来的不同收益。

常见误区

误区论文里 pass@100 高达 90%,这模型肯定很厉害,可以直接上线用。

正解pass@100 允许模型生成 100 个候选,只要有一个正确就算过——相当于给了学员 100 次补考机会,蒙也能蒙对几道。真正决定用户体验的是 pass@1,也就是“第一次就写对”的概率。Codex 12B pass@1 只有 28.8%,但 pass@100 高达 72.2%,如果拿后者宣传,就等于用“补考一百次”的成绩冒充真实水平。读成绩单时必须先看清 k 是几。

为何常见:论文摘要往往同时列出多个 k 的成绩,读者潜意识里会挑最漂亮的数字看,而忽略了 k 越大指标越宽松的本质。

误区模型在 HumanEval 上拿了 70%,那让它去修 GitHub 上的 issue、给项目加个新功能肯定也没问题。

正解HumanEval 的题目是函数级、平均 7.7 行、上下文只有几行 docstring,相当于只考“单脚站立”;真实工程是跨文件、多依赖、长上下文的复杂任务,相当于考“山路漂移”。很多模型在 HumanEval 上是优等生,一进真实仓库就迷路。这也是 SWE-bench、RepoBench 等新基准出现的原因——考卷要更接近真实路况。

为何常见:人脑容易把“写函数”泛化成“写软件”,但中间隔着工程化、代码库理解、依赖管理等巨大鸿沟,这是函数级 benchmark 天然无法覆盖的。

误区pass@k 很简单啊,生成 k 个代码,跑一下测试,通过的占比就是 pass@k。

正解直接“生成 k 个看通过率”在统计上是有偏的,尤其当 k 较大、成功样本稀少时,会系统性低估真实通过率。论文采用的做法是:先固定生成 n(n≥k)个候选,统计成功数 c,再用组合数公式做无偏估计。就像评估补考通过率时,不能只盯着少部分人的前两次成绩,要把所有补考记录都摊开算。

为何常见:直觉上的定义简洁好记,但忽略了“采样→计数→估计”之间的统计偏差,只有做过多次实验才会发现直接计数和理论值对不上。

误区HumanEval 分数这么高,说明模型已经真正理解了编程逻辑,不再是背答案。

正解预训练语料海纳百川,HumanEval 的题目虽然是手写的,但高度相似的函数题在 GitHub、Stack Overflow 上大量存在,模型完全可能“背过答案”。研究者用多语言改写题目、构造新变体来交叉验证,就是为了排除这种“背诵式高分”。分数高≠真会写,必须结合防泄漏措施和跨基准交叉验证来判断。

为何常见:数据泄漏是隐性的——训练集那么大,没有谁能在发布前逐一排查所有语料,于是“分数高=能力强”的直觉很容易掩盖泄漏风险。

面试题

Q1. HumanEval 数据集共有多少道手写编程题?

单选题 · easy

  • A.164 道手写函数题← 正确答案
  • B.500 道竞赛真题
  • C.1000 道爬虫采集题
  • D.80 道面试改编题

答案:A。HumanEval 由 OpenAI 发布,包含 164 道人工编写的函数级编程题。选项 B/C/D 的数量都是干扰项,实际数据集的规模刻意做小,是为了降低预训练数据泄漏的风险,同时保持人工标注质量。

Q2. HumanEval 中一道题的任务需求说明主要存放在哪里?

单选题 · easy

  • A.docstring 描述← 正确答案
  • B.构造函数注释
  • C.独立需求文档
  • D.测试用例日志

答案:A。每道题的输入输出逻辑写在函数签名下方的 docstring 里,模型要完全依靠这段自然语言描述理解需求。函数签名只规定接口,单元测试只验证结果,两者都不承载“任务说明”,需求描述的载体是 docstring。

Q3. pass@k 无偏估计公式中的 n 代表什么?

单选题 · mid

  • A.每个任务采样总数← 正确答案
  • B.数据集题目总数
  • C.函数的参数个数
  • D.测试用例的个数

答案:A。公式 pass@k 中对每个问题先生成 n 个候选,再从 n 个中无偏估计“任取 k 个至少有一个通过”的概率。n 是采样池大小,实验中常用 100 或 200,远大于 k。B 是题目数、C 是参数数、D 是测试数,都与 n 无关。

Q4. 某模型单次采样通过率 p=50%,理论上它的 pass@5 约为?

单选题 · mid

  • A.96.9%← 正确答案
  • B.50.0%
  • C.75.0%
  • D.62.5%

答案:A。在理想伯努利模型下,pass@k=1-(1-p)^k,代入 p=0.5、k=5 得 1-0.5^5=96.875%。这体现补考机制对通过率的放大效应:单次正确率只有一半的模型,给 5 次机会几乎必过。

Q5. HumanEval 评测中为了生成多样候选代码,常用的温度是?

单选题 · mid

  • A.0.8← 正确答案
  • B.2.5
  • C.0.1
  • D.1.0

答案:A。温度越高采样越多样,论文中测 pass@k 通常用 T=0.8,测 pass@1 用 T=0.2。2.5 接近随机噪声,0.1 过于保守,1.0 虽可行但不常用。温度本质是控制“补考的答案之间差异有多大”。

Q6. 关于 pass@1 与 pass@k 的关系,下列说法正确的是?

单选题 · hard

  • A.pass@1 反映首选答案质量← 正确答案
  • B.pass@1 与 pass@k 无关
  • C.pass@k 只受采样数影响
  • D.pass@k 是答案平均分

答案:A。pass@1 是“只给一次机会的通过率”,最贴近真实用户场景,反映模型首选答案的可靠性。pass@k 由单次通过率和 k 共同决定(理论上 1-(1-p)^k),B 说无关是错的;C 忽略模型质量的影响;D 混淆了概率与平均分。

Q7. 以下哪些措施能降低 HumanEval 评测中的数据泄漏风险?

多选题 · mid

  • A.评测前不公开测试题← 正确答案
  • B.用 LeetCode 题扩充训练
  • C.使用测试集微调模型
  • D.用多语言改写复测← 正确答案

答案:AD。不公开测试题能防止模型在推理时作弊;多语言改写题目可以检验模型是“真会做”还是“背了原题”。用 LeetCode 扩充训练与防泄漏无关,使用测试集微调则是严重的数据泄漏——等于考前把答案给了考生。

Q8. 以下哪些方法能有效提升模型在 HumanEval 上的成绩?

多选题 · hard

  • A.把测试题写进提示词
  • B.微调时加入更多代码← 正确答案
  • C.让模型看报错自修复← 正确答案
  • D.答案排序器筛选结果← 正确答案

答案:BCD。加入更多代码语料提升基础能力、自修复利用测试反馈迭代改进、排序器从候选集中挑最优,都是论文验证过的合法手段。而把测试题写进提示词属于测试集泄漏,是作弊行为,分数没有任何参考价值。

Q9. 关于 HumanEval 的局限性,下列说法正确的是?

多选题 · hard

  • A.函数级任务缺少工程上下文← 正确答案
  • B.题目包含大量跨文件依赖
  • C.预训练可能见过类似题目← 正确答案
  • D.题目难度覆盖大多数领域

答案:AC。HumanEval 是单文件、函数级任务,恰恰缺乏真实工程的跨文件上下文,所以 B 与事实相反。由于训练语料规模庞大,模型确实可能见过相似题目,存在数据泄漏风险。题目难度集中在函数实现,覆盖面有限,D 错误。

Q10. 无偏估计中若 n-c < k,则 pass@k 应为?

单选题 · extreme

  • A.1.0← 正确答案
  • B.0.0
  • C.k/n
  • D.c/n

答案:A。n-c 是失败样本数。如果失败样本不足 k 个,那么从 n 个候选中任取 k 个,无论如何组合都会包含至少一个成功样本,因此“全军覆没”的概率为 0,pass@k=1。这是公式的边界条件,也是 pass_at_k 实现中第一行判断的数学依据。