GraSP:给Agent的技能加上因果图,多了反而更行
你有没有碰到过这种情况——给AI Agent塞了一堆技能文档,结果它比只有两三个技能时还笨?
这不是错觉。最近好几个基准测试都显示同一个反直觉现象:2-3个聚焦技能的效果优于完整文档,4+技能反而损害表现。技能越多,Agent越容易迷失在无关操作里,或者把本该先做的步骤放到后面执行,一失败就从头再来。
腾讯最新论文 GraSP 给了一个让我觉得"对,就该这么做"的方案:别再往prompt里堆技能了,先编译一遍。
核心摘要
当前LLM Agent的技能瓶颈已从"有没有技能可用"转移到了"怎么编排这些技能"。GraSP提出了首个可执行的技能图架构——在检索和执行之间加了一个编译层,把扁平的技能列表编译成带显式因果依赖的类型化DAG。执行时逐节点验证前置/后置条件,失败时只在局部子图上修补,把重规划复杂度从O(N)降到O(d^h)。在4个基准、8个LLM骨干上的实验中,GraSP全面碾压ReAct/Reflexion/ExpeL等基线,奖励最高+19分,步骤减少最高41%。核心洞察:结构化编排比扩大技能库更重要。
论文信息
| 项目 | 内容 |
|---|---|
| 标题 | GraSP: Graph-Structured Skill Compositions for LLM Agents |
| 作者 | Tianle Xia, Lingxiang Hu, Yiding Sun, Ming Xu, Lan Xu, Siying Wang |
| 机构 | Tencent |
| 日期 | 2026年4月20日 |
| 链接 | https://arxiv.org/abs/2604.17870 |
问题:技能多了怎么反而更差?
现有的技能Agent有个根本性的结构缺陷——扁平执行。
把所有检索到的技能当扁平列表灌进prompt,LLM得自己隐式推理该先做哪个、后做哪个、哪个依赖哪个的结果。问题来了:
认知过载:10个技能的描述可能就占掉几千token,留给推理和决策的上下文预算被大幅压缩。
丢弃因果结构:技能A的输出是技能B的输入,技能C必须在A完成前置条件后才能执行——这些因果关系在扁平列表里全部丢失了。
失败代价O(N):扁平序列中第k步失败,你只能丢掉所有后续步骤从头重规划。一个20步的任务第18步出错,前面17步的进展全部作废。
说实话,这让我想到编译器——没有编译器的代码就是一堆函数定义,你可以调用它们,但没有类型检查、没有依赖分析、没有错误定位。GraSP做的事情,就是给Agent技能加一个"编译层"。
方法:四阶段流水线
图1:上半部分对比扁平执行(左)与GraSP图执行(右)——扁平链路一步失败则O(N)全部重来,图结构只需O(d^h)局部修补。下半部分是GraSP的四阶段流水线:检索→编译→验证执行→局部修复,低置信度时回退ReAct。
阶段一:记忆条件检索
纯语义检索有个经典问题:选出"主题相关但操作不适用"的技能。比如任务要加热食物,语义检索可能把所有厨房相关技能都捞出来,但真正需要的只有两三个。
GraSP的解法是双分布融合:把语义检索分布pdirp_{\mathrm{dir}}pdir和经验记忆诱导分布pmemp_{\mathrm{mem}}pmem做加权融合,选出top-M个技能。
p(s∣q,x,R)=λ pdir(s∣q,x)+(1−λ) 1Z∑j=1kρj⋅freq(s,τij)p(s \mid q, x, R) = \lambda \, p_{\mathrm{dir}}(s \mid q, x) + (1-\lambda) \, \frac{1}{Z} \sum_{j=1}^{k} \rho_j \cdot \mathrm{freq}(s, \tau_{i_j})p(s∣q,x,R)=λpdir(s∣q,x)+(1−λ)Z1j=1∑kρj⋅freq(s,τij)
λ=0.5\lambda=0.5λ=0.5,直接语义和历史经验等权。ρj\rho_jρj是记忆记录的相似度权重,让更相关的历史经验影响更大。
检索完还会算一个校准置信度,从四个特征综合:平均相似度、语义/记忆分布一致性、检索结果的明确性、对任务目标的覆盖率。置信度低的时候直接回退到ReAct,避免在不可靠的技能上浪费时间。
阶段二:DAG编译——核心创新
这是GraSP最值钱的部分。
编译出来的图G=(V,E)G=(V,E)G=(V,E)中:
- 节点:源节点vsrcv_{\mathrm{src}}vsrc+ 技能调用节点 + 汇节点vsnkv_{\mathrm{snk}}vsnk
- 边:三类有类型边
| 边类型 | 语义 | 硬/软 |
|---|---|---|
| State边 | u的效果满足v的前置条件 | 硬边 |
| Data边 | u的输出绑定为v的输入 | 硬边 |
| Order边 | 来自经验的软优先约束 | 软边 |
关键设计:DAG编译同时完成技能筛选和依赖显式化。无法通过前置-效果边连入图的技能被自动排除——这就是"少即是多"的实现机制。
编译过程是LLM提议节点 + 规则验证边的混合:LLM根据任务和经验摘要提议要执行哪些技能调用,然后系统通过匹配前置条件-效果、输入-输出、经验优先级来推断边。如果检测到环,移除低置信度的软边来破环。
每个节点还带有自己的验证器和修复预算,为下一阶段做准备。
阶段三:验证执行
拓扑遍历DAG,每个节点执行前检查前置条件、执行后检查后置条件。通过就继续下一个,失败就进入修复。
阶段四:局部修复——五类有类型算子
这是另一个关键创新。失败时不做全局重规划,而是根据失败类型选择合适的修复算子,只在失败节点的2跳邻域内操作。
| 算子 | 场景 | 例子 |
|---|---|---|
| Rebind | 技能正确但参数错 | 把microwave改为oven |
| InsertPrereq | 前置条件不满足 | 插入open-receptacle(microwave) |
| Substitute | 技能schema不合适 | 用stove-heat替换microwave-heat,但必须保持下游接口兼容 |
| Rewire | 局部依赖需调整 | 改变执行顺序或将硬边降级为软边 |
| Bypass | 当前状态已满足下游 | 跳过冗余步骤 |
补丁有界:∣ΔV∣≤3|\Delta V| \leq 3∣ΔV∣≤3,∣ΔE∣≤5|\Delta E| \leq 5∣ΔE∣≤5。修复预算耗尽则升级为全局重规划,最终还有ReAct回退兜底。
为什么局部修复比全局重规划好?看数据:前置条件失败的恢复率,局部修复84.2% vs 全局重规划61.8%,差了22.4个点。原因很直觉——全局重规划会丢掉已验证的进展,局部修复只动失败附近的部分。
与同期工作的对比
说到技能图,同月有另一篇工作Graph of Skills (GoS, arXiv:2604.05333)也在用图结构做技能检索。但两者解决的问题层次不同:
| 维度 | Graph of Skills | GraSP |
|---|---|---|
| 核心问题 | 检索阶段——从万级技能库中找到依赖完整的子集 | 编排阶段——检索到的技能怎么结构化执行和修复 |
| 图的位置 | 离线构建技能依赖图,推理时做结构检索 | 在线编译执行图,运行时做验证和修复 |
| 有类型边 | 无 | state/data/order三类 |
| 修复机制 | 无 | 五类有类型算子+有界补丁 |
| 置信度路由 | 无 | 有(结构化↔反应式切换) |
说到底,GoS解决的是"从大库里找到对的小集",GraSP解决的是"找到之后怎么编排执行和容错"。两者互补,不矛盾。
与Graph-of-Thought的区别更本质——GoT结构化的是LLM内部推理,没有环境副作用;GraSP结构化的是外部技能执行,要处理真实环境的不确定性。
实验:全面碾压
主实验
4个交互基准(ALFWorld、ScienceWorld、WebShop、InterCode)× 8个LLM骨干(DeepSeek V3.2、GPT-4.1、Claude-4-Sonnet、GLM-5、Gemini 2.5 Pro、o4 Mini、Qwen3-235B、Kimi-K2.5)。
GraSP在所有48个(model, split)单元格中均优于所有基线。
拿DeepSeek V3.2的结果看:
| 方法 | ALFWorld Seen | ALFWorld Unseen | WebShop | SciWorld | InterCode |
|---|---|---|---|---|---|
| ReAct | 66.4 | 69.4 | 31.6 | 69.9 | 72.6 |
| Reflexion | 70.1 | 73.6 | 35.3 | 72.4 | 75.8 |
| ExpeL | 67.9 | 76.1 | 29.2 | 74.9 | 74.2 |
| ReAct+Skills | 74.9 | 80.3 | 40.2 | 79.6 | 79.1 |
| GraSP | 80.6 | 83.6 | 46.2 | 84.9 | 79.6 |
GLM-5上更夸张——GraSP在ALFWorld Seen拿到96.3%,而ReAct只有65.2%,差了30多个点。
步骤效率也很可观:ScienceWorld unseen上Gemini 2.5 Pro的步骤从19.1降到11.3,减少41%。
消融实验
逐层叠加组件的效果(DeepSeek V3.2,ALFWorld Seen SR% / SciWorld reward):
| 配置 | ALF | SciW |
|---|---|---|
| ReAct(无技能) | 66.4 | 69.9 |
| 单体(所有技能,无选择) | 67.1 | 71.0 |
| ReAct + Skills(扁平) | 74.9 | 79.6 |
| + 经验记忆 | 76.5 | 81.1 |
| + DAG编译 | 78.4 | 82.7 |
| + 局部修复 | 79.7 | 84.1 |
| + 路由(完整GraSP) | 80.6 | 84.9 |
注意第一行和第二行的对比——把所有技能灌进去(67.1)比只用2-3个(74.9)还差。这就是"少即是多"。
DAG编译贡献最大(+1.9/+1.6),因为它同时过滤无关技能并显式化依赖顺序。
更关键的发现
GraSP优势随任务复杂度增长:
图2:(a) 任务越长,GraSP相比ExpeL的优势越大——短任务领先约6%,长任务领先约18%。(b) 类型化修复在所有失败类型上的恢复率都远超全局重规划,尤其是前置条件失败(84.2% vs 61.8%)。
短任务领先ExpeL约6%,长任务领先约18%。原因很清楚——长任务一步失败,扁平Agent丢掉所有下游进度,GraSP只影响局部子图。
三层容错捕获大部分失败:
图3:修复升级机制在各基准上的分布。直接成功占35-58%,局部修复解决12-25%,全局重规划+ReAct回退解决剩余大部分,最终失败仅13-18%。
最终失败率只有13-18%,说明修复层级的设计是靠谱的。
更多技能损害扁平执行,GraSP鲁棒:
图4:技能数量对奖励的影响。扁平执行在M=3时达峰(74.9%),M=8时下降约6%。GraSP在M=8时(79.4%)仍优于扁平最优(74.9%)。
扁平执行在3个技能时表现最好,8个技能时掉了6个点。而GraSP在8个技能时仍然比扁平最优还好4.5个点——DAG编译的结构过滤在起作用。
对技能质量退化更鲁棒:
图5:技能质量×开销热力图。GraSP在所有质量级别都拿到最高奖励,同时LLM调用和步骤最少。扁平方法随质量下降急剧退化,GraSP退化平缓。
技能质量从High→Low,扁平执行下降约9%,GraSP只降约5%。而且GraSP在Low质量(75.4)时仍然优于扁平执行在High质量(74.9)——这数据挺能说明问题的。
我的判断
亮点:
问题定义精准。“技能过载"不是个伪命题,是实际部署中真会碰到的问题。GraSP第一个明确指出瓶颈已从"技能可用性"转到"技能编排”,这个观察本身就是贡献。
DAG编译的思路漂亮。编译器领域积攒了几十年的智慧——类型检查、依赖分析、错误定位——GraSP把这些思想迁移到Agent技能编排上,是正道。
五类修复算子的形式化。不只是"失败了重试",而是给每种失败类型设计了专门的修复策略,且有界。这让系统的行为可预测、可调试。
实验全面。4基准×8模型×5基线,加上大量消融,数据说话,不搞选择性汇报。
问题:
DAG假设排除了循环执行。需要迭代精炼的任务(如反复测量-调整循环)在DAG框架下不好表达。论文也承认了这个局限,说可以通过DAG展开或引入循环构造来扩展,但目前没有实现。
编译阶段对LLM的依赖。DAG的节点提议和边推断都由LLM完成,这意味着编译质量取决于模型能力。如果模型提议了错误的节点或遗漏了关键依赖,后续的验证和修复都建立在有缺陷的图上。
仅在文本交互环境上验证。ALFWorld、ScienceWorld这些环境跟真实的API调用、多模态交互还有距离。
工程启发:
如果你在做Agent系统,已经碰到了技能过载的问题——Agent有几十个工具但经常选错或用错——GraSP的思路值得直接借鉴:
- 别往prompt里堆工具描述了,先编译成DAG
- 给每个技能定义前置条件和后置效果
- 失败时别从头来,只修局部
- 置信度低的时候别硬撑,回退到简单策略
这个"检索→编译→验证执行→局部修复"的流水线,跟软件工程的CI/CD有异曲同工之妙。编译器先驱Alan Perlis说过一句话:“A program is like a poem: you never write a poem, you only rewrite it.” 对Agent来说也一样——你永远不可能一次规划对,但你可以让每次修补的代价尽量小。
觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我