原始英文摘要
arXiv:2610.35616v1 Announce Type: new Abstract: Skills provide agents with reusable experience to guide future decisions without modifying the underlying model. However, coding trajectories are often entangled with task- and repository-specific contexts, making it challenging to distill procedural skills that generalize across diverse coding environments. To address this challenge, we present Hierarchical Skill Evolution (HSE), which progressively distills procedural knowledge from coding trajectories through hierarchical evidence aggregation. HSE first extracts task-level evidence from individual trajectories, then aggregates recurring evidence within the same repository to form repository-specific skill candidates, and finally consolidates consistent patterns across repositories into transferable skills across repositories. The evolution is driven by an external writer-evaluator loop that generates and assesses skills while keeping the underlying coding model frozen. The loop externally updates the writer and evaluator policies to improve subsequent skill generation and assessment. This hierarchy progressively filters task-specific details while preserving procedures that generalize across diverse coding environments. Successful trajectories yield reusable guidance for future tasks, while failed trajectories reveal recurring failure modes that guide avoidance and recovery. We evaluate HSE on SWE-bench Verified and DeepSWE, using GLM-5.2 across Pi and Claude Code harnesses and GPT-5.5 and Opus 4.8 with Pi. Across both benchmarks, 10 skills evolved solely from SWE-Gym improve coding performance across all evaluated settings, demonstrating transfer across benchmarks, coding models, and agent harnesses. We further evolve the skill library from target-benchmark trajectories without verifier feedback, relying solely on the learned evaluator for candidate assessment and achieving additional gains through benchmark-tailored skills.
1. 问题与价值
这篇论文解决的核心问题是:如何从编码智能体的历史执行轨迹中,蒸馏出可跨任务、跨仓库、跨模型复用的程序性技能,而不是只能复述某一次具体修复的补丁或路径。
问题的难点在于,一条编码轨迹天然与具体 issue、仓库结构、文件路径、测试命令和最终 patch 纠缠在一起。直接复用轨迹容易诱导智能体照抄旧方案;而过于宽泛的领域知识又无法告诉智能体如何定位具体 bug、约束补丁范围、验证受影响行为,或在错误编辑后恢复。
论文的价值在于提出了一种分层证据聚合机制:先在任务级提取证据,再在同一仓库内聚合出仓库条件化的候选技能,最后跨仓库合并出可迁移的程序性技能和恢复技能。受益者是使用冻结编码模型做仓库级软件修复的团队:他们可以在不微调模型、不改变底层权重的前提下,通过注入少量技能文档提升修复成功率,并且这些技能可以跨 benchmark、跨 agent harness、跨底层模型迁移。
2. 已有工作的不足
在 HSE 之前,相关工作大致有几类:
SWE-Exp。它保留具体证据,但容易让智能体复制与先前任务或仓库强绑定的解决方案。SWESkillsBench。它提供宽泛的领域知识,但论文指出这类知识不告诉智能体如何定位特定 bug、约束 patch、验证受影响行为或从错误编辑中恢复。实验也显示它在 SWE-bench Verified 上略优于 No Skills,但在 DeepSWE 上反而下降。Trace2Skill、SkillOpt、ReasoningBank、GEPA、AutoSkill、SkillOS、MUSE-Autoskill、SkillRL。这些方法证明了经验可以转化为可复用指令,但论文认为它们没有解决一个核心问题:证据应该在什么层级聚合,才能在去掉任务特定细节的同时,保留让经验真正有用的程序。论文特别指出,已有方法缺少 HSE 这种“任务级 → 仓库级 → 跨仓库级”的程序性证据聚合路径。
3. 重建作者的思考路径
如果我从旧方法出发,面对“轨迹太具体、领域技能太宽”的问题,首先会想到:能不能把轨迹里的成功步骤抽象成自然语言规则,比如“先复现、再定位、再最小编辑、再验证”。这其实就是很多 prompt 优化或技能蒸馏方法在做的事。
但马上会撞上一个矛盾:如果只从单条成功轨迹抽象,得到的规则很容易带上该任务的路径和 patch 形状。比如某次修复是在
django/forms/models.py里改add_fields(),抽象出来的规则可能变成“检查add_fields()中的默认值清除逻辑”。这条规则换一个仓库就没用了。于是自然会想到:不要从单条轨迹抽象,而是先看同一个仓库里的多条轨迹。如果同一个仓库里反复出现“定位到某个文件、做窄编辑、跑某个测试命令”,那么这些重复信号至少说明它不是单次偶然。这样可以得到仓库级候选技能。但仓库级候选仍然可能包含仓库特定 API 和路径,比如
BaseInlineFormSet、django/forms/models.py。再进一步,如果多个仓库都出现类似的程序模式,比如“选择当前证据支持的最窄 owner path”“保持编辑最小”“验证被改变的行为”“失败时重新定位”,那么把这些仓库特定标识符去掉,就可能得到跨仓库可迁移的程序性技能。
到这里,我又会撞上第二个问题:成功的轨迹能告诉智能体“怎么做”,但失败的轨迹怎么办?如果只聚合成功经验,智能体在遇到失败修复方向时仍然可能反复踩坑。于是需要另一条聚合路径:把失败轨迹中反复出现的失败签名,比如“定位漂移”“状态区分塌缩”“验证没有覆盖被改变行为”,聚合成恢复技能,告诉智能体什么时候该停下来、重新定位或改变策略。
第三个问题是:谁来判断一个候选技能该不该被接受?如果只靠固定 prompt 让 LLM 自己写技能,质量会不稳定。于是需要一个外部 evaluator,根据支持度、重复信号、范围、安全性来打分。但 evaluator 的权重如果固定,可能一开始就低估某些后来被证明有用的信号。所以还需要根据后续反馈更新 evaluator 权重,同时更新 writer 的构造规则。
最后还有一个工程问题:训练时更新了技能库和 writer/evaluator 策略,但部署时底层编码模型是冻结的。因此需要把“技能库”和“构造/评估策略”分开:编码智能体只拿技能库,外部控制器保留 writer/evaluator 策略,以便下一轮继续进化。
与论文实际路径的差异:我一开始倾向于直接从单条轨迹抽象通用规则,而论文从一开始就把“仓库”作为中间聚合层,并且把成功技能和恢复技能分成两条跨仓库聚合路径。另一个差异是,我可能把 writer 和 evaluator 都当作普通 LLM prompt,而论文把 evaluator 显式参数化为一个线性打分函数
s(c) = b + θ^T f(c),并固定决策阈值、只更新权重θ。这个线性可解释结构是我在重建时不会自然想到的。4. 核心 intuition
可以用“医院会诊记录如何变成诊疗指南”来类比。
单个病人的病历就像一条编码轨迹:它记录了具体症状、具体检查、具体用药和具体结果。如果医生下次遇到新病人时直接照抄上一个病人的处方,很可能出错,因为病情不同。
HSE 的做法类似:先在同一科室内部汇总多个相似病例,形成“本科室常见处理方案”;再把多个科室都反复出现的处理原则提炼成全院通用的诊疗流程,比如“先确认最窄的病灶位置,再做最小干预,干预后只验证受影响的指标,如果指标矛盾就重新定位”。同时,失败的病例也不会被扔掉,而是汇总成“常见误诊模式与纠正流程”。
这个类比能对上机制:科室对应仓库,全院通用流程对应跨仓库技能,失败病例汇总对应恢复技能。关键点是,聚合层级越高,越会丢掉具体病人和具体科室的细节,但保留的是“下一步该做什么、什么时候停、怎么验证”的程序,而不是“上次开了什么药”。
5. 方法 pipeline 举例
以论文中的
django__django-16950为例,走一遍完整流程。输入:一个 Django issue,描述是 inline form 清除了父对象上生成的 UUID,导致保存时 NOT NULL 错误。仓库快照是 Django 源码,执行环境是测试沙箱。
L1 任务证据:冻结编码智能体执行修复轨迹。轨迹中有工具调用,比如读取
django/forms/models.py中的add_fields()、运行 reproducer、运行测试、修改 patch。证据提取器ϕ把这些工具调用按五个阶段打标签:reproduce、locate、edit、validate、recover。结果摘要器ψ记录 verifier 结果,比如失败或成功。假设这条轨迹最终失败,得到一条z_i = (e_i, y_i),其中y_i = fail。L2 仓库内聚合:把同一个仓库
django/django下的多条任务记录E_r放在一起。writerπ_w发现多条记录都反复触及django/forms/models.py中的add_fields(),并且都涉及“默认值字段被清除”的信号。于是生成一个仓库条件化候选q_r,内容是:触发条件是“inline form 保存时默认值字段被清除”;证据门是“当前 traceback 指向add_fields()”;动作是“检查to_field是否为主键”;验证是“运行 model_formsets 测试”;停止条件是“如果测试失败且与当前方向矛盾,重新定位”。evaluatorπ_e根据支持度、重复信号、范围、安全性打分。假设分数超过0.62且没有强负证据,候选被接受。L3 跨仓库聚合:在多个仓库中,比如
pandas、pydantic、moto、MONAI、mypy,都出现了类似的程序模式:先定位最窄 owner,再做最小编辑,再验证受影响行为,失败时重新定位。writer 去掉django特定标识符,生成一个跨仓库程序性技能success-localize-edit-recover。evaluator 检查跨仓库支持度,比如至少 5 个仓库、11 个仓库事件、37 个 verifier 阳性任务事件,然后接受。这个技能进入技能库K_t。失败路径:如果某些失败轨迹反复出现“定位漂移”或“验证没有覆盖被改变行为”,则另一条 L3 路径把这些失败签名聚合成恢复技能,比如“当 diff 偏离症状时停止并重新定位”。
部署:冻结编码智能体只接收技能库
K_t。新任务到来时,智能体读取技能文档,按其中的证据门判断是否适用,然后执行修复。外部 writer 和 evaluator 保留更新后的策略θ_w、θ_e,用于下一轮进化。6. 核心数学推导
论文的核心可推导公式是 evaluator 的线性打分函数。原文在附录 B 中给出了较完整的形式,但正文 4.4 节和附录 B 的符号略有差异,这里按附录 B 的明确数值推导。
先解释符号:
c:一个候选技能,可以是仓库条件化候选或跨仓库候选。f(c):候选c的证据特征向量。每个分量是一个证据信号,比如正支持、任务级支持、重复信号、跨仓库支持、事件支持、强负证据、诊断信号、风险指标。θ_e:evaluator 的权重向量。每个分量表示对应证据信号对“该候选是否值得接受”的贡献。b:偏置项。附录 B 中明确写为0.35。s_{θ_e}(c):候选c的评估分数。τ_revise:修订阈值,固定为0.45。τ_accept:接受阈值,固定为0.62。打分公式为:
s_{θ_e}(c) = b + θ_e^T f(c)其中
θ_e^T f(c)是权重向量与特征向量的内积,也就是每个证据信号的值乘以对应权重后求和。附录 B 给出了初始权重。例如:
0.080.030.180.120.100.010.16-0.20-0.04-0.08举一个具体计算。假设一个失败衍生候选有:正支持、任务支持、一个重复信号、正支持达到两个任务、三个支持仓库、一个支持事件、没有强负证据。那么它的分数是:
0.35 + 0.08 + 0.03 + 0.18 + 0.12 + 3 × 0.10 + 1 × 0.01 + 0.16先算括号内:
0.08 + 0.03 + 0.18 + 0.12 = 0.41。跨仓库部分:3 × 0.10 = 0.30,加上0.01和0.16,得到0.30 + 0.01 + 0.16 = 0.47。总和是0.35 + 0.41 + 0.47 = 1.23。因为1.23 ≥ 0.62且没有强负证据,决策为接受。决策规则为:
s ≥ 0.62且没有强负证据,接受。0.45 ≤ s < 0.62,修订。权重更新公式为:
θ_{t+1,e,j} = θ_{t,e,j} + α(y) Δ_j其中
Δ_j ∈ {-1, 0, +1},表示第j个证据权重应该增加、不变还是减少。α(y)是步长,强证据用0.04,弱证据用0.02。例如,如果一个被接受的候选后来被发现与回归相关,那么当初促成接受的负信号或风险信号权重会被调低,也就是Δ_j = -1,于是θ减少0.04或0.02。这个公式在计算的是:给定候选技能的证据特征,evaluator 应该给它多高的分数,从而决定接受、修订还是拒绝。它的作用是把“技能质量评估”从一个黑箱 LLM 判断,变成一个可解释、可更新的线性打分器。
7. 实验设计
数据集:训练用 SWE-Gym 的 2,438 个任务,跨 11 个仓库。采样 500 个任务,其中 26 个来自
bokeh/bokeh作为验证集,剩余 474 个来自 10 个仓库作为训练集。验证集与训练集不共享仓库。评估用 SWE-bench Verified 的 500 个任务和 DeepSWE 的 113 个任务。基线:No Skills、
SWESkillsBench、GEPA、ReasoningBank。指标:resolved rate,即 verifier 判定成功的任务百分比。报告 Mean@3 和标准差。差异用百分点表示。
主要结果:静态 HSE 在四个 benchmark-harness 设置上都优于所有基线。相对 No Skills,SWE-bench Verified 上提升 1.9 到 4.5 个百分点,DeepSWE 上提升 5.6 到 7.7 个百分点。相对最强基线,SWE-bench Verified 上超过
SWESkillsBench0.7 到 0.9 个百分点,DeepSWE 上超过GEPA2.1 到 3.5 个百分点。目标 benchmark 适应:从冻结 HSE 技能库开始,每轮收集目标任务轨迹,用固定 writer/evaluator 更新技能库,不用 verifier 反馈。到 Gate 8,SWE-bench Verified 上 Pi 从 75.4% 升到 90.1%,CC 从 80.6% 升到 93.9%;DeepSWE 上 Pi 从 48.7% 升到 71.7%,CC 从 52.5% 升到 75.8%。
消融:移除程序性技能或恢复技能。程序性技能移除在 SWE-bench Verified 上损失更大,恢复技能移除在 DeepSWE 上损失更大。移除层级聚合或控制器更新也都有损失。
跨 harness 和跨模型:固定 HSE pack 跨 Pi 和 CC 部署,相对目标 harness 的 No Skills 提升 3.1 到 7.3 个百分点。跨模型到 GPT-5.5 和 Opus 4.8,也都有正增益。
实验能否支撑结论:实验覆盖面较广,包含两个 benchmark、两个 harness、三个模型,且有消融和适应实验。但有几个缺口。第一,跨模型评估只在 Pi 下进行,没有覆盖 CC。第二,控制器更新消融是把 writer 和 evaluator 更新机制作为一个整体移除,无法区分 writer 更新和 evaluator 更新的各自贡献。第三,目标 benchmark 适应实验在更新技能库后又用同一个完整目标任务集评估,存在潜在的数据复用问题,虽然论文声称 verifier 结果只用于报告指标、不用于反馈。第四,训练只用了 SWE-Gym 的 500 个采样任务,最终只产出 10 个技能,技能数量很少,统计稳定性存疑。
8. take-aways
9. 最脆弱的假设
最脆弱的假设是:从 SWE-Gym 轨迹中蒸馏出的程序性技能,其有效性主要来自“程序模式”本身,而不是来自训练仓库与目标 benchmark 之间未被显式控制的分布重叠或泄漏。
如果这个假设不成立,那么 HSE 的跨 benchmark 迁移增益可能部分来自 SWE-Gym 与 SWE-bench Verified、DeepSWE 之间的任务相似性,而不是技能真正学到了可泛化的修复程序。论文给出的证据是:训练集和验证集不共享仓库,且静态 HSE 技能库在训练时没有接触目标 benchmark。但论文没有系统分析 SWE-Gym 与目标 benchmark 在 issue 类型、依赖库、修复模式上的重叠程度。
另一个相关假设是:evaluator 在没有 verifier 反馈的情况下,仅凭学习到的权重就能可靠地筛选目标 benchmark 适应阶段的新候选技能。论文在目标适应实验中确实没有使用 verifier 反馈,且性能持续上升,这为假设提供了一定支持。但如果 evaluator 在目标分布上出现系统性误判,适应过程可能会把噪声技能引入库中。论文没有报告适应阶段被拒绝的候选数量或质量。
10. 一周最小复现
目标:复现“静态 HSE 技能库相对 No Skills 有正增益”这一最核心结论,不追求完整训练循环。
数据规模:从 SWE-Gym 中选 2 到 3 个仓库,每个仓库取 20 到 30 个任务,总共约 60 到 80 个任务用于技能蒸馏。评估用 SWE-bench Verified 的一个小子集,比如 50 到 100 个任务,或者用 SWE-bench Lite 的可用子集。
步骤:
预期指标:在小规模复现中,不要期待论文报告的 1.9 到 7.7 个百分点提升。合理预期是 HSE 技能库相对 No Skills 有 1 到 3 个百分点的正增益,且方差较大。如果出现负增益,优先检查技能是否过于具体、是否包含仓库特定路径。
关键简化:跳过完整的 writer/evaluator 权重更新,用固定 prompt 和人工筛选代替。跳过恢复技能,只复现程序性技能。这样一周内可以完成一轮训练和一轮评估。
11. 反例设计
设计一个实验,如果成功就能推翻“HSE 的层级聚合和跨仓库程序性技能是增益来源”这一核心主张。
实验:构造一个“伪技能库”,其技能数量、文档长度、注入格式与 HSE 完全相同,但内容是从 SWE-Gym 轨迹中随机抽取的、与修复程序无关的通用编码建议,例如“使用有意义的变量名”“保持函数简短”“优先使用列表推导式”。这些伪技能不包含任何从轨迹中学到的定位、编辑、验证或恢复程序。
判据:在相同的 SWE-bench Verified 和 DeepSWE 设置下,用相同的 GLM-5.2 和 Pi/CC harness 评估。如果伪技能库的 resolved rate 与 HSE 技能库没有显著差异,甚至优于 HSE,那么说明 HSE 的增益可能主要来自“注入了额外上下文”或“改变了智能体的行为分布”,而不是来自层级聚合出的程序性知识本身。
更严格的版本:再做一组“单层聚合”对照。把所有 SWE-Gym 轨迹直接跨仓库混合,不经过仓库内 L2 聚合,直接让同一个 writer 生成 10 个技能。如果这个单层聚合版本的性能与 HSE 三层聚合版本没有显著差异,那么论文关于“仓库作为中间聚合层必要”的主张就被削弱。论文的消融已经做了类似实验,报告了 1.2 到 3.8 个百分点的损失,但该消融是随机打乱仓库结构,不是完全去掉 L2 层。反例实验可以更干净地验证这一点。
12. 落地判断
可以用于“抢占式 GPU 自托管 27B 模型做多智能体脚手架”,但需要调整预期和成本结构。
怎么用:HSE 的技能库是纯文本,不修改模型权重,因此可以直接注入到自托管 27B 模型的 system prompt 或技能检索上下文中。最直接的用法是:先用你的多智能体脚手架在历史任务上积累轨迹,然后离线跑一次 HSE 风格的 L1 到 L3 聚合,生成 5 到 10 个程序性技能和 2 到 3 个恢复技能。之后每次新任务开始时,把这些技能作为静态上下文注入。
成本量级:论文报告 HSE 注入技能上下文约 0.5K words,而
SWESkillsBench约 1.5K words。但总上下文成本仍然很高:在 Pi 下 SWE-bench Verified 的 HSE 总词数约 385.1K,DeepSWE 约 2.8M。对于 27B 模型,这意味着每次任务的长上下文 prefill 成本会很大。如果使用抢占式 GPU,长上下文 prefill 的延迟和显存峰值是主要瓶颈。建议把技能库限制在 3 到 5 个技能,并配合一个简单的检索器,只注入与当前 issue 最相关的 1 到 2 个技能,而不是全量注入。最大的坑:HSE 的训练阶段需要大量完整轨迹和 verifier 反馈。在自托管场景中,你未必有 SWE-Gym 级别的 verifier。如果没有可靠的自动验证信号,L1 的 outcome label 和 L2/L3 的正负证据都会变得不可靠。此时 evaluator 的打分可能退化成 LLM 的自我判断,容易把“看起来合理但实际无效”的技能接受进库。另一个坑是,论文的目标适应实验在更新技能库后又用同一批任务评估,存在乐观偏差。你在自托管环境中如果也用同一批任务既更新技能又评估,会高估真实收益。