← 返回 PaperDaily 视觉与图像

让代码AI出题考自己!南洋理工TCS两阶段强化学习方案全解析

考过程序设计竞赛的读者应该都有同感:决定命运的不是“你觉得自己写对了”,而是评测数据有没有精准戳中你代码里藏得最深的bug。

让代码AI出题考自己!南洋理工TCS两阶段强化学习方案全解析
原论文信息如下:
论文标题:
Two-Stage Reinforcement Learning for Sound and Adversarial Test Generation in Code LLMs
发表日期:
2026年09月
发表单位:
Nanyang Technological University, Singapore; Skywork AI
原文链接:
https://arxiv.org/pdf/2609.03955v1.pdf

代码大模型的新瓶颈:测试用例质量决定验证上限

考过程序设计竞赛的读者应该都有同感:决定命运的不是“你觉得自己写对了”,而是评测数据有没有精准戳中你代码里藏得最深的bug。如今代码大模型也撞上了同一面墙——随着模型能力越来越强,常规样例已经很难把不同候选解法区分开,问题正从“生成一段能跑的代码”变成“在一堆都能跑的代码里找出真正符合题意的那一个”。
于是“自我验证”成了一个极具吸引力的方案:让模型针对候选程序自己生成测试用例,再去执行、数通过数,谁通过得多谁就胜出。这种方案不依赖外部奖励模型,靠的是可执行证据,听起来非常优雅。但问题在于,自生成测试必须同时满足两个苛刻条件:一是可靠性,也就是测试用例的输入输出标注必须正确,不能在标准解身上“误伤”;二是区分度,也就是测试要能暴露错误程序的漏洞,否则错误解法全部蒙混过关,验证等于白做。前者不够会冤枉好人,后者不够会放过坏人。
论文实验里有一个非常值得玩味的现象:直接让基础模型“边写边考”,自生成测试带来的提升其实很有限;而只用人工整理的公开测试集去筛选候选,效果反而更好。这说明瓶颈从来不是“测试生成得不够多”,而是生成得不够好——测试用例的质量,直接决定了验证机制的天花板。
Figure 1: TCS enables adversarial test case generation using ground-truth solutions.
图1:TCS借助标准解(ground-truth solutions)实现对抗性测试用例生成。测试生成器既要保证标准解能通过,又要让错误候选程序在同样的测试上翻车。
来自南洋理工大学和Skywork AI的研究团队,把这个问题建模成一个对抗式强化学习问题,并提出了一套名为TCS(Test Cases Scaling,测试用例扩展)的两阶段训练框架。它的核心思想并不复杂:让代码大模型既当“考生”又当“出题老师”,先用标准答案把模型教成一名合格的出题者,再让它学会针对当前错误解法“量身定制”反例。

TCS两阶段框架:从可靠测试到对抗反例的课程学习

先看TCS的任务设定:每个训练样本包含一道题目的自然语言描述P、一份标准解C*(ground-truth solution)和一套数据集测试集τ。TCS让同一个模型同时扮演两个角色——求解器(Solver)根据P生成代码,目标是跑通τ里的全部测试;验证器(Verifier)则拿到P和一个候选程序,生成新的测试用例,要求“标准解能通过、错误的候选程序过不了”。
为什么要一个人分饰两角?因为在执行可验证的设定下,标准解C*提供了一个干净的“可靠性锚点”,而候选程序C则定义了“对抗目标”。生成可靠测试和生成针对具体bug的反例,是两种容易混在一起的能力;先分开训练再统一,反而能取得更好的协同效果。整个训练流程如图2所示,求解器与验证器共享一套策略参数,使用GRPO(Group Relative Policy Optimization,组相对策略优化)进行联合优化。
Figure 2: Overview of the two-stage training process in Test Cases Scaling (TCS).
图2:TCS两阶段训练流程总览。求解器在线生成的候选程序进入策略对齐缓冲区,验证器再从缓冲区里采样当前模型容易犯错的代码,针对性地生成测试用例。
GRPO是DeepSeek等工作中常用的强化学习算法,它用一个提示词下多个采样回答的平均奖励作为基线,省去了独立价值网络。每个候选的“优势”用组内标准化得到:
Advantage formula
其中r_i是第i个回答在真实执行环境里获得的奖励,mean和std是同一组G个采样奖励的均值与标准差。回答跑赢同组平均水平时,优势为正,策略上升的概率就增大;跑输则反之。
TCS之所以必须分成两个阶段,是因为“生成反例”的奖励极其稀疏。一个能揭露bug的测试用例,要求模型同时做到两件事:生成与标准解一致的正确输入输出,并且恰好命中当前错误候选的某个非平凡漏洞。让基础模型直接去优化这个目标,就好比让刚学编程的新手直接去出国际竞赛题,模型在长周期内拿不到任何正反馈,强化学习根本转不动。
Stage 1 reward
阶段1面向可靠性(soundness)做训练。奖励函数R₁ᵗ规定:生成的测试用例(I_g, O_g)只有在标准解C*上执行结果等于标注输出O_g时才给奖励1;同时,如果用例和题目描述里已经给出的示例测试T_example完全一致,则不给奖励,防止模型“抄作业”。
但只学阶段1还不够。只要求“正确”会诱导模型走捷径,生成空数组、最小样例这类人畜无害的平凡用例——它们虽然不会误伤标准解,但也无法鉴别错误程序。因此当测试生成器在训练批次上的准确率超过0.75左右(1.5B模型大约需要200步,7B大约需要40步),训练就切换到阶段2。此时缓冲区B被清空,只收入“可执行但会挂掉至少一个数据集测试用例”的错误程序,并施加一个更苛刻的奖励:
R₂ᵗ(I_g, O_g, C*, C_wrong) = 1,当且仅当 Exec(C*, I_g) = O_g、Exec(C_wrong, I_g) ≠ O_g,且 (I_g, O_g) ∉ T_example;否则为0。
这个奖励函数处处体现“定向打击”的意图:同一组输入输出,标准解C*必须通过,错误候选C_wrong则必须失败。直接把奖励定义在“候选程序当前会怎么错”上,迫使模型去理解bug模式,而不是泛泛地找几个边界值。
shaona.jpeg

策略对齐缓冲区:让验证器追踪求解器的失败演化

如果只看两个阶段奖励函数,可能会觉得TCS就是把离线数据拿来做两轮强化学习。真正让框架“活”起来的,是它的策略对齐缓冲区(policy-aligned buffer,简称B)。
缓冲区里的候选程序不是从外部静态数据集里找来的,而是求解器在训练过程中实时生成的输出。每当模型写出新代码,只要满足当前阶段的筛选条件,就会被放进缓冲区;同时只保留最近T_b个训练步的样本,旧样本不断被丢弃。这样缓冲区内容始终跟随策略当前的能力分布滚动更新。
这个设计背后的逻辑值得细品。强化学习训练中,求解器策略每时每刻都在变化,早期模型犯的低级错误,到后期可能根本不会出现;反之,随着求解能力增强,新的、更隐蔽的失败模式会不断冒出来。如果验证器训练数据是固定离线的,它学到的是“如何打败过去的模型”,而不是“如何打败现在的模型”。在线缓冲区相当于一个永不掉线的陪练,逼着验证器永远面对求解器当下最真实的软肋。
值得注意的是,两个阶段对缓冲区样本的准入标准并不相同。阶段1只要求候选程序可执行,不要求它出错——此时验证器先学习面对各种代码风格生成可靠测试;一旦切换到阶段2,缓冲区立刻清空并转向只收“可执行但错误”的程序。这样的课程设计让模型先学会走,再学会跑。

理论保证与实验验证:指数级可靠性界与全面性能提升

光有漂亮的训练框架还不够,TCS还为“为什么自生成测试可以用来做推理时选择”提供了理论支撑。推理时,对同一道题采样N个候选代码,每个候选C_i生成M个测试用例,汇总成K = N × M个测试,然后选出通过数最多的候选:
pass count formula
这个规则什么时候可靠?论文定义了两种关键错误率。第一种是可靠性错误α,衡量随机生成的测试用例在标准解C*上执行失败的概率——也就是测试标注本身出错的概率;第二种是反例率δ(C),衡量生成的测试让标准解通过、却让错误候选C执行失败的概率。
alpha definition
α是“乱标率”,必须压得越低越好。
delta definition
δ(C)则是“有效反例率”,越高说明测试越能精准打击错误程序。
当δ > α,也就是“测试对错误候选的命中能力”强于“测试本身出错的比例”时,随着测试数量K增大,选错候选的概率会指数级下降:
exponential reliability bound
这个指数级可靠性界的重要性在于,它把两个训练阶段与推理时行为精确对应起来:阶段1的奖励函数直接压低α,阶段2的奖励函数直接抬高δ。两阶段课程训练出的验证器,本质上是在扩大(δ - α)这个边际优势,让“多采样、多测试”的推理时扩展策略变得真正可用。
实验部分,论文在TACO和LiveCodeBench两个代码生成基准上验证了TCS的效果。TACO的25,433道题被过滤成6,318道拥有充分测试覆盖的实例用于训练,评估集是1,000道验证题;LiveCodeBench则作为跨分布测试集。模型选择DeepSeek-R1-Distill-Qwen家族,包含1.5B和7B两个尺寸。基线设置也相当用心:除了基础模型和联合SFT(joint SFT,使用R1-Distill-Qwen-32B生成的、已经人工筛选的对抗性数据)之外,还拆出了仅训练求解器的Code-RL和仅训练验证器的Test-RL,用于隔离联合训练的价值。
Table 1: Performance on TACO and LiveCodeBench.
表1:TACO与LiveCodeBench上的性能对比。w/o pub表示不使用公开测试用例,w/ pub表示允许使用公开测试用例进行筛选;Avg为四个子项的平均。TCS既提升了pass@1,也让“自生成测试选择”(Self-Generated Test Cases)这一推理时策略的可用性大幅增强。
表格中有一个系统性规律:TCS训练后的模型,其自生成测试在做Best-of-N选择时的表现,从“明显弱于奖励模型排序”逆转为“持平甚至反超奖励模型排序”。这恰恰说明两阶段训练提升的不只是代码正确率,更包括“判断什么代码是对的”的验证能力。论文还报告了一个让人印象深刻的数字:在LiveCodeBench上,7B基础模型本来pass@1只有28.56,加入自生成测试加Best-of-N选择后冲到43.01,涨幅超过14个百分点。这个提升不是靠外部奖励模型,也不是靠人工测试用例,而是模型自己出题考自己考出来的。
Table 4: Joint vs. decoupled training on R1-Distill-Qwen-1.5B.
表4:R1-Distill-Qwen-1.5B上联合训练与解耦训练的对比。TC表示用自生成测试做选择,Test-RL-TC表示使用仅验证器训练产出的测试做选择。联合训练同时拿到了最强的训练时性能和最强的推理时筛选性能,说明求解器与验证器之间存在相互促进的自我对弈效应。
解耦实验的价值在于排除“只是RL把求解器变强了”的替代解释。只做Code-RL虽然也能提升pass@1,但它生成测试的筛选能力并没有同步跟上;只做Test-RL虽然训出了一把好测试标尺,但求解器本身的进步有限。只有联合训练形成了一个正向循环:更聪明的求解器制造更难的失败模式,更强的验证器反过来帮助筛选出更好的解。
Figure 3: Comparison of different inference-time scaling methods on TACO.
图3:TACO上不同推理时扩展方法的对比。随着候选数量N增大,TCS微调后的1.5B模型使用自生成测试做选择,能稳定超过未微调的14B大模型基线;而单纯依赖奖励模型排序在N增大后反而波动。小模型靠着“会出题”也能在推理时逆袭大模型,这正是验证能力独立价值的生动体现。
Figure 4: (a) Pass@1 (blue) and BoN (N=8) (green/orange) performance selected by self-generated or TCS-7B-generated test cases for strong external models in LiveCodeBench. (b) Test case output prediction accuracy. (c) Scores under different training rewards.
图4:(a) 用自生成测试和TCS-7B生成测试分别对强外部模型输出做Best-of-N(N=8)选择,TCS生成的测试带来了更大的下游收益;(b) 在LiveCodeBench的测试输出预测任务上,TCS模型的准确率更高,说明生成测试的可靠性与一致性更强;(c) 直接优化阶段2奖励R₂ᵗ时,训练前期奖励长期接近0,而两阶段课程能顺利爬坡——直观展示奖励稀疏问题为什么需要课程式训练。
TCS生成的测试还具备不错的泛化筛选能力:用TCS-7B训练出的测试去筛选其他强外部模型的输出,也能带来一致的Best-of-N提升。这再次印证了论文的核心观点——“会出题”并不只是“会写代码”的副产品,而是一种可以迁移的代码理解能力。
Figure 5 and Table 3: Inference-time scaling with multiple tests.
图5与表3:TCS微调7B模型在LiveCodeBench上、有/无公开测试时的推理时扩展效果;右侧表3进一步考察每个候选生成多个独立测试(M>1)时的效果。测试数量K越大,通过数选择规则的可靠性越高,这与理论界的指数衰减趋势一致。

局限与展望:从单测试生成到多测试协同

TCS的设定有一个前提:需要同时拿到问题描述、标准解和可执行测试环境。这个条件在竞赛编程类任务里成立,但在真实软件工程场景中并不总能满足——很多业务代码根本没有一份“标准答案”可以用来校验测试的可靠性。因此,把TCS推广到更开放的程序合成与单元测试自动生成场景,还需解决“标准解缺失”时的可靠性锚定问题。
另一个值得注意的方向是“多测试协同”。论文推理时默认每个候选只生成1个测试(M=1),而理论分析已经表明,每个候选生成多个独立测试、扩大K值,可以将选错概率进一步指数级压低。当生成测试的成本足够低时,让多个测试用例共同投票,可能会比单纯增加候选代码数量更划算。这也呼应了近年来大模型推理时扩展的研究主线:给模型更多“自我检查”的机会,往往比盲目多采样更高效。
从成本角度看,TCS需要额外的两阶段强化学习训练,对算力有一定要求。论文在NVIDIA H100 80GB上的训练与单次评估用时对比如下表所示,实际落地时还需要把执行测试用例的环境开销计入总成本。
Table 2: GPU hours on NVIDIA H100 80GB for training and single-run evaluation.
表2:在NVIDIA H100 80GB上的GPU耗时统计。两阶段训练账本比较清晰,适合作为复现时的参考。

龙迷三问

下面是龙哥对于大家可能的一些问题的解答:
这篇论文到底在解决什么问题?南洋理工大学与Skywork AI提出两阶段强化学习框架TCS,让代码大模型学会生成既可靠又具针对性的测试用例,推理时用自生成测试筛选正确代码。
这篇工作最值得看的点是什么?TCS在两个基准上均提升pass@1和推理时选择性能;TCS-7B在LiveCodeBench上pass@1从28.56提升至43.01(自生成测试选择BoN-32);TCS微调的1.5B模型可超越14B基础模型;自生成测试在无公开测试时优于奖励模型排序。
这篇工作的边界或风险在哪里?优点:(1) 两阶段课程设计有效解决稀疏奖励问题;(2) 策略对齐缓冲区使验证器跟踪求解器演化失败模式;(3) 理论分析(指数可靠性界)为推理时扩展提供保证;(4) 联合训练产生协同效应。缺点:(1) 需要真实解C*进行训练验证,限制无验证解场景;(2) 每次推理仅生成单个测试用例,效率受限;(3) 硬切换两阶段可能非最优;(4) 训练计算资源需求高。
如果你还有哪些想要了解的,欢迎在评论区留言或者讨论~

龙哥点评

论文创新性分数:★★★★☆。把测试生成拆成“可靠性”和“对抗性”两个阶段并用在线缓冲区衔接,角度在国内代码RL工作里不多见;还给推理时测试选择补了一个指数级可靠性界,形成了“现象→方法→理论”的完整叙事。

实验合理度:★★★★☆。对照组设计得很扎实:既有外部奖励模型排序,又有CodeRM-8B测试生成器对比,还拆了Code-RL和Test-RL来隔离联合训练的作用;这类消融在代码生成RL论文里属于高配。扣一星是因为表格排版较乱,部分数字在正文与表中对读时要花不少力气。

学术研究价值:★★★★☆。“让模型学会生成测试来验证自己”这个方向,对推理时扩展和代码智能体自我纠错都有借鉴意义;把测试生成的可靠性问题用两个可量化指标α和δ刻画,也给后续工作留下清晰的优化坐标。

稳定性:★★★☆☆。在竞赛类代码生成任务上表现稳定,反复实验都指向同一个结论;但对“标准解缺失”的现实代码场景,TCS没有验证锚点,稳定性会明显下降,所以分值保留三星。

适应性以及泛化能力:★★★☆☆。已经在TACO和LiveCodeBench两个分布上验证,而且强外部模型也能受益于TCS训练出的测试;但整体仍限定在Python算法题这类可执行验证的环境,真实软件工程场景的泛化能力尚未被证明。

硬件需求及成本:★★★☆☆。两阶段RL训练需要H100级别显卡,推理时又要批量执行自生成测试,整体算力开销不低;但好处是不需要额外奖励模型参与排序,省掉了一个推理时的大模型调用成本。

复现难度:★★★☆☆。论文公开了训练数据过滤标准、阶段切换阈值和推理时配置,技术上具备复现条件;但TACO数据筛选、32B教师数据生成和两阶段调参的工程量不小,实际跑通仍需投入可观时间。

产品化成熟度:★★☆☆☆。目前最合适的产品落点是“算法题的自动验证与代码评测辅助”,比如给在线评测系统生成补充测试数据;距离通用的软件开发测试助手还有一段路,主要瓶颈是要么有标准解、要么有可靠的人工测试锚点。

可能的问题:生成反例依赖“错误候选必须真的错误”,如果缓冲区里收集的代码只是边界用例失败而不是逻辑性错误,验证器学到的主要是边界条件排查,对深层逻辑缺陷的打击力还有待检验。


主要参考文献

Xu J, Zhang W, Lyu Z, et al. Two-Stage Reinforcement Learning for Sound and Adversarial Test Generation in Code LLMs. arXiv:2609.03955, 2025.
Shao Z, Wang P, Zhu Q, et al. DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. arXiv:2402.03300, 2024. (GRPO)
Li R, Allal L B, Zi Y, et al. StarCoder: May the Source Be with You? TACO数据集相关,2023.
Jain N, Han K, Gu A, et al. LiveCodeBench: Holistic and Contamination Free Evaluation of Large Language Models for Code. ICLR 2025.
Chen B, Zhang F, Nguyen A, et al. CodeT: Code Generation with Generated Tests. ICLR 2023.
Ma Y, Xie Y, Gou J, et al. CodeRM: A Versatile and Efficient Reward Model for Code Generation. 2025.

end
代码生成再卷出新高度:光会写代码还不够,AI还得学会给自己出题、当自己的“AI考官”!对代码大模型、RL训练、测试生成与推理时扩展感兴趣的小伙伴,欢迎加入龙哥读论文粉丝群,扫描下方二维码或者添加龙哥助手微信号加群:kangjinlonghelper。一定要备注:研究方向+地点+学校/公司+昵称(如 代码智能+上海+南洋理工+小龙),根据格式备注,可更快被通过且邀请进群。 『龙哥读论文』微信群目前包含:图像处理、大模型及智能体、自动驾驶及机器人、AI医疗及AI金融5个群~

*本文仅代表个人理解及观点,不构成任何论文审核或者项目落地推荐意见,具体以相关组织评审结果为准。欢迎就论文内容交流探讨,理性发言哦~ 想了解更多原文细节的小伙伴,可以点击"阅读原文",查看更多原论文细节哦!       

转发文章 微博 X LinkedIn Facebook
龙哥读论文 · PaperDaily

本文基于龙哥读论文 PaperDaily 数据库整理,结合论文原文与工程视角进行解读。