← 返回 2026-07-15

函数感知的填空式中间训练:面向编码智能体基础模型 Function-Aware Fill-in-the-Middle as Mid-Training for Coding Agent Foundation Models

Yubo Wang, Jiarong Liang, Yuxuan Zhang, Xuye Liu, Cong Wei, Yuyu Zhang, Ping Nie, Wenhu Chen 📅 2026-07-14 👍 102 2026-07-19 18:30
SWE-Bench 代码大模型 填空式中间训练 程序依赖图 编码智能体

用函数感知的FIM中间训练对齐智能体循环,提升SWE-Bench并缓解能力退化

前置知识

填空式训练(Fill-in-the-Middle, FIM)

FIM 是代码大模型预训练的标准自监督目标:给定一段代码,把中间某段(middle)挖空,把前后两段作为前缀(prefix)和后缀(suffix)拼成提示,让模型去补全被挖掉的部分。它训练模型在双向上下文下做条件生成,是 Code-Llama、Qwen-Coder、DeepSeek-Coder 等模型的标配成分。常见做法是随机选取一段连续 token 进行遮蔽(random-span FIM),并用 // 等哨兵 token 标记边界。

本文的方法直接建立在 FIM 之上,但批评随机跨度 FIM 与智能体场景对齐不良,并提出函数粒度的变体。理解 FIM 的基本机制是理解论文核心创新的前提。

中间训练(Mid-training)

中间训练是介于预训练和后训练之间的一个训练阶段,模型在精选语料上继续训练,以注入从通用网络文本或微调中难以获得的归纳偏置。MiniCPM、OLMo、DeepSeek-V3 等在预训练末期安排这一阶段,Code-Llama 用类似思路做上下文长度泛化。其核心动机是:专用数据引入的时机和数据量同样重要,靠近后训练引入能让信号更集中。

本文把函数感知 FIM 放在专门的中间训练阶段而非混入预训练,这是其设计的关键,理解这一阶段的定位才能明白作者为何强调信号要在后训练前集中注入。

程序依赖图(Program Dependency Graph, PDG)

程序依赖图是从源代码抽象语法树(AST)抽取的一种图结构,节点是函数/方法,边刻画它们之间的依赖关系。本文构造了两类边:调用边 E_call 连接调用者和被调用者,兄弟边 E_sib 连接同一类中的方法(刻画通过共享实例状态的类内耦合)。调用解析处理常见 Python 习语(直接调用、类实例化、self/cls 方法调用),并用短名回退匹配限定名索引。

PDG 是本文选择遮蔽目标的基石,正是用它才能把遮蔽区域选在函数粒度而非任意跨度,理解 PDG 才能理解方法的核心数据结构和选样逻辑。

编码智能体与 SWE-Bench

编码智能体是能在真实软件仓库中通过工具调用(编辑文件、运行 shell、执行测试)自主解决 GitHub issue 的 LLM 系统,如 SWE-agent、OpenHands、Agentless。SWE-Bench(含 Verified 500 题和 Lite 300 题)是衡量这种能力的核心基准,评估智能体产出的补丁能否通过隐藏测试。后训练流水线如 R2E-Gym、SWE-Smith、SWE-Lego 通过策划或合成智能体轨迹数据来提升这一能力。

SWE-Bench 是本文的主战场和主要评测指标,理解编码智能体的动作→观测→续写循环结构,才能理解作者为何认为它和函数调用点同构。

智能体后训练的能力侵蚀(Capability Erosion)

当模型在专门的智能体轨迹数据上做后训练时,虽然目标任务(如 SWE-Bench)指标上升,但会损害基座模型原本具备的其他能力。本文实测 R2E-Gym 单独后训练会让 LiveCodeBench 掉 13.10 分、BFCL 掉 7.40 分、FullStackBench-EN 掉 6.08 分,六基准平均损失 4.81 分,这是 agent 论文很少强调的隐性代价。

本文的一个重要卖点就是中间训练能同时提升 in-domain 指标并修复大部分 off-domain 退化,理解能力侵蚀现象才能体会这个收益的价值。

研究动机

编码智能体的进展几乎完全靠在后训练阶段扩充合成智能体轨迹数据(SWE-Gym、R2E-Gym、SWE-Smith 等)来驱动,而这些流水线起点的基座模型通常只是用从左到右的下一 token 预测(个别加上随机跨度 FIM)在互联网规模代码上训练得到的。这中间存在一个训练时鸿沟:基座模型几乎没有为智能体后训练将要依赖的条件化结构做专门优化。随机跨度 FIM 与智能体条件化对齐不良,原因有三:跨度边界在语法上是任意的,多数被遮蔽的片段切断表达式或半个语句,对函数级依赖信号很弱;没有推理监督,模型直接填空,缺少镜像智能体先思考再行动模式的中间理由;目标被预训练溶解掉了,等后训练开始时 FIM 带来的结构先验已被万亿无关 token 摊薄。此外,智能体后训练本身有显著隐性能力代价:R2E-Gym 单独后训练让 14B 模型的 LiveCodeBench 掉 13.10、BFCL 掉 7.40、FullStackBench-EN 掉 6.08、τ-bench 掉 2.30,六基准平均相对 Instruct 上限损失 4.81 分。

本文的目标是本文的具体目标是在预训练和智能体后训练之间插入一个专门的中间训练阶段,让基座模型在引入智能体专属数据之前,先对齐与智能体相关的归纳偏置。具体而言,作者希望利用普通代码中天然存在、且与智能体动作-观测-续写循环结构同构的函数调用点作为信号来源,设计一种自监督的函数感知 FIM 目标,从而在不修改任何现有后训练流水线的前提下,提升编码智能体基准(SWE-Bench-Verified/Lite)的通过率,同时缓解后训练对非目标能力(如 LiveCodeBench、BFCL、τ-bench)造成的退化。作者还希望这一提升在多个模型尺寸(7B/14B)、多个后训练流水线(R2E-Gym、SWE-Smith、SWE-Lego)和不同基座家族(Qwen2.5-Coder、Qwen3)上保持鲁棒。

与已有工作不同的是,本文的独特切入角度是一个结构同构观察:智能体每一步维护历史 $h_t$、采样动作 $a_t \sim \pi(a_t|h_t)$、接收外部过程产生的观测 $o_{t+1}$、再基于完整轨迹续写——这个上下文→动作→外部返回→续写的四段分解,与函数调用点完全同构:调用前代码确立意图并绑定参数、调用本身、由当前作用域外代码计算的返回值、消费该返回值的下游代码。这种条件化结构在普通代码中以互联网规模存在,而从左到右预训练却系统性地少暴露它。与随机跨度 FIM 或 AST 子树遮蔽不同,作者把遮蔽目标选在函数粒度,并用程序依赖图分析加上复杂度–可推断性双重判据,同时在 FIM 中间段嵌入思维链理由,使被遮蔽区域成为智能体相关推理单元而非语法子树。

核心方法

整体思路是先有直觉再走技术路线。直觉层面,作者把编码智能体单步循环与函数调用点对齐:上下文对应历史、动作对应调用、外部返回对应被调用者返回值、续写对应下游消费代码。由于这种结构在普通代码中大量存在,可以用自监督方式从源码中提取智能体相关信号。技术路线分四步:先收集并去污染一个 Python 语料库;再用程序依赖图(PDG)分析为每个函数打分,用复杂度–可推断性双重判据选出值得遮蔽的函数目标;接着对每个目标用前沿模型 Gemini-3-Flash 生成思维链理由并过滤;最后把理由加函数体放进 FIM 中间段,在 Qwen2.5-Coder-Instruct(7B/14B)和 Qwen3-8B 上做中间训练,再无缝接上现有后训练流水线。整个流程把训练时鸿沟变成一个独立的自监督阶段,使信号紧贴后训练之前注入。

核心创新点是把遮蔽目标从随机跨度或 AST 子树,升级为基于程序依赖图的函数粒度目标,并用一个与基座模型无关的复杂度–可推断性双重判据选样。复杂度分 $\hat{H}(v)=w_\ell\,\phi(LoC,c_\ell)+w_c\,\phi(CC,c_c)+w_d\,\phi(D,c_d)$ 综合代码行数、McCabe 圈复杂度和嵌套深度,反映该函数值不值得学;可推断性分 $\hat{I}(v)=\alpha C_{caller}+\beta C_{callee}+\gamma C_{sig}+\delta C_{doc}+\epsilon C_{class}$ 聚合五个上下文信号,反映能否从周边代码恢复函数体。两者用调和平均结合并乘难度惩罚 $\rho$:$FIM(v)=\frac{\hat{H}(v)\hat{I}(v)}{\hat{H}(v)+\hat{I}(v)+\epsilon}\cdot\rho(\Delta(v))$,强制两者同时大。与已有方法的本质区别是:被遮蔽区域是智能体相关推理单元而非语法片段,理由被放进 FIM 中间使模型先思考后写码,且整个目标生活在专门的中间训练阶段而非被预训练摊薄。

方法步骤详情

方法分四步。第一步数据收集与去污染:从约 2000 个 GitHub 候选库筛出 968 个 Python 仓库,按仓库名和已知 fork 移除与 SWE-Bench 源仓库重叠者,并限制提交时间早于最早 base-commit,得到约 40 万条 FIM 样本(约 2.6B token):32 万单函数、6 万对、2 万三连。第二步选样:解析 AST 构造节点集 $V$、调用边 $E_{call}$、兄弟边 $E_{sib}$;为每个 $v$ 算 $\hat{H}$ 与 $\hat{I}$,用阈值 $\tau=0.08$ 选目标;多函数版本按 8 种拓扑(caller-callee、call-chain、hub、fan-in 等)挑 2–3 个结构相连的函数组。第三步思维链增强:Gemini-3-Flash 只看遮蔽后文件产出理由和候选函数体(看不到真实体),另一评审按可行性和五维度打分保留约 40 万样本,再格式化为 `前缀后缀理由+函数体`。第四步训练:用标准 FIM 损失(仅对中间段计损失)在 Qwen2.5-Coder-Instruct(7B/14B)和 Qwen3-8B 上中间训练,打包到原生上下文长度并用原生 FIM 哨兵 token,随后不修改地接上 R2E-Gym、SWE-Smith 或 SWE-Lego 后训练。

技术新颖性

技术新颖性体现在四点。第一,目标选择是函数粒度的:通过 PDG 分析和复杂度–可推断性双重判据选样,被遮蔽区域是智能体相关推理单元而非 AST 子树或随机跨度;第二,思维链理由嵌入在 FIM 中间段内,理由在函数体之前,使模型学到先思考后写符合智能体先思考再行动的结构;第三,目标生活在专门的中间训练阶段,把信号紧贴后训练之前注入,而非被预训练万亿 token 摊薄;第四,$\hat{H}$ 与 $\hat{I}$ 都是与基座模型无关的人工设计代理量(不依赖参考模型的可学习预测分),这避免了把选样耦合到某个特定模型,从而支持跨基座泛化分析。消融还表明:FIM 结构本身(无 CoT)已能贡献约一半增益,并非前沿教师蒸馏的变体;函数选择算法是主导杠杆(随机 13.95 → 完整 15.60);多函数遮蔽有用但三连饱和(80%/15%/5% 混合达 16.10)。

Function call site and coding-agent step share the same 4-stage decomposition; FIM mid-training yields consistent SWE-Bench gains across models
Figure 1: Function call site and coding-agent step share the same 4-stage decomposition; FIM mid-training yields consistent SWE-Bench gains across models
Function-aware FIM target selection on a small calculator example
Figure 2: Function-aware FIM target selection on a small calculator example

实验结果

核心发现分四组。第一,主结果一致提升:固定 R2E-Gym,中间训练让 SWE-Bench-Verified 在 7B +2.80(15.00→17.80)、14B +3.00(26.20→29.20),Lite +3.67/+4.00,说明更大预训练检查点并未吸收掉该结构先验。第二,跨流水线与跨基座:7B 换 SWE-Smith,Verified +5.30(12.30→17.60)、Lite 仅 +0.50;换 Qwen3-8B 配 SWE-Lego,Verified +3.20(31.80→35.00)、Lite +5.40。第三,能力保持与跨域迁移:14B 上 R2E-Gym 把 LiveCodeBench 从 37.20 砸到 24.10,加中间训练后恢复到 35.20(+11.10),τ-bench +3.90、BFCL +2.40,六基准平均从 16.04 升到 19.56;语料只含 Python 无工具轨迹,τ-bench/BFCL 提升是函数调用同构的直接证据。第四,机制分析:负向观测恢复率 24.8%→28.8%(相对 +16%),每解一题编辑数 3.3→7.4;增益集中在多函数推理——88 个金补丁改 ≥2 函数的任务上 +9.1 pp,是单函数任务(+2.1)的 4 倍多。

Main results on coding agent benchmarks (SWE-Bench-Verified, SWE-Bench-Lite, Average)
Table 1: Main results on coding agent benchmarks (SWE-Bench-Verified, SWE-Bench-Lite, Average)
Capability preservation and cross-domain transfer at 14B with R2E-Gym
Table 2: Capability preservation and cross-domain transfer at 14B with R2E-Gym
Ablations on 7B with R2E-Gym: CoT source, function-selection algorithm, mask granularity
Table 3: Ablations on 7B with R2E-Gym: CoT source, function-selection algorithm, mask granularity
Headline trajectory metrics on SWE-Bench-Verified
Table 4: Headline trajectory metrics on SWE-Bench-Verified
查看结构化数据
任务指标本文基线提升
SWE-Bench-Verified(Qwen2.5-Coder-7B + R2E-Gym) 解决率(%,3 种子均值) 17.80(±1.40) 15.00(±1.50,仅 R2E-Gym 复现) +2.80
SWE-Bench-Verified(14B + R2E-Gym) 解决率(%) 29.20(±1.50) 26.20(±1.40) +3.00
SWE-Bench-Verified(Qwen3-8B + SWE-Lego) 解决率(%) 35.00(±1.50) 31.80(±1.00) +3.20
SWE-Bench-Verified(7B + SWE-Smith) 解决率(%) 17.60(±1.30) 12.30(±1.20) +5.30
SWE-Bench-Lite(14B + R2E-Gym) 解决率(%) 22.00(±1.20) 18.00(±1.10) +4.00
LiveCodeBench(14B,跨域能力保持) 解决率(%) 35.20 24.10(仅 R2E-Gym) +11.10
τ-bench(14B,非编码工具使用迁移) 解决率(%) 7.30 3.40(仅 R2E-Gym) +3.90
负向观测恢复率(14B Verified) 恢复率(%) 28.8 24.8 +4.0 pp(相对 +16%)

局限与改进

作者明确给出四条局限。第一,语料和评测都仅限 Python,跨语言证据只通过 FullStackBench-EN 间接获得,迁移到 Java、C++、Rust 留待未来。第二,思维链依赖前沿教师 Gemini-3-Flash,虽然 self-CoT 消融显示自生成理由能恢复大部分增益,但完全开源复现仍需要一个同等强度的开源教师。第三,跨基座证据只有一组非 Qwen2.5 配置(Qwen3-8B 配 SWE-Lego),它同时改变了后训练流水线,是混淆变量,因此结论应读作不绑死某一组合而非跨所有基座家族有保证。第四,方法预设模块化代码,对单体脚本、生成代码或 notebook,流水线产出的合格目标更少,这一情形未被系统研究。补充观察:绝对增益不算大,且作者复现的 R2E-Gym 基线(7B Verified 15.00)低于官方报告的 19.00,部分提升可能受益于相对偏低的复现基线;τ-bench/BFCL 的跨域迁移机制虽被归因为结构先验,但仍偏推测性,缺乏更直接的探针证据。

独立分析的弱点

第一个弱点是语料仅 Python、缺乏跨语言验证。改进方向是把 PDG 解析、调用解析和复杂度–可推断性判据扩展到 Java/C++/Rust 等多语言 AST,并在对应语言的智能体基准上验证迁移。第二个弱点是依赖前沿教师 Gemini-3-Flash 生成 CoT,这削弱了开源可复现性;改进方向是用更强的开源教师(如 Qwen3-Coder 大尺寸)或引入自一致性过滤/拒绝采样来稳定 self-CoT,使完全开源配方达到接近的增益。第三个弱点是跨基座证据只有一组配置且混淆了后训练流水线;改进方向是用网格化消融——固定基座换流水线、固定流水线换基座——把基座家族效应和流水线效应解耦。第四个弱点是方法依赖模块化代码,对 notebook、生成代码、单体脚本产出的合格目标少;改进方向是引入更宽松的'逻辑块'定义或基于数据流而非 AST 函数定义的选样,并研究这类代码域下的退化机制。第五个弱点(独立观察)是绝对增益有限且复现基线偏低,改进方向是与更强基线(如官方 R2E-Gym 数值或 RL 后训练)正面对比,并报告达到统计显著的种子数。

未来方向

作者明确提出的未来工作有两条:把选样扩展到非 Python 语言;把中间训练与 RL 后训练组合。基于本文成果可延伸的方向包括:把函数调用点同构推广到更丰富的智能体结构,如多步工具链、检索增强上下文中的插入点,设计对应的结构化遮蔽目标;研究 $\hat{H}$ 与 $\hat{I}$ 的可学习版本,但要小心保持与基座解耦以不破坏跨模型分析;把多函数组遮蔽从 2–3 个扩展到跨文件依赖,以缓解当前多文件任务不被差异化帮助的粒度失配;探索中间训练信号在强化学习阶段的复用,例如把 FIM 目标作为辅助损失或课程;以及研究该先验对长上下文智能体(需跨多文件推理)的迁移。此外,可以把这套选样-过滤-格式流水线迁移到非代码的'调用-返回'结构领域,例如 SQL/Shell/配置文件中的函数式抽象。

复现评估

复现性整体较好。作者开源了 968 仓库的去污染语料库(约 40 万 FIM 样本、2.6B token)、完整选样流水线和中间训练检查点,代码仓库为 https://github.com/TIGER-AI-Lab/FIM-Midtraining 。数据去污染规则(按仓库名和已知 fork 移除与 SWE-Bench 源仓库重叠者,限制提交时间早于最早 base-commit)描述清楚,能有效抑制泄漏。选样算法(单函数见附录 B.1、多函数见 B.7、$\hat{H}/\hat{I}$ 权重见 B.3/B.4、阈值 $\tau=0.08$ 见 B.5)和训练超参(附录 C)都有交代。难点有三:默认 CoT 依赖 Gemini-3-Flash 闭源教师,完全开源复现需自备等强教师;SWE-Bench 评测算力成本高,需跑 OpenHands/SWE-agent 等 scaffold 并多种子(3 个)才能拿到稳定均值;Qwen3-8B 的 SWE-Lego 只训练 2 epoch(非官方 4),复现需对齐这一过拟合防护设定。综合看方法可复现,但端到端跑通需显著工程与算力投入。