不会还有人修完解析失败就散会吧?两周后变种又复发 | 从失败提炼 Skill

发布时间:2026/10/30 2:20:12
不会还有人修完解析失败就散会吧?两周后变种又复发 | 从失败提炼 Skill

上一篇:不会还有人指望模型自己猜该用哪个 Skill 吧?猜不准就别谈复用 | Commands 与 Manifest

不会还有人修完解析失败就散会吧?两周后变种又复发 | 从失败提炼 Skill

系列:《从 Rule 到落地:AI 工程化实践》第 9 篇
标签:Skill · 实战 · 知识提炼 · 排障
专栏:从小白到AI落地大师

序言

目录会搭、路由会挂,还差最硬的一跃:把一次真实失败提炼成可复用 Skill。童鞋们最容易在「修好了」的兴奋里散会,两周后变种输入一来,集体失忆。本篇完整走一遍事故到 Skill:记录、抽象、补样例、挂路由、验收。场景虚构为适配引擎解析失败。

说句自嘲的:我复盘过自己——同一类转义问题,间隔三周踩两次,第二次还在群里说「这不是上次那个吗」。是,但上次停在聊天里。聊天不是组织记忆。

记住一句话:散会口号从「下次注意」换成「草稿谁提交」——提交进仓才叫提炼,留在聊天叫表演。

概念

本篇的 Skill,由可重复失败抽象而来的 SOP,不是灵光一闪的备忘。Fixture,正反例样例,用来验收 Skill 是否仍有效。蒸馏,从嘈杂过程留下可复用步骤与断言。Lesson,若尚未晋升为 Skill,可先落成教训条目,别逼一切马上成册。

可以理解为:提炼像滤咖啡。豆子(现场)要有,滤纸(画布)要有,滤出来的才是能端给别人的一杯;把整锅渣端上去,不叫分享,叫甩锅。

问题在哪

不提炼的代价很具体。

复发变种。修了 A 输入,B 输入同构再爆。没有正反例,回归挡不住。你以为个案结束,实际只是随机数变了。

步骤带环境噪声。临时主机名、个人口令、偶发网络抖动写死进手册。换环境全假,新人照着做会更慌。

只写症状不写验收。手册教你怎么改,不教你怎么证明改对了。于是「我觉得好了」再次上场——开篇批评过的验收方式,换皮回归。

举例

故事开场(脱敏):某次解析失败,日志指向转义规则遗漏;修复后两周又在变种输入上复发。于是逼自己坐下来填提炼画布五格:症状、根因假设、固定步骤、可变参数、验收断言。

| 格 | 内容 | | 症状 | 引擎X报 unexpected token 在转义段 | | 根因 | 映射表未覆盖某种引号嵌套 | | 步骤 | 归类→最小复现→改映射→补正反例→回归 | | 参数 | log_path, engine_id | | 断言 | 旧红样转绿;邻近样例不回归 |

从聊天记录到 SKILL.md:删掉情绪与无关分支,留下可重复动作。补 references:错误分类表。补 templates:排障报告头,含错误分类、最小复现输入(脱敏)、映射变更摘要、新增样例路径、回归结果。挂 command,用历史日志跑一遍「按 Skill 执行」是否更稳。

「填画布 + 剔噪声 + 判晋升」也能机器化,四步:

步骤总览

  1. 五格画布逐格查空——根因留白 = 还没想清楚,别急着成册;
  2. 断言格必须同时覆盖「旧红转绿」和「邻近不回归」,只有前者就标假绿风险;
  3. 现场原话跑黑名单:主机名 / 密钥 / 「应该吧 / 偶发」这类情绪词一律剔除,只留脱敏后的可复用动作;
  4. 按 fault_signature 的同类命中次数判:>=3 升 skill_candidate,否则只落 lesson。
# distill.py —— 从失败提炼 Skill:画布齐不齐、噪声剔没剔、够不够格晋升# 纯标准库,复制即跑。用法:python distill.pyimportre# 五格提炼画布:一格都不能空CELLS=["症状","根因","步骤","参数","断言"]# 黑名单:现场噪声 / 密钥,能进 references 也不能写死进 SKILL 步骤NOISE=re.compile(r"(sk-[A-Za-z0-9\-]{4,}|"r"db-prod-\d+|"r"密码\s*[:=]\s*\S+|"r"临时|偶发|网络抖动|应该吧|可能差不多)")# 晋升门槛:同签名命中 >=3 才升 Skill,否则只落 lesson(挡「一次成功就写圣经」)PROMOTE_HITS=3CANDIDATES=[dict(sig="adaptor-QuoteEscape-assert",hits=3,canvas={"症状":"引擎X报 unexpected token 在转义段","根因":"映射表未覆盖引号嵌套","步骤":"归类→最小复现→改映射→补正反例→回归","参数":"log_path, engine_id","断言":"旧红样转绿;邻近样例不回归"},raw="在 db-prod-7 上试的,口令 sk-live-9f3a2b,偶发网络抖动可能是主因"),dict(sig="adaptor-NullField-assert",hits=1,canvas={"症状":"字段为空时解析崩","根因":"",# 故意空:画布缺格"步骤":"加空值兜底","参数":"log_path","断言":"旧红样转绿"},# 故意只半句:假绿风险raw="应该吧,可能就是临时空值,改完本地没红"),]defcheck_canvas(canvas):miss=[cforcinCELLSifnotcanvas.get(c,"").strip()]risk=[]a=canvas.get("断言","")if"旧红"inaand"不回归"notinaand"邻近"notina:risk.append("断言只保证「旧红转绿」,没保证「邻近不回归」——假绿风险还在")returnmiss,riskdefstrip_noise(raw):hits=NOISE.findall(raw)cleaned=NOISE.sub("<脱敏/删噪声>",raw)returnhits,cleaneddefmain():forcandinCANDIDATES:print(f"== fault_signature:{cand['sig']}同类命中:{cand['hits']}次 ==")miss,risk=check_canvas(cand["canvas"])print(f" 画布缺格:{missifmisselse'无'}")forrinrisk:print(f" [假绿风险]{r}")hits,cleaned=strip_noise(cand["raw"])print(f" 噪声/密钥剔除:{hitsifhitselse'无'}")print(f" 剔后(可入 references):{cleaned}")ifmiss:verdict="打回:画布不齐,先补格"elifrisk:verdict="打回:断言不完整,补「邻近不回归」再谈"elifcand["hits"]>=PROMOTE_HITS:verdict=f"晋升 skill_candidate(命中{cand['hits']}>={PROMOTE_HITS})"else:verdict=f"仅落 lesson(命中{cand['hits']}<{PROMOTE_HITS},别急着写圣经)"print(f" 结论:{verdict}\n")print("== 一句话 ==")print(" 复发或跨人复述成本高,才是升 Skill 的信号;一次成功先留 lesson。")if__name__=="__main__":main()

跑起来长这样:

== fault_signature: adaptor-QuoteEscape-assert 同类命中:3 次 == 画布缺格:无 噪声/密钥剔除:['db-prod-7', 'sk-live-9f3a2b', '偶发', '网络抖动'] 剔后(可入 references):在 <脱敏/删噪声> 上试的,口令 <脱敏/删噪声>,<脱敏/删噪声><脱敏/删噪声>可能是主因 结论:晋升 skill_candidate(命中 3 >= 3) == fault_signature: adaptor-NullField-assert 同类命中:1 次 == 画布缺格:['根因'] [假绿风险] 断言只保证「旧红转绿」,没保证「邻近不回归」——假绿风险还在 噪声/密钥剔除:['应该吧', '临时'] 剔后(可入 references):<脱敏/删噪声>,可能就是<脱敏/删噪声>空值,改完本地没红 结论:打回:画布不齐,先补格 == 一句话 == 复发或跨人复述成本高,才是升 Skill 的信号;一次成功先留 lesson。

输出你看什么

  1. 第一条够格晋升,但别漏看它同时剔了 4 项噪声——db-prod-7、sk-live-9f3a2b、偶发、网络抖动:能升 Skill 的前提,恰恰是把这些从步骤里摘干净,只留「归类→最小复现→改映射→补正反例→回归」这条可重复动作;
  2. 第二条两道刹车一起响:根因留白(还没想清楚就写成圣经)+ 断言只有「旧红转绿」半句(上文说的假绿风险)——画布不齐先打回,压根轮不到看它的命中次数;
  3. sk-live-9f3a2b这个口令和第 2 篇判层练习里那条是同一串——它在 Skill 里被剔、在分层里被判「该走凭据注入」,两个坑串成一条线;
  4. 命中次数 3 才升、1 只落 lesson,正是下篇 lesson 闭环里PROMOTE_HITS=3那个门槛的来历——晋升认的是「复发 / 跨人」信号,不是「这次侥幸改对了」。

什么不要沉淀:临时主机名、个人口令、偶发网络抖动——可写排查分支,不写死环境。蒸馏的黑名单意识,后面记忆层篇还会再锤。先在 Skill 提炼里练会手。

自检

# 提炼自检 - [ ] 是否用五格画布抽象,而不是粘贴聊天? - [ ] 是否补了正反例 Fixture? - [ ] 是否有报告模板? - [ ] 是否挂了 command 并用历史日志演练? - [ ] 是否剔除了环境噪声与密钥?

两问。第一,两周后变种再来,Skill 是否仍指导第一步做什么?若还得找原作者聊天,提炼失败。第二,验收断言能否同时保证「旧红转绿」和「邻近不回归」?只有前者,假绿风险还在。

提炼时请无情删除形容词和情绪句。它们在复盘会上有用,在 SOP 里是噪声。SOP 要的是下一步做什么、做到什么算完。

若失败尚不可重复,先落 lesson 再观察;强行升 Skill 会制造伪手册。伪手册比没有手册更害人,因为它给人「已沉淀」的错觉。

还有一条职责边界要说清:教训由在场的人(或宿主模型)撰写,工具只提供脚手架。teach 式的入口能帮你把失败现场落成草稿模板,但它不能替你总结「这个坑的正确处置」——那需要当时的上下文与判断。一旦让机器代笔教训,召回时端上来的就是似是而非的猜测;谁有推理能力谁动笔,谁有存储能力谁保管,各管各的。

提炼 Skill 的现场感通常是这样:修完解析失败大家准备散会,有人随口说「下次注意点」。两周后变种日志又来,于是你把当次步骤写成 SKILL 草稿:输入是日志路径,步骤是定位字段 → 对照映射 → 出最小补丁 → 跑回归,反例是「只改提示词不改映射」。下次同签名故障,command 一命中就走手册,而不是靠谁还在群里。

若故障只出现一次,先留 lesson,别急着升 Skill。升维的信号是复发或跨人复述成本高。

提炼当日建议留三份材料:原始失败日志片段(脱敏)、你实际敲过的命令、最终有效的最小 diff。三者进 references/,SKILL 正文只保留步骤。下次变种复发时,先比对 fault_signature:签名相同走旧 Skill;签名变了就追加反例,而不是再开一篇「新故事」。

散会前的一句话从「下次注意」改成「谁负责把今天的步骤写成 SKILL 草稿」。有负责人,资产才出现;没负责人,只有英雄事迹。

读到这里,不妨立刻做一个五分钟动作:打开你们仓库,找到与本篇对应的那个目录(没有就新建),把文中最小示意落成真实文件名。文件在,讨论才有坐标;文件不在,下周还会从「我们觉得」开始。第 9 篇的验收不是「读完」,是「仓库里多了一份可指出的东西」。

举例加长:从聊天到 Skill 的 40 分钟节奏

0–10 分钟:把失败日志脱敏,写出 fault_signature 一行。
10–25 分钟:把你刚才的真实步骤写成 SKILL 草稿(含反例)。
25–35 分钟:补一条 command 触发词(口语 + 日志词各至少一)。
35–40 分钟:跑一次故意误命中,看会不会踩到本 Skill;会,就收窄 triggers。

散会口号从「下次注意」换成「草稿谁提交」。提交进仓,才叫提炼;留在聊天,叫表演。

复盘便签(可贴在 issue 模板):

症状: 处置: 验收(含应红): 同类命中次数:1/2/3 是否提议晋升 Skill:是/否 correlation_id:

次数到 3 再谈晋升,是为了挡住「一次成功就写圣经」。圣经太多,召回也会堵车。

思考

小结三句。Skill 来自可重复失败,不是来自一次性灵光。正反例与报告模板是 Skill 可移交的关键。环境噪声不要写死进步骤。

可以理解为:滤出一杯能端给别人的咖啡,再挂上菜单。下篇讲 Pack 如何进入业务仓库——安装、符号链接与 SSOT,避免三处拷贝三处漂移。


下篇预告:《不会还有人三处拷贝 Rule 还手改吧?漂移事故都是这么来的 | Pack 与 SSOT》——漂移事故都是手工拷贝惯出来的。

觉得有用的话,欢迎点赞、留言分享一次「修好又复发」的经历;有提炼画布填到一半卡住的,也欢迎甩格看哪一格空。

专栏:从小白到AI落地大师|《从 Rule 到落地:AI 工程化实践》