2026/10/6 18:13:23

LLM Agent技能库膨胀治理:SkillBrew多目标精炼实践

LLM Agent技能库膨胀治理:SkillBrew多目标精炼实践 不知道从什么时候开始我做 Agent 技能库的方式变成了“只进不出”每次任务失败就往库里塞一条新技能每个业务方提一个需求就追加一套 prompt 模板。技能库从 200 条涨到 2000 条我以为 Agent 会越来越聪明结果检索开始飘模型在多个技能之间反复犹豫连原来稳定命中的场景都开始出问题。这个痛点卡了我很久直到我刷到 EMNLP 2026 上 SkillBrew 这篇工作才意识到问题不在于“技能太少”而在于我从来没有对技能库做过真正的减法。SkillBrew 的核心思路很直白把“经验积累”从单纯的增量添加变成一种可量化的多目标精炼。它不只是删掉不用的技能而是对已有技能做合并、压缩、淘汰让整个技能库在保持覆盖率的同时降低冲突率、检索成本和维护负担。如果你也在维护 LLM Agent 的技能库、做 prompt 工程、或者被“技能越多越笨”折磨过这篇文章会把 SkillBrew 的思路拆开讲透并给出一套可以落地的实操流程。1. 拥抱“只增不减”的代价为什么技能库需要做减法1.1 技能库膨胀的源头和陷阱技能库这个概念听起来很专业其实干的就是一件很朴素的事把 Agent 做某类任务时需要用到的经验、规则、工作流沉淀成可复用的模块。在实践里一个技能通常包含触发条件、使用说明、prompt 模板、输入输出约束甚至还可以挂工具调用。它的价值在于让 Agent 不用每次从零开始推理而是直接调用已经被验证过有效的“套路”。问题出在维护方式上。大多数人跟我一样技能库的扩张完全由“新增需求”驱动。今天客服场景反馈说“用户问退款失败需要安抚”你加一条明天运营场景发现“商品比价要区分自营和非自营”你又加一条。一年下来库里积累了几千条规则谁也不敢删。因为每一条技能当初都是“某个时刻的救命稻草”删掉之后万一线上又复现后果没人担得起。这种“只增不减”的代价不是线性的而是指数级的。第一向量检索的命中率会随技能数量增加而下降因为相似技能之间的向量距离越来越近召回 top-5 时经常带出一堆无关项第二模型需要在前缀里塞进大量候选技能上下文窗口被占满推理延迟和 token 成本一起涨第三技能之间的“边界模糊”会造成规则打架同一个输入同时命中两条语义相似但约束不同的技能Agent 就懵了。1.2 从“更多技能”到“更好技能”我一度觉得技能库维护就是“做加法”做得越多系统能力越强。SkillBrew 把这个假设直接翻了过来技能的最终目标是让 Agent 在合适场景下用最少的认知成本做出正确决策。如果你有 100 条技能能覆盖 80% 的场景和 1000 条技能能覆盖 82% 的场景前者的工程价值其实更高因为那多出来的 2% 覆盖率往往是用 900 条低频、冗余、互相干扰的技能换来的。这里要区分两个概念技能数量和技能质量。SkillBrew 的多目标精炼就是主动对技能做“合并、压缩、淘汰”在覆盖率和简洁度之间寻找一个帕累托最优。它不是简单按使用频率砍掉冷门技能因为冷门不代表没用而是在多个目标下找出那些“即使删除也不影响核心收益、即使合并也不损失语义边界”的冗余项。做减法还有一个隐藏价值它逼着你把技能抽象化。只减不增的库里很多技能其实是同一个底层能力的变体比如“退款失败安抚”和“发货超时安抚”本质都是“负向事件 情绪安抚”。一旦合并成“服务异常情绪安抚”反而能提升泛化能力让 Agent 在面对没见过的新异常时也有一点应对逻辑。2. 多目标精炼的核心逻辑把减法变成可量化决策2.1 多目标打分的三个维度如果“做减法”只是拍脑袋删技能那跟直接把库清空没什么区别。SkillBrew 的关键贡献是把减法的决策过程变成可量化的多目标评估。我理解下来它有三个核心目标维度。第一个维度是覆盖度。精炼后的技能库在测试集上的成功覆盖率不能明显下降最好能通过合并带来一定的正向迁移。覆盖度不能只看“这个技能有没有被触发”而要看到具体场景下的任务成功率。比如一个技能被删了但它覆盖的 case 被另一个技能以更泛化的方式命中那覆盖度就没有损失。第二个维度是冲突度。每两个技能之间都会存在语义相似性冲突度的计算方式是找出“输入空间重叠、输出约束矛盾”的技能对。精炼后这个值应该下降。我自己的经验里很多冲突不是字面上的矛盾而是两条技能给出了不同粒度的指令比如一条说“遇到售后问题先道歉”另一条说“遇到投诉先核实订单再道歉”模型其实很难判断该听谁的。第三个维度是运行成本。这里包括向量检索的 top-k 命中率、生成阶段占用的 token 量、以及人肉维护技能库所需的时间。运行成本是一个复合指标不需要算得非常精确但要有相对变化。我通常用“精炼前总 token 数 / 精炼后总 token 数”来衡量再结合线上延迟毛估。还有两个附加维度值得带上技能的可解释性和复用频率。复用频率高的核心技能要尽量保留即使它和某个低频技能语义相近也应该优先压缩低频项而不是去动高频项。可解释性则是看技能描述是否具备“人类可读、可维护”的特征很多历史技能是当初赶工写出来的连触发条件都写得模棱两可。2.2 技能表示与“能合并”的判断要让多目标精炼落地第一步是把技能变成机器可处理的表示。SkillBrew 的做法并不复杂先把每个技能文本用 embedding 模型转成向量再做聚类同时提取技能的操作意图比如“安抚”“比价”“退款”“解释”“拒绝”等动作类别把向量相似度和意图标签一起作为聚类特征。聚类结果会告诉你哪些技能属于同一簇但同一簇不代表一定可以合并。我的经验是判断“能不能合并”要看三条硬条件第一两个技能的触发条件是否有显著重叠第二两边给出的执行步骤是否一致或有兼容关系第三合并之后是否还保留双方的核心边界。如果三个条件都满足就可以做合并。如果只满足前两个但有一条关键约束不一致那就不要合并而是考虑“压缩”其中一个冗余技能。压缩和合并是两个不同动作。合并是“把多个技能编成一个新技能”目的是减少数量压缩是“保留技能核心逻辑删掉描述性废话、冗余示例和重复约束”目的是减少 token 但不减少功能。我实际测试过一条 300 token 的技能压缩后能到 180 token效果几乎没有变化因为里面大量的“比如”“你可以参考”“特殊情况”其实都是 GPT 生成技能时填充的水话。2.3 迭代式精炼流程SkillBrew 的精炼不是“跑一次脚本然后删一批技能”这么粗暴。它更接近一个持续集成的流程先对当前技能库做全面评估生成多目标得分然后筛选出冗余候选集接着对候选集执行合并、压缩、淘汰最后用固定评估集做回归测试出了问题就回滚到上一个版本。这个过程需要保留版本水位线。我通常给技能库打 Git 标签比如skill-lib-v1.2.0每次精炼前切一个分支精炼后跑评估。评估通过就把分支合回主干失败就丢弃分支。这样做减法才有安全感因为你随时可以回到“没删之前”的状态。迭代式精炼还有个容易忽略的细节评估集需要定期补充新 case。如果你的评估集永远是老 case精炼很可能会过拟合到评估集上删掉一些“评估集里没覆盖但线上偶尔有用”的技能。我建议每个版本从线上日志里抽样 10% 的新对话由规则或人工标注后加进评估集保持评估集跟真实分布同步。3. 实操过程从技能库快照到多目标精炼落地3.1 第一步规范化技能库与生成技能卡片在做任何精炼之前我先把技能库重构成结构化条目。原始技能可能是一堆散落的 markdown 文件、prompt 片段或工具描述统一格式化后才有办法批量处理。我用的格式大致长这样id: sk-1024 name: 处理发货超时安抚 category: 售后安抚 trigger: - 用户表达不满 - 订单状态为发货超时 - 用户询问补偿方案 instructions: - 先确认订单号 - 核实超时原因 - 致歉并说明预计时长 constraints: - 不承诺具体补偿金额 - 不承认承运商责任 frequency: 0.12 success_rate: 0.86 conflict_ids: [sk-1041, sk-1099] token_size: 312字段里的frequency和success_rate是从线上日志里统计出来的conflict_ids是上一轮评估标出的冲突技能对。这些元信息是后面多目标打分的原料如果没有精炼就完全靠人工读文本效率和稳定性都很差。如果是从零开始建技能库我建议先用一段时间的 Agent 日志做候选挖掘。把日志按任务聚类提取成功的调用链把“用户目标 Agent 行为 结果”转成候选技能再用规则和人工双重筛选。这个过程不需要一次做到完美只要做到“每个候选技能都有对应的线上真实 case”即可因为后面精炼时会反复用这些 case 做验证。3.2 第二步多目标评分与候选筛选有了结构化技能卡片后就可以写一个评分脚本。下面是简化版的多目标评分逻辑只保留最核心的覆盖度、冲突度和成本三个维度。def score_skill(skill, eval_set, conflict_map, cost_weight0.2): coverage estimate_coverage(skill, eval_set) # 0~1命中且成功概率 conflict 1 - len(conflict_map.get(skill[id], [])) / max_conflict # 惩罚冲突 cost 1 / max(skill[token_size], 1) # token 越小越好 total 0.5 * coverage 0.3 * conflict cost_weight * cost return total筛选时的具体参数我会用“候选比例”和“功能重叠阈值”两层控制。比如聚类后某个簇里有 20 条技能如果两两相似度中位数超过 0.82我会把该簇标为“高冗余候选簇”在这个簇里只有被触发频率低于 0.05 且成功率低于均值 10% 的技能才会进入淘汰名单。举个实际数字。我上一个项目里技能库有 2143 条聚类后得到 126 个功能簇其中 38 个簇的相似度中位数超过 0.8。在这些簇里筛出了 412 条低分技能合并后生成 83 条新技能压缩掉 156 条冗余文本最终精炼目标是缩减到约 1428 条。这个过程不是一次做完而是分了五轮每轮只处理 60~80 条候选避免一次改动太大无法定位问题。3.3 第三步精炼动作与人工确认自动评分只解决“哪些技能值得处理”真正执行合并和淘汰时我建议保留人工确认环节。SkillBrew 本身没有规定必须全自动它的价值在于把候选集缩小到一个人类可以逐条审查的程度。让一个人把 2000 条技能全部读一遍不现实但让人看 60 条合并建议是可行的。合并动作有一个重要的实操技巧不要只做文本拼接。直接把两条技能的 prompt 模板拼在一起得到的是一个又臭又长的新技能token 没省多少语义边界反而糊了。我尝试过的有效做法是先让 LLM 基于两条技能各自的核心逻辑生成一个抽象版本再由人工删掉其中“过于具体”的例子和“重复的约束”最后人工确认抽象版本是否覆盖了两边的主要 case。对于删除动作我的原则是“先归档不删除”。被淘汰的技能不是丢进回收站而是移入一个archive/目录保留完整元数据和历史评估记录。这样即使三个月后某个场景突然复活还能快速找回旧技能不用重写。4. 常见问题与排查技巧实录做技能库精炼最怕的不是“效果没提升”而是“改动之后出了问题但你不知道是哪里出的问题”。我把实际操作中遇到的典型坑整理成了一张表方便你按症状排查。症状可能原因排查思路解决参考合并后技能覆盖率下降合并时丢失了某一方的边界条件用 case 对比合并前后命中情况找出丢失的子场景把丢失的边界条件重新作为 if 分支写进新技能冲突率不降反升聚类阈值太低把不该合并的强约束技能强行合并查看合并技能的冲突报告回滚冲突 pair收紧合并阈值只合并约束方向一致的技能检索召回变差新技能文本过长或中心向量偏移检查新技能 embedding 与代表 case 的相似度用代表 case 重建技能描述尽量控制在 200 token 内精炼后线上效果波动评估集却很稳定评估集和线上分布不一致从新日志补充 hard case 到评估集建立线上抽样的持续回归集prompt token 没减少多少压缩时只删了水话没删冗余示例统计技能中“示例/约束/指令”各自占比将重复示例改为引用固定 case 编号低频但关键技能被误删评分只看频率忽视了罕见场景价值给罕见场景技能加重要性权重评分函数里增加“场景关键度”维度第一个问题最值得展开。有一次我把“退款失败安抚”和“退款延迟安抚”合并成“退款异常安抚”直觉上很合理但合并后“退款失败”场景的覆盖率从 0.79 掉到 0.61。原因是我在抽象新技能时把“失败”这个词理解得太宽导致技能在引导用户重新支付时给出了一些不适合“延迟但会到账”场景的建议。人类很容易在抽象时丢失精确性机器更难把握这种微妙边界。后来我在合并模板里加了强制步骤生成抽象版本后逐条对照两个原始技能的约束项只要有一项不一致就把这一项显式写进新技能的constraints里。第二个问题也很常见。很多人以为冲突率会随着技能数量减少而自动下降实际上如果合并得不好一条新技能可能同时继承了双方的触发条件反而跟第三条技能发生新的冲突。我现在的做法是每轮精炼后重新计算全局冲突图而不是只看被合并的那几对技能冲突图的构建成本不高但能避免“按下葫芦浮起瓢”。关于评估集过拟合我想额外强调一点技能库精炼最大的风险不是删除错误而是评估集失真。如果你的测试集是三个月前固定的那么任何一次精炼都可能过度适配这个测试集。我现在每个版本自动抽取最近 7 天的线上日志进行去隐私处理后人工抽样 500 条覆盖新增场景保证“评估集永远比线上慢半拍而不是慢半年”。5. 一些实操心得和后续扩展我自己的经验是精炼节奏比精炼幅度更重要。不要想着一次把技能库从 2000 条砍到 500 条那是大扫除不是精炼。SkillBrew 理念里真正可复制的是“持续小步做减法”的思路每轮只删 5%~15% 的冗余项跑完一轮评估稳定后再继续下一轮。这样做的好处是每次改动的因果链都相对清晰出了性能波动能很快定位到具体某一批技能改动如果一次性大砍问题混在一起根本没法排查。在跑技能库精炼之前一定要先建立版本水位线和回滚机制。我见过不少团队连 Git 都没给技能库建仓直接用线上配置文件覆盖一次精炼错了就要从历史备份里翻文本。技能库本质上跟代码一样是应该被严格版本管理的资产。我的习惯是每次精炼前生成一个快照并把评估报告一起入库这样就算回滚也能知道上个版本为什么是那个样子。后续扩展我觉得有两个方向很有意思。一个是把精炼做成运行时的钩子当 Agent 在线上重复遇到“同一条技能被高频触发但失败率上升”时自动给这条技能打上“待精炼”标记积累到一定数量后进入下一轮精炼。另一个方向是把个人经验里的 hard case 直接转成技能库的“反向约束”让技能库不仅能做加法减法还能对冲突情况做显式禁止相当于把容易出错的边界直接写死。最后分享一个小技巧在做多目标精炼的评分阶段不要把“模型效果”当作唯一目标可以把“人类维护这种技能库的负担”也当成一个隐性指标。我在实际操作中的体会是精简后的技能库不仅线上效果更稳日常维护也轻松得多因为你在阅读 1500 条技能时比阅读 3000 条技能时更容易发现那些真正值得修改的细节。这个收益没法写到论文里但对我来说才是 SkillBrew 这套思路最实在的价值。