SkillZip:把技能库当成带契约的图来压缩,10 万个技能也能毫秒级检索

你有没有发现一个很拧巴的现象:Agent 的技能库越攒越大,加载技能的方式却越来越糙——要么整个包塞进去,要么把技能文本压一压,要么检索完再临时拼执行图。三个环节,三种粒度,谁也不认谁。

上周刷到这篇 SkillZip(arXiv: 2608.05604),我的第一反应是:终于有人把这个"粒度错位"问题说透了。它给出的答案也很干脆——别在文本上压缩了,把技能先切成带契约的 section 子图,在图上做可逆压缩,检索、压缩、执行围着同一个单元转。

核心摘要:LLM Agent 的过程性知识越来越多地存在可复用的技能包里,但现有系统在"检索用整包、压缩按文本、建图在检索后"三种粒度之间反复横跳,重复例程被反复加载、契约被压坏、库本身从不被优化。SkillZip 把技能统一转成 section 级的过程图,把反复出现且契约合法的子图重写成可逆宏(ported macros),配合契约校验(边界签名一致、依赖闭合、验证器可达)保证压缩后的东西还能执行、还能还原。结果相当能打:在 SkillsBench 和 ALFWorld 上比最强 baseline SkillDAG 最高提升 12.2 个点,压缩率 3.46× 的同时保持 99.2% 的依赖保留和 98.7% 的验证器可达性,技能库从 200 扩到 10 万时检索优势反而越拉越大。我的判断:这不是一个压缩技巧,是对"技能该以什么单元存在"的一次重新定义,做技能系统的人值得细读。


📖 论文信息

  • 标题:SkillZip: Contract-Preserving Graph Compression for Scalable Agent Skill Libraries
  • 作者:Xingyu Tan, Xiaoyang Wang, Qing Liu, Xiwei Xu, Xin Yuan, Liming Zhu, Wenjie Zhang
  • 发表:2026 年 8 月 6 日(arXiv v1)
  • 链接:https://arxiv.org/abs/2608.05604

🎯 问题:三个环节,三种粒度

先把场景具象化。技能库里有两个技能:Clean CSVPivot Tables。它们共享 schema inference、header 归一化、行数校验这几个例程,但下游操作和验证逻辑不同。现在来了个任务,只需要两者共享的那几节。

现有的技能系统会怎么做?技能级检索器会把两个完整的包都加载进来——明明只要几节,却塞进两份完整说明书。

作者把这个病拆成了四个挑战,说实话我觉得这个拆解比方法本身还值钱:

  • 复用粒度不匹配:progressive-disclosure 和 skill-graph 系统以整个技能为检索单元,没法只挑包里相关的那段过程。
  • 压缩不保契约:文本压缩直接优化 token 预算,但"文字相近"不等于"契约等价"。一段被压缩的技能可能措辞跟原文很像,却把前置条件、guard 分支、verifier 钩子悄悄抹掉了。这个坑我自己在做上下文压缩的时候也踩过——压缩完的指令看着挺顺,跑起来就是漏检查。
  • 压缩不持久:任务时的执行图是检索完之后才建的,库本身从来不是压缩后的持久结构。于是同样的重复例程,每个任务都要重新发现、重新验证一遍。
  • 维护无感知:一次性压缩器既认不出"后来的技能让某个例程变得可复用",也没法修一个反复触发展开、验证失败、下游返工的坏宏。

一句话总结:检索以包为单位、压缩以文本为单位、执行以图为单位——三个决策作用在三种不同的对象上。SkillZip 的主张是让它们对准同一个东西:带契约的 section 子图,让过程契约在检索、压缩、执行三个环节都活着。

图1:技能库的四类代表性工作流

图1:同一个任务"归一化表头并校验行数"下的四种工作流对比。(a) 粗粒度技能暴露:按元数据匹配后加载整包,小任务也得背全量说明书(挑战1);(b) 文本压缩:改写或摘要技能文本,保住字面意思却可能藏掉 verifier 和检查(挑战2);(c) 检索后建图:执行图只在任务时临时编译、从不持久化,库本身永远没被优化(挑战3);(d) SkillZip:section 级统一图工作流,Sec2Graph 建图、MotifZip 压缩、PathHydrate 按需水合、ReZip 增量维护,四个模块围着同一个 section 级单元转。


🧠 方法:契约保持的可逆图压缩

先给一句话直觉:把技能从"文档"变成"带接口声明的图",然后像编译器做函数内联的逆操作一样,把重复出现的合法子图提取成可调用的宏

整个框架四个模块:Sec2Graph(建图)、MotifZip(压缩)、PathHydrate(推理时水合上下文)、ReZip(增量维护)。下面挨个聊。

图2:SkillZip 框架总览

图2:SkillZip 框架全景。左上 Sec2Graph:技能包经 section 定位、九类角色标注与契约抽取,建成过程子图,跨技能兼容的 section 挂到共享原型上;左中 MotifZip:挖掘重复 motif,过四道契约校验(边界清晰、签名稳定、依赖闭合、验证器可达),按压缩增益 \(\Delta(g)\) 排序后做可逆宏重写,得到持久的压缩库和宏字典;左下 PathHydrate:任务锚定后做双层种子融合与带约束的子图搜索,宏按 name/contract/outline/source 四级水合,渲染出紧凑的执行契约交给执行器;右侧 ReZip:新技能来了匹配复用旧宏、不匹配的进残差缓冲区攒够支持度再晋升,执行痕迹回流用于宏的晋升与降级。

Sec2Graph:把技能切成带契约的 section 节点

每个 section 是一个七元组节点 \(v = \langle \tau_v, c_v, X_v, Y_v, R_v, G_v, src_v \rangle\):执行角色 \(\tau_v\)、内容 \(c_v\)、输入/输出签名 \(X_v / Y_v\)、资源依赖 \(R_v\)、guard/verifier 条件 \(G_v\)、指向原始技能源码的指针 \(src_v\)

角色一共九种:Intent、Trigger、Input、Precondition、Operation、Resource、Failure、Verifier、Output。注意这里的设计意图很明显——它把"执行要素"(前置条件、资源、失败处理、验证器)都提成了一等公民节点,而不是埋在段落文本里。这是后面一切契约校验的基础。

构建流程也顺理成章:按标题、列表、代码块、警告等边界线索分节 → 角色推断 → 契约抽取(typed I/O、资源、guards、verifier 条件)→ 建过程子图(weak-order 边、依赖边、verifier 边、repair 边)→ 跨技能复用:兼容的 section 链到共享的 canonical prototype,但 motif 的支持度按原始出现次数计。

所谓"契约",就是 \((X_v, Y_v, R_v, G_v)\) 这些字段加上 typed 边和端口,覆盖三个方面:接口(typed I/O 与资源绑定)、执行(前置条件、依赖、guards、效果、失败处理)、验证(成功条件与 verifier 钩子)。

MotifZip:可逆宏,不是有损摘要

这是全文最核心的设计。一个宏节点 \(M_g: I_g \Rightarrow O_g\) 压缩一个连通子图 \(g=(V_g, E_g)\),带边界输入 \(I_g\)、边界输出 \(O_g\) 和展开规则 \(M_g \Rightarrow (V_g, E_g, \chi_g)\)

关键在于:每个宏可以按四个层级渲染——name、contract、outline、full source。这是一个可逆重写,不是有损摘要。你可以只给 Agent 看宏的契约(几十个 token),需要细节时再展开到源码。说实话,这个设计让我想起代码里的函数声明与实现分离——声明够用时绝不读实现。

一个 motif 要被接受为宏,必须过三道契约校验:

  1. 接口稳定:input/output 端口、角色签名、资源需求在各次出现间一致;
  2. 执行闭合:依赖要么在 motif 内部,要么通过宏端口显式暴露;
  3. 验证可达:每个改变状态的操作,其 verifier 要么保留在宏契约内,要么能从宏输出到达。

第三条值得展开。验证器可达性的形式化是:对子图 \(P\) 中的操作节点 \(u\) 和 verifier 节点 \(z\),若在依赖边导出子图中存在有向路径 \(u \rightsquigarrow z\),则 \(z\)\(u\) 可达;\(P\) 中每个 state-changing 操作至少有一个可达 verifier 才算满足。你想想看,要是压缩把一个校验步骤压没了,Agent 就会在没护栏的情况下执行操作——这正是文本压缩最容易犯的错,而这里它被写进了硬约束。

选哪些 motif 做宏?用一个描述长度增益公式:

\[\Delta(g) = \text{freq}(g)\cdot L(g) - L(M_g) - L(rule_g) + \alpha\cdot\text{Reuse}(g) - \lambda\cdot\text{Cut}(g) - \mu\cdot\text{Risk}(g)\]

前两项是经典的 MDL 思路:出现频率乘以子图长度,减去宏本身和重写规则的代价。后面三项是作者的工程直觉:奖励跨技能/跨任务族复用,惩罚边界切割损失,惩罚弱 verifier 支持或模糊契约的风险。

论文还给了一个结构性保证(Proposition 1):对两两不冲突的 occurrence 集合,压缩再展开后的图与原图同构(up to auxiliary prototype links),且同构保持 typed 外部依赖和 operation-to-verifier 可达性。作者自己也坦白:这个保证是结构上的,不是语义上的。这个态度我喜欢,不吹牛。

PathHydrate:够用最少的上下文水合

推理时的问题变成:在预算 \(B\) 内,给任务 \(q\) 编译出一个可执行上下文。

任务先被锚定成 \(z_q = (g_q, O_q, \Gamma_q, I_q, D_q, \{d_i\})\)(目标、期望输出、所需能力、可见输入、执行器画像、有序子目标)。检索用双层种子融合:section 级打分取子目标与整查询相似度的最大值,skill 级用 reciprocal-rank fusion 融合两个排名。

然后是一个带约束的子图搜索:

\[P_q^\star = \arg\min\ \eta\cdot T(P) + \beta\cdot |P| + \gamma\cdot E(P) - \delta\cdot \text{Match}(P, q)\]

约束包括 anchor 覆盖、依赖闭合、验证器可达、token 预算不超 \(B\)。搜索之外还有 scaffold repair:向后回溯补 Input、Precondition、Resource,向前补 Failure、Verifier、Output;预算内实在凑不齐 verifier-reachable,就回退到覆盖 anchors 的最小技能级整包。

这里有个措辞我觉得很讲究:context filling 是"充分性门控,而不是预算追逐"这件事——不是把预算花满,而是够用就停。对每个宏选最低够用的水合层级,契约里没暴露的 input、guard、verifier 或 source 指针缺失时才展开。最终每个任务只渲染约 1941 个 token,比 top-5 整技能加载少 72.1 个点

ReZip:让压缩库跟着执行证据进化

最后一个模块解决"库会老"的问题。状态模型 \(\mathcal{Z}_t = (\mathcal{G}_{zip}^t, \mathcal{M}_t, \mathcal{B}_{res}^t, \Sigma_t)\),新技能或执行痕迹来了就做一次转移。

两条通路:

  • 新技能同化:新技能过 Sec2Graph 后,连通区域按 typed 端口和契约三方面跟现有宏匹配;匹配的复用宏并保留各自的 source map,不匹配的进残差缓冲区。当残差跨技能支持数到阈值 \(m\)、增益 \(\Delta(r) > 0\) 且通过同样的契约检查,就晋升为新宏。
  • 执行感知的宏修订:风险分数 \(\rho_t(M) = \lambda_e \cdot n_{exp}/n_{use} + \lambda_v \cdot n_{fail}/n_{use} + \lambda_d \cdot c_{repair}/n_{use}\),三项分别量宏细节不足(频繁被要求展开)、验证失败率、下游修复代价。风险超阈值先提高受影响任务画像的水合层级,持续不行就拆成更窄的契约兼容规则,或者直接退役回源 section。

等等,这个降级机制其实挺关键的——它承认了"压缩决策可能是错的",并且给了错了之后的退路。很多压缩方案缺的就是这个后悔药。


📊 实验:12.2 个点的提升从哪来

实验在 SkillsBench 和 ALFWorld 两个基准上做,backbone 用了 MiniMax-M2.7 和 gpt-5.2-codex,对比 Vanilla Skills(全量加载)、Vector Skills(embedding 检索)、GoS(Graph-of-Skills)和最强 baseline SkillDAG。

主结果

MiniMax-M2.7 下的核心数字:

方法 SkillsBench R Ret@1 Ret@5 MRR ALFWorld R Ret@1 Ret@5 MRR
Vanilla Skills 17.2 47.1
Vector Skills 10.4 3.6 10.8 5.8 50.7 37.9 68.6 49.2
GoS 18.7 50.6 65.5 57.3 54.3 56.4 86.4 67.9
SkillDAG 27.3 66.7 78.2 71.3 67.1 57.9 92.1 71.1
SkillZip 33.3 73.6 92.0 81.3 79.3 85.7 98.6 91.2

gpt-5.2-codex 下趋势一致:SkillsBench R 从 SkillDAG 的 36.8 提到 43.0(+6.2),ALFWorld 从 93.6 提到 96.4(+2.8)。

几个值得说道的点:

  • 最大提升出现在 MiniMax-M2.7 的 ALFWorld 上,比 SkillDAG 高 12.2 个点(67.1 → 79.3)。具身环境里操作链长、验证频繁,契约保持的价值被放大了,这个结果是自洽的。
  • ALFWorld 上 gpt-5.2-codex 的 GoS/SkillDAG 已经 93.6%,天花板附近还能抠出 2.8 个点,说明检索质量还在实打实地变好(Ret@1 提升 30.3 个点)。
  • Vector Skills 在 SkillsBench 上只有 3.6 的 Ret@1,惨是惨,但也说明这个基准的技能确实重叠得厉害,纯 embedding 根本分不开。
  • 效率上(MiniMax-M2.7, SkillsBench, vs SkillDAG):累计 prompt 处理量减 47.0%,平均工具调用减 21.7%,端到端任务时间减 21.1%。检索准了,Agent 就不瞎试了,链条是通的。

压缩 vs 保真:同一压缩率下的碾压

Table 2 是我觉得全文最有说服力的一张表。同样压到 3.46×,文本压缩和 SkillZip 的结构保真度完全是两个物种:

表示方式 压缩率 Token 依赖保留 验证器可达 需恢复比例 Reward
原始 section 图 1.00× 6,716 100.0 100.0 0.0 31.0
精确文本去重 1.43× 4,697 98.6 98.1 5.2 31.2
文本压缩 3.46× 1,941 65.0 60.0 45.0 25.5
通用图语法 2.91× 2,308 93.4 90.8 22.7 29.4
SkillZip w/o 校验 3.78× 1,777 88.9 84.6 31.5 27.8
SkillZip 3.46× 1,941 99.2 98.7 14.8 33.3

文本压缩(LLMLingua-2)压到同样的 token 数,依赖保留只剩 65.0、验证器可达只剩 60.0,45% 的查询得回原文恢复——这正是"文字相近不等于契约等价"的实锤。而 SkillZip 在同样的压缩率下把这两个数钉在 99.2 和 98.7,恢复需求从 45.0% 降到 14.8%,reward 反而比不压缩的原始图还高 2.3 个点。

还有个反直觉的发现:SkillZip w/o 校验那行,压缩率更高(3.78×)但 reward 掉了 5.5 个点。压得更狠反而更差——没有契约校验换来的压缩率是负资产。这个对照设计得很聪明。

顺带一提,契约抽取本身的质量是 91.6 macro-F1、84.6 exact match,在 10% 契约扰动下还能维持高 DPR/VR。抽取不完美,但系统对噪声有耐受。

消融:每个组件都在干活

Table 3(SkillsBench):

变体 R Ret@1 Token DPR VR
完整 SkillZip 33.3 73.6 1,941 99.2 98.7
w/o section 级节点 27.9 66.7 3,103
w/o MotifZip 31.0 71.8 2,967 100.0 100.0
w/o 依赖闭合 28.6 72.1 1,653 82.3 92.6
w/o 验证器约束 29.1 72.8 1,668 94.9 76.4
w/o 全局 section 补全 30.4 68.2 1,812 96.5 96.8
w/o 自适应水合 31.5 73.2 2,587 99.2 98.7

两个观察。

一个,去掉 section 级节点伤得最重:Ret@1 掉 6.9、reward 掉 5.4、渲染上下文暴涨 59.9%。粒度是一切的地基,这和论文的核心论点完全咬合。

另一个更有意思:w/o 依赖闭合时 DPR 崩到 82.3,w/o 验证器约束时 VR 崩到 76.4,但两者的 Ret@1 都还在 72 以上——检索是对的,执行还是翻车。作者那句点评我很认同:光有正确的检索,没有保执行的压缩,是不够的。

Scaling:库越大,优势越大

最后是我最看重的 scaling 分析。技能库从 200 扩到 100K:

  • SkillZip 对 SkillDAG 的 Ret@1 优势从 6.2 个点扩大到 23.3 个点——规模越大,契约化组织的复利越明显。
  • 10 万技能(对应 477 万个 section 节点)下,Ret@1 保持 65.1,在线检索加水合延迟 248.3 ms
  • 离线侧:契约就绪后,局部建图加 MotifZip 一共 178 秒;整体存储实现 3.46× 压缩和 71.0% 的活跃存储削减。

毫秒级在线延迟加分钟级离线压缩,工程上是可用的。当然,178 秒的前提是"section contracts 就绪",契约抽取那一步的成本论文没把它算进这个数里,实际落地时这块的开销值得自己测一测。


🤔 我的判断

这篇论文最值钱的地方,是把"技能压缩"这个看似工程的问题,上升到了"技能该以什么单元存在"的表示层面。Unit mismatch 这个诊断非常准——检索按包、压缩按文本、执行按图,三套粒度互相打架,是现在很多技能系统越用越臃肿的根因。SkillZip 给出的答案(带契约的 section 子图 + 可逆宏)在概念上干净,在实验上站得住,还有结构性保证兜底。

但也有几个地方我持保留态度。

说实话,9 种角色的 section 切分和契约抽取严重依赖 LLM 的抽取质量,91.6 的 macro-F1 也就是接近一成的契约字段是错的。论文用 10% 扰动实验证明系统有耐受,但真实场景里系统性抽错(比如某类技能的 verifier 总被漏标)和随机噪声是两回事,这块的鲁棒性 evidence 还不够硬。

还有,SkillsBench 和 ALFWorld 的技能都偏"结构化文档",天然好切节。真实世界里大量技能是一坨流水文本甚至代码,Sec2Graph 在那种语料上能切出什么质量的图,论文没回答。

跟同期工作比,GoS 和 SkillDAG 已经在做技能图,SkillZip 的真正增量是把"契约保持"和"可逆性"做成了硬约束和持久结构,而不是检索后的临时产物。说它是底层突破可能过了,说它是把表示、压缩、维护三件事一次性想清楚的系统性整合,不为过。而且消融里"检索对但执行翻车了"这组对照,本身就是一个对后续研究很有价值的洞见。

工程上的启发很直接:如果你在攒技能库,别等库大了再考虑组织结构——从第一天起就把技能切成带输入输出签名和验证条件的 section,把 verifier 当一等公民对待。即使不上 SkillZip 全套,光是"压缩必须过依赖闭合和验证器可达两道闸"这一条,就能避开大多数上下文压缩的坑。

更本质的问题还在后面:契约目前是人定义schema、LLM填字段。技能在真实执行中演化出的隐式契约(哪些前置条件其实没人检查、哪些输出字段其实没人消费),能不能从执行痕迹里自动学出来?ReZip 已经用执行证据修宏了,下一步用执行证据修契约,这条路看起来是通的。


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我