Loading...
正在加载...
请稍候

当 AI 学会说这不是我的锅:SkillAA 让技能图谱学会精准归因与回滚

✨步子哥 (steper) 2026年09月18日 21:03

skillaa_nopatch.svg

一个尴尬的场景

想象你是一个资深工程师,手下有个实习生叫小 G。小 G 脑子很聪明,但记不住流程细节,所以你给他写了一本"操作手册"——什么时候该查哪个数据库、什么时候该调用哪个工具、什么时候该跳过哪一步。

某天小 G 在一个问答任务上翻车了。你翻看他的执行日志,发现问题出在第三步:他该查"巴拿马法院 1993 年定罪的领导人",却答了 Manuel Noriega 而不是标准答案 Noriega。

这时候你会怎么做?

A. 把操作手册重写一遍
B. 在手册里加一条"遇到人名时用简称"
C. 修一下评分器,让它能识别别名
D. 什么都不改,因为这是评分器的问题

如果你选了 A 或 B,恭喜,你正在犯当前大多数 LLM 技能优化系统都在犯的错。

问题的根源:失败不等于"该改技能"

南京大学的 SkillAA 团队(尚子乔、葛凌越、郭兰哲)发现了一个被忽视的问题:当前所有"技能进化"系统都在用"失败 → 改技能"的单一映射,但真实场景里失败的原因五花八门——可能是技能写错了,可能是检索没找到关键证据,可能是模型视觉识别错了字符,甚至可能只是评分器太严格。

把所有失败都归因于"技能有问题",就像把所有 bug 都归因于"代码写错了"——有时候是硬件故障,有时候是数据缺失,有时候是需求文档自相矛盾。盲目改代码只会越改越坏。

SkillAA 的核心贡献,就是给"技能优化"这件事装上了一套精准归因 + 定向修复 + 闸门验证的工程化流水线。

核心设计:把技能变成"有地址的图"

SkillAA 的第一个关键决策,是把技能从一段段平铺的文本,变成一张有地址的有向图

每个节点不是一坨自然语言描述,而是被拆成三个结构化字段:

  • when_to_use:什么时候该用这个技能(触发条件)
  • how_to_use:具体怎么执行(步骤序列)
  • avoid:什么时候不该用(排除边界)

节点之间用带类型的边连接,比如 prereq(前置依赖)、enhance(增强组合)。

这个设计的好处是什么?每个可编辑的位置都有了地址。就像代码库里的 src/auth/login.py:42——当 bug 出现时,你能精确指向"就是这一行这个函数这个分支",而不是"整个登录模块重写一下"。

这就是 SkillAA 名字里 "Attribution"(归因)的真正含义:不是笼统地说"技能有问题",而是定位到具体哪个节点的哪个字段

六条归因路径:失败也有分类学

SkillAA 最有洞察力的设计,是定义了六条归因路径。当一次执行失败时,teacher 模型会对照执行记录诊断,把失败归入以下六类之一:

归因码 失败条件 授权的修改
MISSING_SKILL_FAMILY 缺少整个技能 新增节点 + 绑定边
MISSING_ACTIVATION_CUE 技能存在但没被激活 只扩展 when_to_use
HARMFUL_EXISTING_RULE 现有语义导致错误 只替换出问题的字段
MISSING_OR_INCORRECT_PROCEDURE 步骤/边界/关系缺失 补全 how_to_use 或 avoid
EXECUTION_LAPSE 图是对的,但模型没按图执行 NO_PATCH(不改图)
INSUFFICIENT_EVIDENCE 证据不足以定位 NO_PATCH(保留原图)

注意最后两行。NO_PATCH 是 SkillAA 的一等公民输出——当诊断发现"图是对的,是模型执行走样了"或者"证据不够,定位不到具体字段"时,正确做法是什么都不改

这个设计看似简单,实则深刻。当前所有技能进化系统都隐含一个假设:"失败了就该改点什么"。SkillAA 用 NO_PATCH 明确否定了这个假设——有些失败不是技能的锅,强行改图只会把好的技能改坏

两道闸门:像数据库事务一样管理技能修改

定位到该改哪里、提出了候选修改之后,SkillAA 不会直接提交。它设了两道闸门,像数据库的事务隔离机制一样层层把关。

Local Gate:局部回归测试

第一道闸门是局部级的。对于每个候选修改(或一组相互依赖的修改,称为 atomic group),SkillAA 只重跑可能受影响的用例:

  • 这个节点被哪些用例用过?(Q_use
  • 修改的源头是哪些用例?(Q_src
  • 用例记录缺失的也纳入(Q_unk

重跑后统计三个数:

  • n_fixed:原来错的现在对了
  • n_broken:原来对的现在错了
  • n_unresolved:原来错的还是错的

只有当 n_fixed > n_broken + n_unresolved 时,这个修改才被保留。否则,整个 atomic group 回滚——节点字段恢复原值,新增的节点和边一起撤销。

这就像数据库的行级约束:改了一行,先检查所有相关行的一致性,不一致就回滚。

Big Gate:epoch 级提交

第二道闸门是epoch 级的。所有通过 Local Gate 的修改合并成一个候选图 \(\tilde{G}^{(t+1)}\),在整个 update pool 上跑一遍:

  • n_corrected:原来错的现在对了
  • n_regressed:原来对的现在错了

只有 n_corrected > n_regressed 时,才提交这个候选图作为新的基准。否则,图和参考执行记录都恢复到 epoch 开始前的状态。

这就像数据库的 COMMIT:所有局部修改通过了行级约束还不够,整个事务必须让全局指标净正向才能提交。

关键实验:不是所有失败都是"图能修的"

SkillAA 在三个 benchmark 上验证:SearchQA(问答)、LiveMath(数学)、DocVQA(文档视觉问答)。用 gpt-5.6-sol 作为 student 和 teacher,三个 epoch 后:

  • SearchQA:81.5%
  • LiveMath:66.7%
  • DocVQA:91.2%

在九个 model-benchmark 组合上,SkillAA 都取得了最高点估计值。但更有意思的不是这些数字,而是两个"负面"结果。

负面结果一:ALFWorld 上改图反而变差

在 ALFWorld(一个交互式家庭任务环境)上,所有方法在 100 步内都能 100% 完成。但在 50 步的紧预算下,初始技能反而是最好的——SkillAA 改了图之后,成功率反而从 95.5% 掉到 92.5%。

这是一个反直觉但极其重要的发现:当初始技能已经足够支撑任务,剩余失败来自探索或执行时,改图不仅没用,还会帮倒忙

这就像一个已经写对的函数,你硬要"优化"它,结果引入了 bug。知道什么时候不改,和知道改什么一样重要。

负面结果二:残差错误审计

团队手动审计了六个 held-out 上的错误,发现它们需要四种完全不同的修复:

  1. 评分器问题:模型答 Manuel Noriega,标准答案 Noriega——该修评分器,不是改技能
  2. 证据缺失:检索没找到"第一任国务卿"的"第一"——该改检索,不是改技能
  3. 定理识别错误:数学定理选了相关但非等价的——该加领域知识库,不是改技能
  4. 视觉识别错误:手写日期 7/18 看成 11/18——该加 OCR 交叉验证,不是改技能

六个错误里只有一个是真正的技能缺陷(role selection),而且因为只出现一次,连这个都不够格做持久化修改——需要同类错误反复出现才能确认是系统性技能缺陷

这个残差审计是整篇论文最有工程价值的部分。它告诉我们:"答错了"不等于"技能错了"。把所有错误都塞给技能系统,就像把所有系统故障都塞给应用层——数据库慢了改应用代码,网络抖了改应用代码,硬件坏了改应用代码。

工程洞察:三件事比"改技能"更重要

综合 SkillAA 的设计和实验,有三个工程洞察值得所有做 agent 系统的人记住。

洞察一:把技能变成"有地址的空间"

从"一段技能文本"到"一张有节点字段和类型边的图",不只是表示形式的升级,而是把技能从"可读文档"变成了"可寻址的代码库"

没有地址,你只能说"这个技能有问题"。有地址,你可以说"节点 #7 的 when_to_use 字段缺了第 3 个触发条件"。前者无法做定向修复,后者可以。

这和软件工程的演进一模一样:从"改这个文件"到"改这个函数的这一行"到"改这个分支的这一个 commit"。粒度越细,修复越精确,回滚越干净。

洞察二:NO_PATCH 是一等公民

当前所有技能进化系统都在追求"改得更多、改得更好"。SkillAA 反其道而行,把"不改"提升到和"改"同等重要的地位。

这不是保守主义,而是对失败原因多样性的尊重。当失败可能来自检索、感知、推理、执行、评分器中的任何一个环节时,把所有失败都塞给技能系统,就像把所有疾病都开抗生素——不仅治不好病毒感染,还会制造超级细菌。

SkillAA 的 NO_PATCH 路径,相当于给技能系统装了一个"分诊台":先判断这个失败是不是技能能修的,不是就转诊到其他组件。

洞察三:两道闸门 = 事务化技能管理

Local Gate + Big Gate 的设计,本质上是把数据库事务管理的思路搬到了技能优化上:

  • Local Gate = 行级约束(修改不能破坏局部一致性)
  • Big Gate = 事务提交(整个 epoch 的修改必须让全局指标净正向)

这个设计解决了一个长期被忽视的问题:技能修改的副作用。改了一个技能,可能修好了 A 任务但搞坏了 B 任务——以前没人检查这个。SkillAA 的 Local Gate 专门抓这种回归。

一个更深的洞察:什么时候该改图,什么时候该换模型

论文最后提出了一个我非常喜欢的框架:graph-addressable vs capability-limited failures

  • Graph-addressable failure:技能图里某个字段或边有明确缺陷,改了就能修好
  • Capability-limited failure:技能图是对的,但模型本身能力不够(推理、感知、执行)

当 epoch 级别的修改开始反复被 Big Gate 拒绝时,这是一个停止信号——不是模型能力到顶了,而是"图能修的都修完了,剩下的得靠改模型"。

未来的系统应该交替进行:改图修 graph-addressable 的失败,改模型修 capability-limited 的失败,两者迭代推进。这就像软件迭代:先优化算法(改图),再升级硬件(改模型),循环往复。

对步子哥们的启示

如果你在做 agent 系统、在用 skill 或 prompt 管理任务流程,SkillAA 给了三个直接可用的思路:

  1. 给你的 skill 加地址:不要把 skill 写成一坨 markdown,拆成 when_to_use / how_to_use / avoid 三个字段,用图结构管理依赖关系。这样失败时你能定位到具体字段,而不是"重写整个 skill"。

  2. 设两道闸门:改 skill 之前先问"这个修改会影响哪些已通过的 case",改完之后跑一遍回归测试。全局指标净正向才提交,否则回滚。这比"改了就上线"靠谱十倍。

  3. 学会说 NO_PATCH:不是所有失败都该改 skill。先诊断失败原因——是触发条件没命中?步骤错了?还是模型本身能力不够?前两者改图,后者改模型(或换更大的模型)。把"不改"作为合法输出,能避免大量无效修改。

开源代码

论文配套代码已开源:https://github.com/Ziqiao-Shang/SkillAA

仓库包含图优化器、Gate 实现、benchmark 数据准备脚本、以及完整的 per-example 预测记录。用 gpt-5.6-sol 作为 student/teacher,三个 epoch 就能复现主表结果。终端图(SearchQA 30 节点 8 边、LiveMath 37 节点 40 边、DocVQA 20 节点 19 边)也已发布,可以直接用来做 inference-only 的消融实验。

论文信息

  • 标题:SkillAA: Attribution-Guided Skill-Graph Updating with Targeted Validation and Rollback
  • 作者:Ziqiao Shang, Lingyue Ge, Lan-Zhe Guo(南京大学)
  • arXiv:2609.20455
  • 代码:https://github.com/Ziqiao-Shang/SkillAA

个人思考:SkillAA 最让我欣赏的不是它的数字,而是它对"失败"的尊重。当前 AI 圈的技能进化系统都在追求"改得更多更快",但真正成熟的工程系统知道——知道什么时候不改,比知道改什么更难也更重要。这和软件工程里"不要为了修 bug 而引入 bug"是同一个道理。

NO_PATCH 作为一等公民输出,这个设计哲学值得所有做 agent 自进化的团队借鉴。不是所有失败都是技能的锅,承认这一点,技能系统才能真正可靠。

讨论回复

加载中...
正在加载回复...

正在加载回复...

推荐
智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

领取 2000万 Tokens 通过邀请链接注册即可获得大礼包,期待和你一起在 BigModel 上畅享卓越模型能力
登录