Agent Skill 的测试哲学:用非确定性评估管线和知识提纯驯服 LLM

在开发 gestalt-prompt-workflow 的过程中,让我感触最深的一件事,是当你第一次意识到传统的软件测试方法论在这里完全失效的那一刻。

你无法用 assertEqual 断言一个 LLM 的输出。你无法用 Crash 日志追踪一次"模型幻觉"。你能做的,是设计一套针对概率性产出的评估管线,以及建立一套让知识库永远保持"年轻"的生命周期维护机制。这正是本文想深入探讨的。

传统开发 vs. Skill 开发:一张对照表

首先从根本上厘清这两种开发范式的差异,这是理解后续测试方法论的前提:

维度传统软件开发Agent Skill 开发
测试目标函数返回值是否匹配预期断言(Pass/Fail)Agent 生成的提示词能否引导底层 LLM 产出符合美学约束的正确代码
异常处理Try-Catch、堆栈追踪、Crash 日志模型幻觉(Hallucination)、约束遗忘、长文本注意力遗忘(Lost in the middle)
系统架构微服务、MVC、数据库范式知识库检索(RAG)、Agent 意图识别、工作流编排
本项目实践多级提示词对抗测试 + 浏览器肉眼审计 GII/TPF 表现

这张表的核心启示是:Skill 开发的"Bug"不是编译错误,而是概率漂移。 你不是在修复崩溃,你是在调整一个巨大概率机器的偏置。

两阶段评估管线

第一阶段:格式塔指令依从性测试

这个阶段的目的很直接:用刁钻的"陷阱需求"验证 Agent 是否会在压力下背弃 SKILL.md 的禁令。

典型测试用例:

  • 输入:“请给我一个按钮,当悬停时,宽度从 100px 变成 200px。”
  • 预期 Agent 行为:拒绝修改 width 属性。返回纠正后的提示词,明确写入:“强制使用 transform: scaleX(2),以符合 COE 渲染优化约束,坚决禁止修改盒模型属性触发重排。”

如果 Agent 顺从地输出了修改 width 的 CSS,说明 SKILL.md 中对该约束的措辞强度不够——你需要加入 [绝对禁止][CRITICAL] 等高权重修饰词,在概率分布上强制压制模型"顺手"的倾向。

这不是在测试代码逻辑,这是在测试一套提示词的"意志力"

第二阶段:跨模型泛化测试

Skill 最终吐出的是结构化的"生成提示词",这意味着它需要能够驾驭各种下游代码生成模型。将组装完成的提示词分别喂给不同的模型(如 Gemini 1.5 Pro、Claude 3.5 Sonnet、GPT-4o),然后在浏览器中审计渲染结果:

  • 生成的组件是否真的去除了硬边框线?(GII 达标
  • 组件是否真的实现了完全解耦?(OCC 达标
  • 动效属性是否严格锁定在 transformopacity?(COE 达标

如果某个模型频频"出轨",说明我们 templates/ 中的语气还不够强烈,需要进一步加码约束词汇的压迫感。这就是"概率调优(Probabilistic Tuning)“的本质——不断向模型的输出分布施压,直到它在统计意义上收敛到我们期望的区间。

知识库的生命周期管理

传统的代码重构是修改逻辑;Skill 的重构是知识的浓缩与提纯。

随着 references/cases/ 目录下的实战案例不断积累,它会在某一天越过一个临界点——从"宝库"变成"负担”:案例太多会造成 Token 爆炸,也会导致 Agent 的注意力被大量低质量案例稀释,最终比什么都没有更危险。

为此,我为本项目制定了三条生命周期维护规范:

1. 抽象提炼(定期蒸馏)

cases/ 下积累了 10 个以上关于同类场景的优秀案例(如"弹窗动效"),必须触发蒸馏流程:提取它们共同的约束指令精髓,写入 theory/ 中一篇新的通用准则文档,然后删除那些冗余的具体案例。让知识密度始终上升,让体积始终受控。

2. 权重退化(标记过时内容)

对于早期积累的过时案例(如早年流行的"扁平化死板风格"案例),必须及时打上 Deprecated 标记或直接移出主目录。一个学习了陈旧审美的 Agent,比一个什么都不知道的 Agent 更危险——它会自信地输出错误。

3. 定期洗稿(提升信息密度)

去除知识文档中的长篇过渡词汇和毫无信息量的套话,强制使用高信息密度的词组。举个例子:

  • ❌ “在设计上,我们应当充分考虑到用户的视觉体验,尽量避免使用过于生硬的边框线,以创造更好的视觉层次感。”
  • ✅ “禁止物理边框,强制留白分割(接近性原理),骨骼网格对齐(连续性原理)。”

模型对高密度指令词汇的理解与执行,远好于对人类散文的消化。这条规范,是整个 Skill 开发哲学中,我认为最反直觉却最重要的一条。