代码偏好优化的函数级执行反馈
摘要
本文提出Step-KTOder,这是一个用于代码偏好优化的框架,它使用函数级执行反馈与单元测试相结合,在HumanEval+和MBPP+等基准测试上优于仅基于结果的方法(如KTO和DPO)。
arXiv:2608.23632v1 公告类型:新
摘要:过程监督在数学推理中已有所改进,其中中间步骤自然地表现为思维链。然而,在代码生成中,过程监督仍未被充分探索,因为没有标准的步骤概念。监督可以针对行、推理轨迹或程序状态,导致不清楚标记和优化什么。我们提出STEP-KTODER,这是一个代码偏好优化框架,它将步骤定义为分解的多函数程序中的模块级函数,并通过自动生成的单元测试分配二进制正确性标签。我们的方法提供了逐步KTO的代码特定实例化,将函数级过程监督与整个程序的基于结果的反馈相结合。我们在HumanEval(+)、MBPP(+)、BigCodeBench和LiveCodeBench上进行评估,显示STEP-KTODER优于仅基于结果的KTO和DPO。进一步分析表明,基于执行的标签至关重要:LLM作为法官的注释系统性地过度预测函数故障,破坏正步骤标签,并降低下游偏好优化。代码可在以下地址获取:https://github.com/inechnech/STEP-KTODER。
查看缓存全文
缓存时间: 2026/08/26 09:10
# 面向代码偏好优化的函数级执行反馈
来源:https://arxiv.org/html/2608.23632
Idris Nechnech, Sehwan Kim
affiliation: 首尔大学电气与计算机工程系
Jimin Seo
affiliation: 首尔大学电气与计算机工程系
Yeongoon Kim
affiliation: 首尔大学电气与计算机工程系
Minhae Oh
affiliation: 首尔大学电气与计算机工程系
Sangwoo Hong
affiliation: 建国大学计算机科学与工程系
\{inechnech, junglee\}@snu\.ac\.kr
Jungwoo Lee
###### 摘要
过程监督在数学推理中取得了进展,其中的中间步骤自然地表达为思维链。然而,在代码生成中,过程监督的探索仍然不足,因为缺乏步骤的标准定义。监督可以针对行、推理轨迹或程序状态,因此不清楚应该标注和优化什么。我们提出了 **Step-KTOder**,一个用于代码偏好优化的框架,它将步骤定义为分解的多函数程序中的模块级函数,并通过自动生成的单元测试分配二元正确性标签。我们的方法提供了分步KTO的代码特定实例化,将函数级过程监督与整个程序的结果级反馈相结合。我们在 HumanEval\(\+\)、MBPP\(\+\)、BigCodeBench 和 LiveCodeBench 上进行了评估,表明 **Step-KTOder** 优于仅基于结果的KTO和DPO。进一步分析表明,基于执行的标签至关重要:LLM-as-a-judge 标注系统性地过度预测函数失败,破坏了正向步骤标签,并降低了下游偏好优化的效果。代码可在以下地址获取:https://github.com/inechnech/STEP-KTODER\.
\$\dagger\$\$\dagger\$footnotetext:通信作者\.
## 1 引言
代码生成已成为大型语言模型(LLMs)的一个主要应用领域,最近专门针对代码的模型在各种编程任务上取得了强劲表现\((8 (https://arxiv.org/html/2608.23632#bib.bib9);11 (https://arxiv.org/html/2608.23632#bib.bib10))\)\. 这些模型通常通过两个阶段进行改进:在高质量代码数据上进行监督微调(SFT)\((30 (https://arxiv.org/html/2608.23632#bib.bib31))\),然后通过一个对齐阶段使模型适应更好的输出\((24 (https://arxiv.org/html/2608.23632#bib.bib30))\)\. 在对齐方法中,直接偏好优化(DPO)\((26 (https://arxiv.org/html/2608.23632#bib.bib8))\) 被广泛用于从成对的偏好数据中学习,而卡尼曼-特沃斯基优化(KTO)\((7 (https://arxiv.org/html/2608.23632#bib.bib4))\) 则从单个输出的二元合意性标签中学习\. 然而,将这些技术应用于代码生成并非易事\. 这些方法通常在整个程序层面进行实例化,将完整解决方案作为单一的反馈单元\. 这只提供了粗糙的训练信号:一个程序可能大部分正确,仅在狭窄的边缘情况下失败,但结果级监督仍然将整个输出标记为不理想\. 这种监督无法揭示哪个组件是正确的,哪个组件导致了失败,因此需要更细粒度的代码生成监督\. 在数学推理中,*过程监督*——对中间推理步骤提供反馈——已被证明非常有效\((17 (https://arxiv.org/html/2608.23632#bib.bib1);21 (https://arxiv.org/html/2608.23632#bib.bib2);29 (https://arxiv.org/html/2608.23632#bib.bib11))\),过程奖励模型(PRMs)支撑了最先进的推理系统\. 基于这一成功,18 (https://arxiv.org/html/2608.23632#bib.bib3) 将分步二元反馈与KTO相结合,联合优化数学问题解答的中间和最终答案质量\. 然而,将这一想法迁移到代码生成仍然是一个未解决的挑战:代码不能自然地分解为单一的标准化中间逻辑步骤序列,使得“步骤”的定义本身就很模糊\.
参考说明
图1:**Step-KTOder** 框架概述\. 参考解 $y^\{\\star\}$ 被分解为模块级函数 $s_\{1\},\\ldots,s_\{n\}$,并为每个函数生成函数级单元测试\. 候选补全根据这些测试进行评估,以获得指示局部正确性的步骤标签 $z_i$,同时从数据集提供的测试套件中获得结果标签 $o$\. 生成的带标签数据用于训练模型,采用结合结果级KTO ($\mathcal\{L\}\_\{\mathrm\{out\}\}$) 和函数级监督 ($\mathcal\{L\}\_\{\mathrm\{step\}\}$) 的联合目标,在强化局部正确函数的同时惩罚局部不正确的函数\.
我们通过将步骤定义为分解程序中的模块级函数来解决这一模糊性,并提出了 **Step-KTOder**,一个为代码生成带来函数级过程监督的框架\. 我们的关键思想是,分解后的程序提供了可执行的步骤结构:当一个解被编写为多个函数时,每个函数都可以使用自动生成的单元测试进行独立测试,从而获得局部正确性的二元标签\. **Step-KTOder** 使用这些标签来扩展结果级KTO,加入函数级监督,通过全局程序成功和局部正确性(如图1所示 \((https://arxiv.org/html/2608.23632#S1.F1))\) 来指导训练\. 除了主要的实证增益外,我们还研究了两个对 **Step-KTOder** 有效性很重要的设计选择\. 首先,通过数据集提供测试但包含局部不正确函数的程序,提供了一种仅基于结果的训练无法表达的监督形式\. 我们发现,保留这些局部/全局不匹配可以增强步骤级监督的好处,而掩盖此类不匹配则会大大削弱信号\. 其次,我们评估了自动生成的单元测试是否是可靠步骤监督所必需的,用LLM-as-a-judge标注替代了基于执行的步骤标签\. 尽管这些标注与基于执行的标签表现出中等程度的一致性,但它们系统性地过度预测步骤失败,并且当用于 **Step-KTOder** 训练时,会降低性能\. 即使对于已经经过指令微调的Qwen2\.5-Coder模型,**Step-KTOder** 也实现了显著的改进:在BigCodeBench Hard\((35 (https://arxiv.org/html/2608.23632#bib.bib23))\) 和 LiveCodeBench\((12 (https://arxiv.org/html/2608.23632#bib.bib24))\) 上分别比基础模型提高了高达 \+26\.7\% 和 \+27\.0\%\. 我们的贡献如下:
- • 我们提出了 **Step-KTOder**,一个分步KTO的代码特定实例化,将函数级过程监督与结果级反馈相结合\.
- • 我们引入了一个自动数据构建流程,将解决方案分解为函数,生成函数级单元测试,并推导出用于训练的基于执行的步骤标签\.
- • 在广泛使用的基准上的实验表明,**Step-KTOder** 改进了训练后的代码模型\. 我们进一步证明,用LLM-as-a-judge标注替代基于执行的步骤标签会削弱步骤级信号并降低性能\.
## 2 相关工作
### 2.1 推理的过程监督
过程监督在数学推理中非常有效,其中步骤级反馈优于仅基于结果的监督\((5 (https://arxiv.org/html/2608.23632#bib.bib29);28 (https://arxiv.org/html/2608.23632#bib.bib12);17 (https://arxiv.org/html/2608.23632#bib.bib1))\)\. 后续工作扩大了这种监督规模:29 (https://arxiv.org/html/2608.23632#bib.bib11) 通过蒙特卡洛估计引入了自动步骤级标注,21 (https://arxiv.org/html/2608.23632#bib.bib2) 提出了一种用于大规模过程监督数据的分治蒙特卡洛树搜索框架\. 18 (https://arxiv.org/html/2608.23632#bib.bib3) 引入了 Step-KTO,它将KTO与PRM标注的分步反馈相结合,联合优化中间推理质量和最终响应正确性\. 我们的工作基于这一思想,但针对代码进行了重新表述:我们不是使用PRM标注的推理步骤,而是将步骤定义为具体的、可独立测试的函数,并直接通过基于执行的单元测试反馈进行监督\. 这一观点与最近关于代码PRM的研究一致,表明执行反馈提高了代码过程监督的可靠性\((15 (https://arxiv.org/html/2608.23632#bib.bib7))\)\. 与PRM训练不同,我们研究如何将基于执行的过程标签直接纳入离线偏好优化\.
### 2.2 代码的偏好优化
偏好优化已成为代码模型的标准训练后技术\. DPO\((26 (https://arxiv.org/html/2608.23632#bib.bib8))\) 从成对偏好中学习,而KTO\((7 (https://arxiv.org/html/2608.23632#bib.bib4))\) 利用基于前景理论的二元合意性标签,消除了对配对数据的要求\. 最近的研究探索了针对代码的局部化和细粒度反馈:34 (https://arxiv.org/html/2608.23632#bib.bib5) 将DPO损失集中在容易出错的token跨度上,而31 (https://arxiv.org/html/2608.23632#bib.bib33) 引入了Target-DPO,一个将偏好更新定位到目标代码区域的聚焦偏好对齐框架\. 6 (https://arxiv.org/html/2608.23632#bib.bib6) 通过强化学习训练了一个PRM,在代码生成过程中提供密集的行级反馈\. 33 (https://arxiv.org/html/2608.23632#bib.bib13) 引入了CodeDPO,它构建自生成的偏好对来对齐代码模型以兼顾正确性和效率\. 这些方法针对不同的粒度——token、代码块、行或整个程序——但据我们所知,这些方法中没有一个将步骤定义为具有语义意义、可独立测试的函数,并将它们集成到二元偏好优化目标中\.
### 2.3 解决方案分解与自动化测试
填空目标\((2 (https://arxiv.org/html/2608.23632#bib.bib14))\) 训练模型在给定周围上下文的情况下完成代码,鼓励模块化结构\. 27 (https://arxiv.org/html/2608.23632#bib.bib32) 将这一思想扩展到对齐,将代码分割成基于AST的块,为DPO构建更多样化的偏好对\. 基于提示的方法也强调了代码生成的模块化分解:25 (https://arxiv.org/html/2608.23632#bib.bib27) 通过分层提示将复杂的编程问题分解为更小的推理模块\. 19 (https://arxiv.org/html/2608.23632#bib.bib15) 提出了同时生成代码和单元测试,然后使用自验证来增强生成质量\. 自动化单元测试生成技术已相当成熟\((3 (https://arxiv.org/html/2608.23632#bib.bib17);22 (https://arxiv.org/html/2608.23632#bib.bib16))\);我们的流程利用这一能力在函数级设置中发挥作用,为单个函数生成测试,并将执行结果作为训练的二元步骤标签\.
### 2.4 基于执行的推理时方法
最近的基于执行的方法则在推理时改进代码\. S* 将并行采样与迭代调试相结合,并使用自适应合成的输入及其执行结果在候选者中进行选择\((14 (https://arxiv.org/html/2608.23632#bib.bib34))\),而ORPS则探索由执行结果和自我批评引导的推理和代码轨迹树\((32 (https://arxiv.org/html/2608.23632#bib.bib35))\)\. 与这些每查询搜索和选择方法不同,**Step-KTOder** 在离线数据构建期间使用函数级执行来生成标签,以更新模型策略\.
## 3 方法
### 3.1 问题表述
给定提示 $x$ 和参考解 $y^\{\\star\}$,我们首先使用一个强大的代码语言模型将 $y^\{\\star\}$ 重写为分解的多函数程序 $\tilde\{y\}=(s_\{1\},s_\{2\},\\dots,s_\{n\})$,其中每个 $s_\{i\}$ 表示分解程序中的一个函数,$n$ 是此类函数的总数\. 我们将每个函数 $s_\{i\}$ 视为一个*步骤*\. 然后从此分解中生成训练样本:目标模型填充 $\tilde\{y\}$ 定义的函数骨架,产生候选解 $y$\. 每个训练样本获得两种形式的二元监督:
- • 一个结果标签 $o\in\\{0,1\\}$,指示 $y$ 是否通过数据集提供的测试套件对 $x$ 的测试\.
- • 一个步骤标签序列 $\mathbf\{z\}=(z_\{1\},\\dots,z_\{n\})$,其中每个 $z_\{i\}\\in\\{0,1,\\varnothing\\}$ 指示 $y$ 中 $s_\{i\}$ 的实现是否通过其函数级单元测试\. 标签 $\\varnothing$ 表示该步骤没有有效的单元测试可用\. 这种表述区分了*局部正确性*和*全局正确性*,提供了比仅基于结果评估更细粒度的监督\. 它不是将部分正确的程序统一视为合意或不合意,而是使目标能够强化正确的函数,同时惩罚导致失败的函数\.
### 3.2 KTO背景
我们基于卡尼曼-特沃斯基优化(KTO)\((7 (https://arxiv.org/html/2608.23632#bib.bib4))\),它使用卡尼曼-特沃斯基启发的值函数,基于策略 $\pi_\{\theta\}$ 和冻结参考策略 $\pi_\{\mathrm\{ref\}\}$ 之间的对数比率,从二元反馈中对齐策略:$r_\{\theta\}(x,y)=\\log\\frac\{\pi_\{\theta\}(y\\mid x)\}\{\pi_\{\mathrm\{ref\}\}(y\\mid x)\}$\. 结果级参考点为 $z_\{0\}^\{\mathrm\{out\}\}=\\mathrm\{KL\}\\!\\left\(\\pi_\{\theta\}(y^\{\\prime\}\\mid x)\\;\\middle\\|\\;\\pi_\{\mathrm\{ref\}\}(y^\{\\prime\}\\mid x)\\right\)$,其中 $y^\{\\prime\}$ 表示用于估计策略和参考之间散度的输出序列\. 给定二元合意性标签 $o\in\\{0,1\\}$,结果级值函数为:
$$v_\{\mathrm\{out\}\}=\\begin\{cases\}\\lambda_\{D\}\\,\\sigma\\!\\bigl\(\\beta_\{\mathrm\{out\}\}(r_\{\theta\}\-z_\{0\}^\{\mathrm\{out\}\})\\bigr\),&o=1,\\\\\[2\.0pt\] \\lambda_\{U\}\\,\\sigma\\!\\bigl\(\\beta_\{\mathrm\{out\}\}(z_\{0\}^\{\mathrm\{out\}\}\-r_\{\theta\})\\bigr\),&o=0,\\end\{cases\}$$
其中 $r_\{\theta\}\\equiv r_\{\theta\}(x,y)$ 且 $\sigma(\\cdot)$ 表示sigmoid函数\. $\beta_\{\mathrm\{out\}\}>0$ 控制结果级值函数的敏感度,$\lambda_\{D\}$ 和 $\lambda_\{U\}$ 分别加权合意和不合意样本\. 结果级KTO损失为 $\mathcal\{L\}\_\{\mathrm\{out\}\}(\\pi_\{\theta\},\\pi_\{\mathrm\{ref\}\})=\\mathbb\{E\}\_\{\(x,y,o\)\\sim\\mathcal\{D\}\\}\\bigl\[\\lambda_\{o\}\-v_\{\mathrm\{out\}\}\\bigr\]$,其中如果 $o=1$ 则 $\lambda_\{o\}=\\lambda_\{D\}$,如果 $o=0$ 则 $\lambda_\{o\}=\\lambda_\{U\}$\.
### 3.3 Step-KTO 目标
我们遵循18 (https://arxiv.org/html/2608.23632#bib.bib3),在第3\.1节定义的函数级步骤上实例化分步KTO,并为未经过验证的本地测试的函数引入可靠性掩码\. 对于每个步骤 $s_\{i\}$,我们计算该函数token上的步骤局部对数比率:$r_\{i\}=\\sum_\{t\\in s_\{i\}\}\\log\\frac\{\pi_\{\theta\}(y_\{t\}\\mid x,y_\{\(<t\}\})\}\{\pi_\{\mathrm\{ref\}\}(y_\{t\}\\mid x,y_\{\(<t\}\})\}$,其中 $y_\{\(<t\}\}$ 表示在函数 $s_\{i\}$ 中位于token $t$ 之前的token序列\. 参考点计算为 $z_\{0,i\}^\{\mathrm\{step\}\}=\\mathrm\{KL\}\\!\\left\(\\pi_\{\theta\}(y^\{\\prime\}_\{s_\{i\}\}\\mid x, y^\{\\prime\}_\{<s_\{i\}\})\\;\\middle\\|\\;\\pi_\{\mathrm\{ref\}\}(y^\{\\prime\}_\{s_\{i\}\}\\mid x, y^\{\\prime\}_\{<s_\{i\}\})\\right\)$,其中 $y^\{\\prime\}$ 是用于估计的输出序列\. 对于每个函数 $s_\{i\}$,基于其步骤标签 $z_\{i\}\\in\\{0,1,\\varnothing\\}$ 的步骤级值函数为:
$$v_\{\mathrm\{step\}\}_\{i\}=\\begin\{cases\}\\lambda_\{D\}\\,\\sigma\\!\\bigl\(\\beta_\{\mathrm\{step\}\}(r_\{i\}\-z_\{0,i\}^\{\mathrm\{step\}\})\\bigr\),&z_\{i\}=1,\\\\\[2\.0pt\] \\lambda_\{U\}\\,\\sigma\\!\\bigl\(\\beta_\{\mathrm\{step\}\}(z_\{0,i\}^\{\mathrm\{step\}\}\-r_\{i\})\\bigr\),&z_\{i\}=0,\\\\\[2\.0pt\] 0,&z_\{i\}=\\varnothing.\\end\{cases\}$$
这里,$\beta_\{\mathrm\{step\}\}>0$ 控制步骤级值函数的敏感度\. 当 $z_\{i\}=\\varnothing$(即没有有效的单元测试)时,损失被屏蔽(贡献为零)\. 步骤级KTO损失是所有 $n$ 个函数上的平均值:$\mathcal\{L\}\_\{\mathrm\{step\}\}=\\mathbb\{E\}\_\{(x,y,\mathbf\{z\}\)\\sim\\mathcal\{D\}\\}\\bigl\[\\frac\{1\}\{n\}\\sum_\{i=1\}^\{n\}\(\\lambda_\{o,i\}\-v_\{\mathrm\{step\}\}_\{i\})\\bigr\]$,其中 $\lambda_\{o,i\}=\\lambda_\{D\}$ 如果 $z_\{i\}=1$,$\lambda_\{o,i\}=\\lambda_\{U\}$ 如果 $z_\{i\}=0$,并且当 $z_\{i\}=\\varnothing$ 时 $\lambda_\{o,i\}=0$\. 最终的训练目标是两个损失的加权和:$\mathcal\{L\}=\\alpha\\,\\mathcal\{L\}\_\{\mathrm\{out\}\}+(1\-\\alpha)\\,\\mathcal\{L\}\_\{\mathrm\{step\}\}$,其中 $\alpha\\in[0,1]$ 控制函数级监督相对于结果级监督的权重\. 在实践中,$\alpha$ 作为一个超参数进行调整\.
### 3.4 数据构建管道
我们的自动数据构建管道由以下步骤组成:
1. **参考解分解**:对于每个数据集样本 $(x, y^\{\\star\})$,我们使用一个强大的代码LLM(例如 GPT-4)将参考解 $y^\{\\star\}$ 重写为由模块级函数组成的程序 $\tilde\{y\}$,确保函数签名和文档清晰\. 生成的程序 $\tilde\{y\}$ 保留了 $y^\{\\star\}$ 的功能,但具有明确的函数边界\.
2. **函数级单元测试生成**:对于 $\tilde\{y\}$ 中的每个函数 $s_\{i\}$,我们自动生成一组单元测试 $\mathcal\{T\}_\{i\}=\{t_\{1\}, t_\{2\}, \\dots, t_\{k\}\}$\. 测试生成过程使用一个代码LLM,并接受函数签名、文档字符串以及从整个程序中提取的相关全局变量/类型作为输入,以生成覆盖正常和边缘情况的多样化测试\. 生成的测试被解析并执行,以确保其有效性,并过滤掉会导致语法错误或无限循环的无效测试\.
3. **步骤标签生成**:对于通过提示 $\tilde\{y\}$ 和一些训练示例采样的候选解 $y$,我们通过提取每个函数 $s_\{i\}$ 的实现来生成步骤标签 $\mathbf\{z\}$\. 对于每个函数,我们在其生成的单元测试 $\mathcal\{T\}_\{i\}$ 上执行其实现\. 如果所有测试都通过,则 $z_\{i\}=1$(局部正确);如果有任何测试失败,则 $z_\{i\}=0$(局部错误);如果无法生成有效测试(即 $\\mathcal\{T\}_\{i\}$ 为空),则 $z_\{i\}=\\varnothing$(未定义)\. 我们注意到,即使一个函数 $s_\{i\}$ 在其局部测试中失败($z_\{i\}=0$),整个程序 $y$ 仍然可能通过数据集测试($o=1$),例如,如果函数 $s_\{i\}$ 在参考解中未被使用,或者该函数的错误未被数据集测试检测到\. 这种局部/全局不匹配是细粒度监督的关键信号\.
### 3.5 实现细节
我们的方法在概念上很简单,但实现上涉及一些工程细节,这些细节在附录中进行了详细说明\. 关键点包括:(1)分解策略:我们使用少量示例提示,要求LLM将参考解重写为一个主要函数和若干辅助函数,(2)测试生成:我们使用专门的提示来为每个函数生成测试,(3)执行沙箱:我们使用安全的沙箱环境来执行生成的代码和单元测试,(4)标签可靠性:我们通过多次采样来估计标签的可靠性,并丢弃高方差的标签\. 这些步骤确保了用于训练的标签质量和稳定性\.相似文章
通过语法引导和语义感知偏好优化改进代码翻译
本文提出CTO方法,通过对比学习和直接偏好优化结合语法引导与语义感知偏好优化来改进代码翻译,在C++、Java和Python翻译中显著优于现有基线。
代码优化的强化学习
本文针对使用强化学习进行代码优化时面临的挑战,提出了三个阶段:通过DMC-Optim改进测试方法;通过正确性与速度组合以及离线模拟器将执行时间转化为奖励;以及调整GRPO以适应含噪时序奖励。该方法在代码优化基准测试中取得了显著提升。
提示优化为何有效,为何有时无效:基于因果启发的编辑级分析
本文对自动化提示优化进行了基于因果启发的分析,涵盖多种框架、大语言模型和任务,识别出特定编辑类型(如复杂度增加型、元指令型)根据任务特征具有系统的负面或正面效应,从而解释了泛化失败的原因。
TD-DPO: 差异感知偏好优化在临床自闭症干预对话中缓解谄媚行为
本文提出TD-DPO,一种令牌级差异感知偏好优化方法,用于缓解临床自闭症干预对话中大语言模型的谄媚行为,在减少谄媚行为和保持干预能力之间实现了更好的权衡。
偏好树优化:利用前瞻模拟增强目标导向对话
本文介绍了偏好树优化(PTO)框架,该框架通过前瞻模拟生成偏好数据,以迭代改进目标导向对话代理。实验表明,在动机访谈场景中取得了性能提升。