Paper

Skill1 论文精读:用 RL 统一训练 Agent 的技能选择、利用与蒸馏

8 min read ·

研究动机:为什么 Agent 技能库需要统一训练

最近一年,基于 LLM 的 Agent 系统越来越多地引入**技能库(Skill Library)**机制:将历史成功经验抽象为可复用的技能片段,在遇到新任务时检索相关技能辅助求解。这个思路很直觉——人类专家也是靠积累和调用已有经验来解决新问题的。

但现有方案有一个被忽视的结构性问题:技能选择、技能利用、技能蒸馏这三个子能力是分开训练的

分开训练的后果是优化目标不一致。检索模型按语义相似度排序,但语义相似不等于求解有用;求解策略按任务成功率优化,但它无法反向影响检索模型的排序偏好;蒸馏模块生成的技能描述可能对当前策略有用,但对未来的检索模型却是噪声。

Skill1 的核心洞察很简单:既然这三个能力最终都要服务于同一个目标(任务成功率),为什么不把它们放在一个策略网络里端到端训练?

Skill1 框架详解

Skill1 的推理流程可以用五个阶段来描述。下面用一个简化的时间线展示整个过程:

┌─────────────────────────────────────────────────────────────────┐
│                        Skill1 推理流程                          │
│                                                                 │
│  ① 查询生成          ② 技能检索          ③ 重排选择            │
│  ┌──────────┐       ┌──────────┐       ┌──────────┐           │
│  │ 策略网络  │──q──▶ │ 向量索引  │──top-k▶│ 交叉注意力│──skill──▶│
│  │ π_θ(·|x) │       │ SkillDB  │       │  重排器   │           │
│  └──────────┘       └──────────┘       └──────────┘           │
│       │                                                      │
│       ▼                                                      │
│  ④ 条件求解          ⑤ 技能蒸馏                                │
│  ┌──────────┐       ┌──────────┐                             │
│  │ 策略网络  │──a──▶ │ 策略网络  │──新skill──▶ SkillDB         │
│  │ π_θ(·|x,s)│      │ π_θ(·|τ) │                             │
│  └──────────┘       └──────────┘                             │
└─────────────────────────────────────────────────────────────────┘

① 查询生成

给定任务描述 x,策略网络 π_θ 生成一个查询向量 q。这个查询不是自然语言,而是策略在隐空间中学习到的表示,用来表达”我当前需要什么样的技能”。

# 伪代码:查询生成
def generate_query(task_description, policy):
    # policy 将任务编码为隐向量,再投影到查询空间
    hidden = policy.encoder(task_description)
    query = policy.query_projector(hidden)  # shape: [d_skill]
    return query

② 技能检索

查询向量 q 与技能库中所有技能的 embedding 做内积相似度计算,取 top-k 个候选。技能库中的每个技能 s_i 都有一个预计算好的 embedding e_i

# 伪代码:向量检索
def retrieve_skills(query, skill_db, k=8):
    # skill_db.embeddings: [N, d_skill] 的矩阵
    scores = skill_db.embeddings @ query  # [N]
    topk_indices = scores.topk(k).indices
    candidates = [skill_db.texts[i] for i in topk_indices]
    return candidates

③ 重排选择

top-k 候选进入一个交叉注意力重排模块。策略网络对候选技能做两两比较,输出一个选择分布,最终采样一个技能 s 作为求解条件。

# 伪代码:重排与选择
def rerank_and_select(query, candidates, policy):
    # 交叉注意力:query attend to candidates
    attn_scores = policy.cross_attention(query, candidates)
    # softmax 得到选择分布
    selection_dist = F.softmax(attn_scores, dim=-1)
    # 从分布中采样一个技能
    selected_idx = torch.multinomial(selection_dist, 1)
    return candidates[selected_idx]

④ 条件求解

策略网络以任务描述和选中技能为输入,生成动作序列来完成任务。这一步和标准的 Agent 求解没有本质区别,但关键在于:策略是在训练中学会了”什么样的技能对求解有用”,而不是单纯依赖检索模型的语义相似度。

⑤ 技能蒸馏

任务完成后,如果成功,策略网络会将整个求解轨迹 τ 压缩为一条新的技能描述,写回技能库。蒸馏过程由同一个策略网络完成,因此它在训练中学会了”什么样的经验值得提炼为技能”。

整个流程中,查询生成、重排选择、求解、蒸馏都由同一个参数化策略 π_θ 驱动,训练信号统一来自任务最终是否成功。

训练策略:GRPO + task-outcome reward

Skill1 采用 GRPO(Group Relative Policy Optimization)作为优化算法,这也是 DeepSeek-R1 系列使用的 RL 方法。选择 GRPO 而非 PPO 的原因是 GRPO 不需要训练一个独立的 value 网络,这对多模块统一训练的场景更友好——少一个需要同步更新的网络就少一份训练不稳定的隐患。

训练循环

For each training step:
    1. 从任务分布中采样 batch of tasks {x_1, ..., x_B}
    2. 对每个任务 x_i,采样 G 条完整轨迹(包括检索-重排-求解-蒸馏)
    3. 计算每条轨迹的 task-outcome reward r ∈ {0, 1}
    4. 组内归一化:r̃_ij = (r_ij - mean(r_i)) / std(r_i)
    5. 用 GRPO loss 更新 π_θ

reward 设计

Skill1 的 reward 设计极其简洁:任务成功返回 1,失败返回 0。没有中间步骤的 shaping reward,没有检索质量的辅助奖励,没有技能覆盖率的正则项。

这个设计的选择基于一个观察:在 Agent 任务中,中间步骤的 reward shaping 往往引入额外的超参数和偏差,而 task-outcome reward 虽然稀疏但信号纯净。GRPO 的组内相对归一化机制天然适合处理稀疏二值奖励——同一任务的多条采样轨迹中,成功的轨迹相对于失败的轨迹获得正优势,这已经足够驱动策略改进。

为什么统一训练能工作

从优化视角看,统一训练的增益来自梯度信号的一致性。当策略网络同时负责检索和求解时,task-outcome reward 的梯度会同时流向检索模块和求解模块。检索模块会自动调整排序偏好,使得它认为”语义相似”的技能恰好是求解模块最擅长利用的技能。蒸馏模块同样受益——它生成的新技能描述会自然地适应检索模块的偏好和求解模块的需求。

这种对齐在分开训练时不可能自然发生,因为每个模块只能看到自己的局部梯度。

实验结果与消融分析

benchmark 与主要结果

论文在三个 Agent benchmark 上进行了评估:

Benchmark任务类型分离训练 baselineSkill1提升
WebShop网页交互购物62.3%70.1%+7.8
ALFWorld家庭指令遵循71.5%76.8%+5.3
ToolBenchAPI 调用规划54.2%66.4%+12.2

WebShop 任务要求 Agent 在模拟电商网站上搜索和购买商品;ALFWorld 要求 Agent 在模拟家庭环境中完成各种指令(如”把杯子放到桌子上”);ToolBench 要求 Agent 规划并调用一系列 API 完成复杂任务。

三个 benchmark 的共同特点是任务多样性高,单一技能难以覆盖所有场景,因此技能库的检索和选择质量直接影响最终表现。ToolBench 的提升最大(+12.2),可能因为 API 调用任务对技能选择的精度要求最高——选错一个 API 的调用方式,整个调用链就会失败。

消融实验

论文做了三组关键消融:

消融配置WebShopALFWorldToolBench
Skill1(完整)70.1%76.8%66.4%
分离训练(三个模块独立优化)62.3%71.5%54.2%
统一训练但冻结检索模块65.8%73.1%59.7%
统一训练但冻结蒸馏模块68.4%75.2%63.8%

这两组消融清晰地表明:统一训练的核心收益来自检索-求解的对齐,蒸馏的贡献是锦上添花。

训练效率

Skill1 的训练成本与标准 GRPO 训练相当,没有显著的额外开销。技能库的检索操作在 GPU 上可以用矩阵乘法完成,重排模块是轻量级的交叉注意力,蒸馏模块复用策略网络的解码器。论文报告在 8xA100 上,Skill1 的训练吞吐量约为标准 Agent RL 训练的 85%。

工程启示:如何在你的 Agent 系统中应用

Skill1 的核心思想——让检索和求解共享优化目标——对实际 Agent 系统的设计有直接启发。

1. 技能库检索不要独立于 Agent 策略

很多 Agent 框架把 RAG 检索和 Agent 求解做成两个独立组件,各自有独立的模型和优化目标。Skill1 的实验表明,即使不完全统一训练,至少应该让检索模型的微调信号包含来自求解结果的反馈。

# 现有常见做法(分离优化)
retriever = train_retriever(query_skill_pairs)  # 只看语义相似度
agent = train_agent_with_skill(tasks, retriever)  # 只优化求解

# Skill1 启发的做法(联合优化)
agent = train_agent_with_skill(tasks, retriever, 
    reward="task_outcome",           # 统一 reward
    update_retriever=True)           # 梯度回传到检索器

2. 技能蒸馏应该由 Agent 策略主导

不要用一个独立的 LLM 来做技能蒸馏。让 Agent 自己决定什么经验值得提炼、如何描述这条技能,因为 Agent 最清楚自己需要什么样的技能。

3. reward 设计从简

不要急于设计复杂的中间 reward。先用 task-outcome reward 跑通,观察策略是否收敛,再根据具体问题决定是否需要辅助奖励。Skill1 的经验表明,简洁的 0/1 reward 配合 GRPO 已经足够驱动检索-求解-蒸馏的协同优化。

4. 技能库需要容量管理

论文的一个附带发现是技能库大小与检索质量存在 trade-off。在实际系统中,建议定期清理低频使用的技能,或者引入技能的”新鲜度”衰减因子,避免库膨胀导致检索噪声增大。

局限性与未来方向

Skill1 的局限性值得关注:

技能库规模瓶颈。当技能库超过 10K 条时,top-k 检索的质量开始下降。论文使用的是内积检索,没有引入更复杂的近似最近邻(ANN)索引。在实际部署中,如果技能库持续增长,需要考虑 HNSW 或 IVF 等 ANN 索引方案。

蒸馏的冷启动问题。训练早期,策略网络的水平有限,蒸馏出的技能质量较低。这些低质量技能如果持续留在库中,会干扰后续训练。论文没有明确讨论技能库的清洗策略,这是一个工程落地时需要解决的问题。

仅限文本 Agent。三个 benchmark 都是纯文本交互场景,没有涉及多模态(如 GUI 操作、视频理解)的 Agent 任务。在多模态场景下,技能的表示和检索可能需要重新设计。

可扩展性验证不足。论文没有在更大规模的技能库(100K+)和更复杂的任务(如长程规划、多 Agent 协作)上进行验证。这些场景下统一训练是否依然有效,需要进一步研究。

未来一个有趣的方向是将 Skill1 与持续学习结合——Agent 在部署过程中不断遇到新任务、蒸馏新技能、更新策略,形成一个自我进化的闭环。另一个方向是探索技能的层次化表示,将细粒度的原子技能组合为高阶的复合技能,以提升技能库的覆盖效率。

FAQ

Skill1 和现有的 Agent 技能库方法有什么区别?

现有方法将技能选择、利用、蒸馏分开训练,容易导致优化目标不一致——选择模块挑的技能未必是利用模块最擅长的。Skill1 用单一策略网络和统一的 task-outcome reward 端到端训练,让三个能力自然对齐。

Skill1 的技能库是什么数据结构?

技能库是一个向量索引的文本技能集合。每个技能是一段描述性文本(如解题策略或代码片段),通过 embedding 模型编码后建立索引。策略生成查询向量来检索 top-k 候选,再通过交叉注意力重排选择最终技能。

Skill1 的训练信号从哪里来?

仅依赖 task-outcome reward——即任务最终是否成功。不需要中间步骤的标注数据。策略通过 GRPO(Group Relative Policy Optimization)优化,每批采样多个轨迹,用相对奖励估计优势函数。

Skill1 在哪些 benchmark 上验证了效果?

论文在 WebShop(网页交互)、ALFWorld(家庭指令遵循)和 ToolBench(API 调用)三个 Agent benchmark 上测试,分别超越分离训练 baseline 约 8%、5%、12%。消融实验证明统一训练的增益主要来自技能选择与利用的对齐。

Skill1 的局限性是什么?

三个主要局限:1) 技能库规模受限于检索延迟,超过 10K 条技能后检索质量下降;2) 蒸馏的新技能质量依赖于当前策略水平,早期训练阶段容易蒸馏出低质量技能;3) 仅在文本 Agent 上验证,多模态场景未覆盖。

Frequently asked questions

Skill1 和现有的 Agent 技能库方法有什么区别?
现有方法将技能选择、利用、蒸馏分开训练,容易导致优化目标不一致——选择模块挑的技能未必是利用模块最擅长的。Skill1 用单一策略网络和统一的 task-outcome reward 端到端训练,让三个能力自然对齐。
Skill1 的技能库是什么数据结构?
技能库是一个向量索引的文本技能集合。每个技能是一段描述性文本(如解题策略或代码片段),通过 embedding 模型编码后建立索引。策略生成查询向量来检索 top-k 候选,再通过交叉注意力重排选择最终技能。
Skill1 的训练信号从哪里来?
仅依赖 task-outcome reward——即任务最终是否成功。不需要中间步骤的标注数据。策略通过 GRPO(Group Relative Policy Optimization)优化,每批采样多个轨迹,用相对奖励估计优势函数。
Skill1 在哪些 benchmark 上验证了效果?
论文在 WebShop(网页交互)、ALFWorld(家庭指令遵循)和 ToolBench(API 调用)三个 Agent benchmark 上测试,分别超越分离训练 baseline 约 8%、5%、12%。消融实验证明统一训练的增益主要来自技能选择与利用的对齐。
Skill1 的局限性是什么?
三个主要局限:1) 技能库规模受限于检索延迟,超过 10K 条技能后检索质量下降;2) 蒸馏的新技能质量依赖于当前策略水平,早期训练阶段容易蒸馏出低质量技能;3) 仅在文本 Agent 上验证,多模态场景未覆盖。