想象你经营着一家软件检修车间。车间里每天都在上演同一出戏:客户送来一套“带病”的代码,AI维修师傅(也就是大模型)负责找到毛病、动手修好;而你,作为质检主管,最关心的不是师傅修得有多炫,而是怎么科学地判断“修好了”——这正是“代码修复能力评测”要做的事。 要构建这样一套验收体系,你需要四样东西:标准考件(缺陷是怎么造出来的)、验收工序(修复正确性怎么验证)、复查流程(怎么防止“修好A处弄坏B处”)、以及一本记分牌(评分标准)。现实中,SWE-bench、HumanEvalFix 这些评测基准,就像是官方技能大赛的考卷;PASS@K 则像“每位选手可以交K份答案,只要有一份全对就算过”的比赛规则。当然,任何考卷都有盲区——题库可能泄题、考点可能太窄、考场布置成本太高——这就是评测基准的局限性。 这篇文章,就带你把这间“代码检修车间”的每一道工序都拆开看一遍。

岗位关联

掌握代码修复评测的完整方法论,意味着你能看懂主流基准的分数含义、设计自己的修复能力评估方案,避免被排行榜上的虚高数字误导——这是AI工程师量化模型真实实力的基本功。

目录
  1. 可视化演示
  2. 缺陷注入方法:考卷上的“标准次品”从哪来
  3. 修复正确性验证:质检员凭什么说“修好了”
  4. 回归测试设计:防止“拆东墙补西墙”的复查工序
  5. 评测基准设计:官方技能大赛的考卷从哪来
  6. 评分标准体系:记分牌上的PASS@K
  7. 基准局限性:任何考卷都有盲区
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

演示代码修复能力评测:缺陷注入生成缺陷样本、模型定位缺陷生成修复补丁、多层次验证正确性,并计算修复通过率与pass@k指标。

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

模式1:缺陷注入 正确代码植入缺陷 按缺陷类型分类 correct→buggy 生成标准化缺陷样本

缺陷注入方法:考卷上的“标准次品”从哪来

软件检修厂要考核徒弟,师傅第一步是准备“标准考件”。怎么准备?要么在好零件上故意做手脚——划几道痕、剪断一根线,难度可控、想考什么就考什么;要么直接从仓库里挑出顾客退货的真坏件,毛病千奇百怪但绝对真实。两种办法各有拥趸,质量好的考件体系往往两者都要。

代码修复评测的第一步,就是“缺陷注入”——为模型准备带bug的代码任务。人工标注缺陷指研究者手工修改代码制造bug,比如从 HumanEval 里挑一个正常函数,故意改错边界条件,难度可以分层设计;自然缺陷采集指从真实 GitHub 仓库的历史提交中,找出“修复了一个bug”的 commit,把修复前版本当作缺陷版本。前者像标准题型卷,后者像真题卷。

不过,注入缺陷不能随心所欲。一个“坏件”必须能被质检工序抓出来,否则模型修不修,分数都毫无差别。因此每个注入缺陷都要做有效性过滤:在缺陷版本上跑一遍原有测试,确认至少有一个用例失败。这条规则用公式表达就是:

回到检修车间:每道送进考场的“次品题”都得盖一个“可检出”的章。如果划的那道痕根本不影响零件工作,质检员测不出来,这道题就是废题。评测基准同样要淘汰这类无效缺陷,只保留能被测试抓住的真bug。

有效注入:∃ t∈T原, run⁡(t, buggy)=Fail\text{有效注入}: \exists\, t \in T_{\text{原}},\ \operatorname{run}(t,\ \text{buggy}) = \text{Fail}
该公式说明:一个缺陷要想进入评测基准,必须存在某个原有测试用例,在该缺陷版本上运行结果为失败。换句话说,缺陷“可被测试观测到”才有效。
  1. 原有测试集项目在引入缺陷之前就已经存在的回归测试,是判断缺陷是否可见的标尺。
    T原={t1,t2,…,tm}T_{\text{原}} = \{t_1, t_2, \ldots, t_m\}
  2. 存在量词只要这组测试里至少有一个测试用例满足条件即可,不要求全部失败。
    ∃ t∈T原\exists\, t \in T_{\text{原}}
  3. 运行验证把该测试实际执行在缺陷版本代码上,得到真实运行结果。
    run⁡(t, buggy)\operatorname{run}(t,\ \text{buggy})
  4. 失败判定运行结果必须是失败,证明这个bug确实能影响程序行为。
    run⁡(t, buggy)=Fail\operatorname{run}(t,\ \text{buggy}) = \text{Fail}

修复正确性验证:质检员凭什么说“修好了”

徒弟把修好的零件交回来,质检员不会听口头汇报。他要把整套工序重新走一遍:先针对这次故障做专门的检测,再把原本的全部检测项目重跑一次,最后还要对照原厂图纸,确认内部结构没被改得面目全非。

在评测中,模型生成修复补丁后,“对错”由测试集来裁决。基准会为每个任务准备两组测试:新测试(针对这个bug新写的断言,专门检验“故障现象消失”)和回归测试(原本就有的测试,检验“其他功能没被弄坏”)。模型补丁必须同时通过这两组测试,才被判定为修复正确。

但这还不够严谨。测试总有覆盖不到的地方——比如模型把某个函数的逻辑整体重写了一遍,恰好蒙混过关。于是基准还需要语义等价校验:用静态分析或差异化测试,检查补丁后的代码行为是否与“真修复”等价;对于高风险补丁,还会引入人工确认机制,由专家抽查。三者叠加,才是完整的正确性验证:

质检员的逻辑从来都是“双向确认”:专门的故障检验证明了病根已除,全面复检证明了身体无恙。代码修复评测同样如此——只过新测试,可能是把整个功能删了来逃避检查;只过旧测试,则是bug根本没修干净。

Correct(patch)=(⋀t∈Tnewpass⁡(t))∧(⋀t∈Tregpass⁡(t))\text{Correct}(\text{patch}) = \left( \bigwedge_{t \in T_{\text{new}}} \operatorname{pass}(t) \right) \wedge \left( \bigwedge_{t \in T_{\text{reg}}} \operatorname{pass}(t) \right)
该公式是修复判定标准的“逻辑合取式”:所有新测试都通过,并且所有回归测试都通过,整体结果才为真。任何一个测试失败,修复都不算正确。
  1. 补丁模型对缺陷代码做出的修改,是评测的对象。
    patch=Δ(buggy)\text{patch} = \Delta(\text{buggy})
  2. 新测试集针对当前缺陷新增的隐藏测试,专门验证bug行为是否被消除。
    Tnew={t1new,t2new,…}T_{\text{new}} = \{t_1^{\text{new}}, t_2^{\text{new}}, \ldots\}
  3. 回归测试集缺陷之前就存在的测试,确保原有功能不退化。
    Treg={t1reg,t2reg,…}T_{\text{reg}} = \{t_1^{\text{reg}}, t_2^{\text{reg}}, \ldots\}
  4. 全称合取对集合内每个测试都要求通过,任一失败整体即为假。
    ⋀t∈Tpass⁡(t)\bigwedge_{t \in T} \operatorname{pass}(t)
  5. 两组同时满足新测试与回归测试用“与”连接,缺一不可。
    Correct=true  ⟺  两组测试全过\text{Correct} = \text{true} \iff \text{两组测试全过}

回归测试设计:防止“拆东墙补西墙”的复查工序

维修厂老师傅总念叨一句话:“修一个地方,可能带坏三个地方。”拧紧螺丝可能压断线路,换掉齿轮可能卡住轴承。所以真正的复查,一定不是只查修过的那一处,而是把整条流水线的关键节点全部重新测一遍。

代码修复中的“拆东墙补西墙”极为常见:模型为了让新测试通过,可能直接把有bug的函数体清空,或者加上一堆硬编码的if分支来“骗过”断言。回归测试设计就是为了防住这些花招。它的第一条原则是高覆盖测试集——测试要尽量执行到被修复函数的每一条代码路径,让“删代码”这种取巧行为立刻暴露;第二条是新增边界用例——针对bug的性质补上极端输入,比如空列表、负数、超大整数,让修得不够本质的补丁现形;第三条是防伪修复检测——通过断言“修复后代码仍保留正常功能”来识别假装修复的伪补丁。

这些原则背后最常用的量化工具是覆盖率:

回到复查工序的比喻:覆盖率就是“这段零件被质检探针扫过的比例”。探针没扫到的地方,偷工减料就能藏身。当然,覆盖率也不是越高越好,追求100%行覆盖可能带来冗余测试和巨大算力消耗,评测基准需要在“体检彻底”与“成本可控”之间找平衡。

Coverage(T)=∣Lcovered∣∣Ltotal∣\text{Coverage}(T) = \frac{|L_{\text{covered}}|}{|L_{\text{total}}|}
覆盖率衡量测试集对代码的“体检范围”:被测试执行到的代码行数除以总代码行数。覆盖率越高,测试抓不到的死角就越少,伪修复的生存空间就越小。
  1. 全部代码行被测程序中所有可执行行的集合,是覆盖率的分母。
    Ltotal={l1,l2,…,ln}L_{\text{total}} = \{l_1, l_2, \ldots, l_n\}
  2. 已覆盖行运行测试集时至少被执行过一次的代码行的集合。
    Lcovered={l∈Ltotal:l run by T}L_{\text{covered}} = \{l \in L_{\text{total}} : l \text{ run by } T\}
  3. 覆盖率计算用已覆盖行数除以全部行数,得到0到1之间的比例。
    Coverage(T)=∣Lcovered∣∣Ltotal∣\text{Coverage}(T) = \frac{|L_{\text{covered}}|}{|L_{\text{total}}|}

评测基准设计:官方技能大赛的考卷从哪来

车间要办一年一度的维修技能大赛,最头疼的就是出卷。出卷人有两条路线:从真实客户故障记录里挑典型案例改造成考题,或者请专家按知识点人工编题。前者真实但难控制难度,后者标准但可能脱离实际。[SWE-bench](0) 就是前者的代表作——它从真实 GitHub 仓库中收集了大量 issue 与对应修复 PR,把“问题描述、原始代码、真实测试”打包成任务;[HumanEvalFix](1) 则属于后者,在 HumanEval 函数集上人工注入bug,覆盖简单、中等、困难三档难度。

无论是真题卷还是标准卷,好的基准都要贴近真实项目场景:任务不能只是孤立的小函数,最好带上项目上下文、依赖关系和真实的失败测试信息。唯有如此,模型在大模型基准上练出的修复能力,才能迁移到工程师日常面对的复杂代码库中。

设计考卷时还有一个关键步骤——计算基线通过率。所谓基线,就是用一个非常朴素的修复器(比如直接返回原代码、或早期弱模型)先跑一遍基准,看看“瞎蒙”能得多少分。如果基线通过率太高,说明考卷太简单、区分度差;太低则说明任务难到没有区分意义。基线通过率的定义是:

官方大赛的每一套考卷,都得先让“普通人”试做一遍,才能确定难度星级。评测基准同理——基线通过率就是考卷上的“难度提示”,告诉使用者这套题是入门级还是挑战级,也为后续对比模型分数提供了参照系。

B(base)=1∣D∣∑i=1∣D∣1[ Fix⁡base(di) passes ]B(\text{base}) = \frac{1}{|D|} \sum_{i=1}^{|D|} \mathbb{1}[\ \operatorname{Fix}_{\text{base}}(d_i)\ \text{passes}\ ]
基线通过率把所有基准任务逐题交给基线修复器,统计“通过全部测试的任务占比”。它是一张“难度标尺”,用于校准整套考卷对模型能力的区分能力。
  1. 任务集基准包含的所有修复任务,每个任务对应一个缺陷。
    D={d1,d2,…,dN}D = \{d_1, d_2, \ldots, d_N\}
  2. 基线修复用简单方法对每个任务生成一个“保底”补丁。
    Fix⁡base(di)\operatorname{Fix}_{\text{base}}(d_i)
  3. 指示函数补丁通过全部测试记1分,否则记0分,把“通过与否”变成可累加的数字。
    1[ ⋅ ]\mathbb{1}[\ \cdot\ ]
  4. 平均通过率把得分求和除以任务总数,得到0到1之间的基线水平。
    B(base)=通过任务数NB(\text{base}) = \frac{\text{通过任务数}}{N}

评分标准体系:记分牌上的PASS@K

维修技能大赛现场,最激动人心的环节是记分。最简单的记分方式自然是“一题一分,全过才算对”——这就是端到端通过率:每个任务只有“全部测试通过”和“没通过”两种结果,按任务数求平均。它的优点是干净明确,缺点是太苛刻:模型明明产生了高分补丁,只因为测试环境一点抖动就判零分,浪费了信息。

于是比赛升级了规则:每位选手可以交K份答案,只要其中有一份全对,这题就给你算通过。 这就是 PASS@K 的思想。它来自 Codex 论文提出的无偏估计:假设模型对一道题采样了 n 个候选补丁,其中 c 个通过全部测试,随机从 n 个中抽取 k 个,至少有一个成功的概率。公式如下:

除了正确率,记分牌还有“效率栏”:修复效率度量会关注补丁是否最小改动、修复耗时多长、消耗了多少token。两位师傅都修好了同一个零件,一位换了整块变速箱,另一位只换了一个垫圈——谁的工艺更好?不言自明。

pass@k=E[1−(n−ck)(nk)]\text{pass}@k = \mathbb{E} \left[ 1 - \frac{\binom{n-c}{k}}{\binom{n}{k}} \right]
PASS@K 度量的是“多给几次机会模型能不能抓住一个对的答案”。它比单次通过率更稳定,能减少采样随机性带来的分数波动,在修复能力评测中广泛使用。
  1. 样本总数与成功数n 是模型为单个任务生成的全部候选补丁数,c 是其中通过测试的个数。
    n:samples,c:successesn: \text{samples},\quad c: \text{successes}
  2. 组合数分母从 n 个候选里任取 k 个的所有取法数,构成随机抽样的样本空间。
    (nk)\binom{n}{k}
  3. 组合数分子从失败的 n-c 个候选里取 k 个的取法数,代表“随机抽的 k 个全是失败”。
    (n−ck)\binom{n-c}{k}
  4. 求反面概率用1减去“全是失败”的概率,得到“至少一个成功”的概率。
    1−(n−ck)(nk)1 - \frac{\binom{n-c}{k}}{\binom{n}{k}}
  5. 期望对评测集中的所有任务求这个概率的平均值,得到整体 PASS@K。
    E[⋅]\mathbb{E}[\cdot]

基准局限性:任何考卷都有盲区

再严谨的考卷也有三个绕不开的盲区。第一个是数据污染:竞赛题目如果提前泄露给了考生,分数就失去意义。代码修复基准同样如此——如果模型的训练语料里恰好包含了 SWE-bench 中的 issue 原文、修复 commit 甚至测试代码,那它“修复”问题时很可能只是把背过的答案默写出来,分数虚高却不代表真实能力。

第二个盲区是领域覆盖有限。SWE-bench 偏向 Python 仓库,HumanEvalFix 偏向函数级小任务,它们无法覆盖大型系统的架构级缺陷、多文件联动故障、或是编译期才能暴露的类型错误。在真实项目里修 bug,面对的挑战远比一张考卷复杂。第三个盲区是复现成本代价:跑全量测试验证补丁需要大量算力,尤其当测试集庞大时,一次评测可能消耗数小时GPU时间,这让小团队复现基准结果变得困难。

当任务数量有限时,分数本身也有统计波动。假设观测通过率为 p,任务数为 N,模型真实能力的置信区间可以近似表达为:

回到车间:一套考卷如果每年都泄题、只考车床不考焊工、而且考场租金贵到只有少数人考得起,那么即使它是官方认证,大家也要保持警惕。看懂基准的局限性,比记住排行榜名次更重要。

CI=p±z1−α/2p(1−p)N\text{CI} = p \pm z_{1-\alpha/2} \sqrt{\frac{p(1-p)}{N}}
置信区间告诉我们:评测分数不一定是模型真实水平,真实水平有一定概率落在该区间内。任务数 N 越小,区间越宽,分数越不可信。
  1. 观测通过率模型在基准上“考出来”的分数,是 p 的估计值。
    p=cNp = \frac{c}{N}
  2. 样本量基准任务总数,决定统计估计的稳定性。
    N=∣D∣N = |D|
  3. 置信水平系数对应置信度的正态分位数,95% 置信水平下取约 1.96。
    z0.975≈1.96z_{0.975} \approx 1.96
  4. 标准误差用二项分布近似估计通过率的波动幅度。
    p(1−p)N\sqrt{\frac{p(1-p)}{N}}
  5. 区间宽度波动幅度乘以置信系数,N 越大区间越窄,分数越可靠。
    CI=p±z⋅SE\text{CI} = p \pm z \cdot \text{SE}

AI 应用场景

CI/CD流水线中的自动修复机器人

阶段:评测与闭环验证

解决的问题:传统 CI/CD 流程中,测试一旦失败,开发者需要手动查看日志、定位故障、写补丁、再触发一轮构建,来回一次往往耗费数小时。AI 修复机器人可以按“缺陷注入→修复→验证”的评测框架,先根据失败测试反推缺陷位置,生成候选补丁,再自动跑完整回归测试进行验证。

具体案例:某中大型 Python 服务团队在 GitHub Actions 上配置了自动修复机器人。当 PR 触发测试失败时,机器人调用代码修复模型生成 3 个候选补丁,逐一在隔离环境中运行测试集,选出 PASS@3 命中的补丁并自动提交,开发者只需做最终审查。整个过程将平均修复时间从 2 小时压缩到 15 分钟。

开源维护者批量处理issue

阶段:基准应用与工具链

解决的问题:开源维护者每天面对几十个 bug issue,从复现、定位到修复、合入的链路很长。利用 SWE-bench 这类“真实issue+真实测试”的基准流程,可以筛选出有明确测试用例的任务,交给 AI 生成修复补丁,维护者只做最后一道 code review,大幅降低维护成本。

具体案例:某流行的 Python 开源库维护者,每周收到约 30 个新 issue。他写了一个小脚本:把 issue 附带的失败用例接到主分支、用模型生成补丁、自动跑全量单元测试。凡是模型补丁能让新旧测试全绿的任务,再人工确认语义等价后合入,每周能自动关闭约 15 个 issue。

模型迭代的能力回归看板

阶段:能力评估

解决的问题:大模型团队在微调新版本时,最怕“修了对话能力、砸了代码能力”。固定代码修复基准就像一台“能力体重秤”,每次发布前过一遍,用 PASS@1 和 PASS@K 量化修复能力变化,防止版本回退。

具体案例:某 AI 公司的评测平台团队维护了一个包含人工注入缺陷与真实issue混合的代码修复集,共 500 个任务。每次模型迭代后自动跑分,并计算通过率的 95% 置信区间;若新版本分数低于旧版且区间不重叠,则拦截发布。该机制已帮助团队在 4 次迭代中发现并修正了两次代码能力回退。

Python 演示

python77 行
"""Mini benchmark for code repair: inject bug, verify patches, compute PASS@K."""import math  def flawed_mean(values):    """Original buggy version: raises ZeroDivisionError on empty list."""    return sum(values) / len(values)  def candidate_1(values):    """Patch that returns 0.0 for empty list and keeps normal math."""    return sum(values) / len(values) if values else 0.0  def rounded_mean(values):    return round(sum(values) / len(values), 2) if values else 0.0  def candidate_2(values):    """Patch using rounding, still handles empty list."""    return rounded_mean(values)  def candidate_3(values):    """Fake fix: drops negative numbers, hidden bug remains."""    positive = [v for v in values if v > 0]    return sum(positive) / len(positive) if positive else 0.0  TEST_CASES = [    ("empty list", [], 0.0),    ("all positive", [1, 2, 3], 2.0),    ("with negative", [1, -2, 3], 0.6667),    ("all negative", [-1, -2, -3], -2.0),    ("single item", [42], 42.0),]  def run_all(func):    """Run the full regression suite, return True only if all pass."""    for name, values, expected in TEST_CASES:        try:            got = func(values)        except Exception:            return False        if abs(got - expected) > 0.01:            return False    return True  def comb(n, k):    """Binomial coefficient, returns 0 when k is out of range."""    if k < 0 or k > n:        return 0    return math.comb(n, k)  def pass_at_k(n, c, k):    """Probability that at least one of k sampled patches succeeds."""    return 1 - comb(n - c, k) / comb(n, k) if n >= k else 0.0  def main():    candidates = [candidate_1, candidate_2, candidate_3]    results = [run_all(f) for f in candidates]    n = len(candidates)    c = sum(results)    for i, (func, ok) in enumerate(zip(candidates, results)):        print("candidate %d: %s" % (i + 1, "PASS" if ok else "FAIL"))    print("success count: %d / %d" % (c, n))    for k in (1, 3):        score = pass_at_k(n, c, k)        print("PASS@%d = %.3f" % (k, score))  if __name__ == "__main__":    main()
目的:演示一个微型代码修复评测完整流程——注入缺陷、准备候选修复补丁、运行回归测试验证、最后用 PASS@K 公式为模型打分。
  1. def flawed_mean(values):这是“缺陷注入”环节:一个故意写错的函数,空列表时抛出除零异常。
  2. def candidate_1(values):模拟模型生成的第一个修复候选,正确处理空列表边界。
  3. def candidate_3(values):一个“伪修复”候选:丢弃负数,表面不报错但行为错误。
  4. TEST_CASES = [回归测试集,包含空列表、负数等边界用例,相当于质检工序表。
  5. def run_all(func):验证环节:跑全部测试,任何用例失败或异常都返回 False。
  6. if abs(got - expected) > 0.01:浮点比较必须带容差,不能直接用相等判断。
  7. def pass_at_k(n, c, k):PASS@K 核心公式的无偏估计实现。
  8. return 1 - comb(n - c, k) / comb(n, k) if n >= k else 0.0用“全是失败”的概率取反,得到“至少一次成功”的概率。

常见误区

误区我觉得构造bug很容易,往代码里删几行、换个运算符,就能拿来做修复评测了,不需要什么流程。

正解注入缺陷必须经过“有效性过滤”——在缺陷版本上跑一遍原有测试,至少要有一个用例失败,否则这个缺陷对测试不可见,模型修不修评测结果都一样。此外还要过滤重复缺陷和纯语法错误。好比质检车间造次品,得先确认质检工序真能把它检验出来,否则它只是“隐形的坏件”。

为何常见:人们天然把“制造坏件”想得很简单,却忽略了“缺陷可被测试观测”才是缺陷进入考卷的入场券。

误区模型把针对bug的新测试跑通了,这不就是修好了吗?还要看别的吗?

正解真正判定修复正确,必须“新测试全过”与“回归测试全过”同时满足。修好了bug但把原有功能搞挂,是模型常见的失败模式;只过新测试也可能是删掉了整个函数来逃避断言。评测基准用逻辑合取式表达这两层要求,就像维修师傅把空调修制冷了,但把风扇搞得不转了,验收同样不合格。

为何常见:开发者平时自己修bug时只关心眼前现象,容易忽略“回归”这个概念在评测中的决定性作用。

误区PASS@K 不就是让模型生成K次答案然后算平均分吗?答案越多分越高?

正解PASS@K 的真实含义是“K个候选补丁中至少有一个通过全部测试的概率”,用组合数做无偏估计。它衡量的是模型产出“聪明候选”的稳定性,而不是平均质量。如果K份答案全失败,平均分再高也是零;只要有一份成功,这题就算通过。这好比比赛允许交K份答卷,评委只看最好的一份。

为何常见:从图像分类里的 top-k accuracy 习惯迁移过来,容易把“最好的一次”错当成“多次平均”。

误区SWE-bench 上排名第一的模型,写代码能力应该就是世界最强了吧?

正解要警惕三个陷阱:一是数据污染,若训练语料混入了基准的issue、补丁或测试,模型可能只是“背过答案”;二是领域覆盖有限,基准偏Python、偏函数级,无法衡量架构设计能力;三是小样本统计波动,任务数少时置信区间很宽。分数高只能说明“在这套考卷上表现好”,不能直接等价于真实开发能力。

为何常见:排行榜只有孤零零的数字,数据泄露和覆盖偏差都隐藏在数字背后,初学者很难察觉。

误区既然回归测试能防伪修复,那测试用例越多越全,基准是不是就越可靠?

正解回归测试并非多多益善。测试数量增长会带来三重代价:验证时间变长、算力成本上升、评测复现门槛提高。设计时需要在覆盖率与成本之间权衡,优先选择高覆盖、高断言质量的最小测试集。覆盖率公式只是工具,盲目堆用例反而会拖垮整个评测流水线。

为何常见:直觉上“查得越细越安全”,但忽略了评测体系本身也有资源约束和时间成本。

面试题

Q1. 评测基准构造中,判定“注入缺陷”是否有效的关键条件是什么?

单选题 · easy

  • A.行数足够多的Bug标注
  • B.原有测试集至少一例失败← 正确答案
  • C.修复后代码明显变短
  • D.函数命名包含Bug字样

答案:B。注入缺陷必须能被测试观测到,否则模型修不修分数无差异。B正是“有效性过滤”的定义:缺陷版本上至少一个原有测试运行失败。A、D无关紧要,C更是修复结果而非注入条件。

Q2. 代码修复评测中,“修复正确”通常要求什么?

单选题 · easy

  • A.仅新增测试通过
  • B.仅原有测试通过
  • C.新旧测试全部通过← 正确答案
  • D.代码能通过编译

答案:C。修复正确要求新测试与回归测试同时通过——新测试证明bug行为被消除,回归测试证明原有功能没被破坏。只满足A可能是删功能逃避检查,只满足B则是bug没修干净,能编译更远不足以判定修复正确。

Q3. PASS@K 指标的核心含义是什么?

单选题 · mid

  • A.模型运行K次的平均得分
  • B.K个候选至少一个通过的概率← 正确答案
  • C.模型K分钟修复完成概率
  • D.K个测试全部通过的概率

答案:B。PASS@K 用组合数无偏估计“随机抽K个候选补丁中至少一个成功”的概率,不是平均分,也不是时间指标或测试数量指标。它衡量模型产出可修复候选的稳定性,多给几次机会能否抓住一个正确答案。

Q4. 关于 SWE-bench 评测基准,下列说法正确的是?

多选题 · mid

  • A.基于真实仓库issue与PR← 正确答案
  • B.包含真实测试用例验证← 正确答案
  • C.只评测程序代码格式
  • D.全部为人工虚构缺陷

答案:AB。SWE-bench 从真实 GitHub 仓库收集 issue、修复 PR 与配套测试,属于“自然缺陷采集”路线。C与基准的语义验证目标相悖,D描述的是人工注入路线(如 HumanEvalFix),与 SWE-bench 相反。

Q5. 回归测试在代码修复评测中的作用有哪些?

多选题 · mid

  • A.防止修复引入新破坏← 正确答案
  • B.确认原有功能保持正常← 正确答案
  • C.验证模型推理的速度
  • D.检测删除功能的伪修复← 正确答案

答案:ABD。回归测试的核心是“复查”:补丁通过回归测试,说明原有功能未退化,防止拆东墙补西墙;高覆盖回归集还能发现删函数、加硬编码等伪修复。C考察性能与功能正确性无关。

Q6. 数据污染对代码修复评测基准的影响是什么?

单选题 · mid

  • A.让评测基准变得更难
  • B.使分数虚高失去参考意义← 正确答案
  • C.对评测完全不构成影响
  • D.只影响测试执行的速度

答案:B。当模型的训练语料混入基准的issue、补丁或测试时,模型可能背过答案,评测分数虚高但真实修复能力不变。作弊式得分让基准失去区分能力,因此需要时间线切分与相似度检测来缓解。

Q7. 修复正确性验证中,语义等价校验的目的是什么?

单选题 · mid

  • A.检查代码的注释风格
  • B.验证行为与预期语义一致← 正确答案
  • C.替代全部回归测试
  • D.压缩补丁的代码体积

答案:B。测试总存在覆盖盲区,模型可能用重写逻辑的方式侥幸通过断言。语义等价校验通过静态分析或差异测试,确认补丁行为与预期语义一致,补上测试的漏洞。它辅助而非替代测试,与风格、体积无关。

Q8. 人工注入缺陷与自然缺陷采集相比,正确的认识是?

多选题 · hard

  • A.人工注入可控但可能失真← 正确答案
  • B.自然缺陷真实但成本高昂← 正确答案
  • C.两者完全一样没有区别
  • D.人工注入需要有效性过滤← 正确答案

答案:ABD。人工注入能精确控制难度与分布,但可能偏离真实bug形态;自然缺陷来自真实仓库,真实度高但收集、清洗成本高。两者都必须做有效性过滤,确保缺陷可被测试捕捉。C显然错误。

Q9. 评测基准提供“基线通过率”的主要目的是什么?

单选题 · easy

  • A.供参赛者参考答案
  • B.校准难度体现基线表现← 正确答案
  • C.减少测试用例数量
  • D.增加评测代码行数

答案:B。基线通过率是用简单修复器(如原样返回代码)跑基准得到的分数,相当于“裸考成绩”。它像考卷的难度星级,帮助使用者判断任务区分度:基线过低任务过难,过高则区分度不足。

Q10. 小样本评测中,模型通过率 p 的置信区间主要受什么影响?

单选题 · extreme

  • A.测试用例的代码风格
  • B.任务数量与通过率方差← 正确答案
  • C.模型参数量大小
  • D.补丁文件命名方式

答案:B。置信区间公式中,区间宽度取决于标准误差,而标准误差由 p(1-p) 和任务数 N 决定。N 越小区间越宽,说明少量任务上的分数波动大、不可轻信。代码风格、模型参数和文件命名都与此无关。