文档智能体

9 分钟读完

U15
实战手册 · 编码与计算机操作智能体

文档智能体。

写错的测试会失败;写错的一段话会被人信两年。文档是你仓库里唯一没有裁判的产物——这意味着文档智能体没有任何东西能纠正它。于是唯一可行的设计是:按"机器能不能核查"把文档语料切开,只在能核查的那一片上给智能体无人监督的权限,在其余所有地方把它降级为一个提工单的人。

STEP 1

别的编码智能体都有裁判,这个没有。

打补丁的智能体有测试套件,做迁移的有编译器,做评审的有一个要么合并要么不合并的人。这些都是在改动抵达任何人之前就会喊出错了的信号。文档没有这样的信号,而且这个缺口不是你能补上的工具短板——它正是文档存在的理由。如果一句话的正确性能从代码推导出来,那句话就不必写。

  • 它的失败是无声且长久的。构建挂掉九十秒内就会被发现。一个描述着上季度已被删掉的开关的页面,要等到第十四个来试的人才被发现,那已是几个月后,而他们中的大多数根本不会来告诉你。
  • 在这里,"流畅"本身就是那个特定的危险。模型"听起来像文档"的本事强于"是对的"的本事,而读者会拿文体当权威的代理指标。一段自信的错话,会打赢一段留有余地的对话——这正是幻觉与接地里的接地问题,只不过瞄准了读者最信任的那件产物。
  • 所以"合并前人工评审一下"不是方案。那是所有人都会写进文档、却没人真的执行的方案:为事实准确性去评审散文比自己写还慢,而一个每周都到的文档 PR,到第三周就只会被扫一眼。
  • 这就把设计问题定住了。要问的不是"怎么让智能体写出好文档",而是"哪些论断可以被机械地证伪,以及我们如何禁止它在无人监督时做出别的论断"。
STEP 2

按可核查性切开语料,并让这条切线决定权限。

你的文档不是一样东西,而是四样真值条件差别极大的东西。有用的做法,是在写下第一行智能体代码之前,先把每一页归进其中一类。

  • 派生型参考 —— 机器可核查,交给智能体。参数表、返回类型、错误码、CLI 开关、环境变量、接口 schema。真值是源码的函数,所以漂移可被检测、再生成可被验证。这类内容应当是生成出来的而不是写出来的;当源码形状变化时,智能体的活儿是让生成器保持诚实。
  • 可执行散文 —— 机器可核查,交给智能体。能编译能跑的代码样例、容器能端到端执行的快速上手、能解析的链接、与 lockfile 一致的版本号。这里的每一项都是一个附带测试的论断;把那个测试接进 CI,智能体就在这一片上继承了一个裁判。
  • 解释型散文 —— 不可核查,智能体只能提议。这个组件为什么存在、它取代了什么、三种做法里你该选哪种、当初促成这个设计的失败模式。这些文字的价值恰恰在于:某个人知道一件源码没有记录的事。
  • 责任性内容 —— 不可核查,永远不要自动化。安全指引、迁移步骤、数据处理说明,以及任何读者会不假思索照做的东西。这里写错一句是一起事故,不是一个错别字。

比这套分类更要紧的是比例。在多数仓库里,前两类占了页面数的大头,却几乎不占任何人记得住的写作工作量——这正是它们最陈旧的原因,也正是一个带着机械校验的智能体能立刻回本的地方。

STEP 3

从源码写出来的文档,会连同 bug 一起继承源码的假设。

最顺手的搭法,是把智能体指向代码然后要文档。它会产出读起来不错、但价值很低的东西,原因值得说准确:那是对输入的一次有损复述,而好文档里每一句有意思的话,恰恰是输入里没有的信息。

  • 它说不出意图。代码说重试次数是 3。文档的活儿是说清为什么是 3、设成 10 会怎样,以及这个数字当初是为一个如今已不存在的下游限流选的。
  • 它会把 bug 洗成规范。当智能体靠读实现来描述行为时,一个缺陷就变成了被记录在案的行为;而一旦记录在案,它就成了某人日后拒绝打破的兼容性义务。
  • 它说不出"别用这个"。成熟文档里最有价值的一句话是把读者从自己身上指开:已废弃、已被取代、仅供遗留路径使用。源码里没有任何东西能区分"推荐的 API"和"还能用的 API"。
  • 把别的输入喂给它。提交信息、PR 讨论、issue 线程、设计文档和支持工单才是意图的所在地,而在这些材料上做检索才是真正有价值的能力——也就是仓库导航与代码上下文里那个检索问题。
  • 逼它引用。每一条非派生的论断都要带上它来源的提交、issue 或讨论链接。一条没有出处的断言,评审者去核实的成本高于自己重写,这与依赖升级智能体里是同一笔账。
STEP 4

把"删除"做成一等输出,否则没别的东西会做。

放任不管,文档智能体只会让语料单调增长:每一轮都在加,没有一轮在减。两个季度后,你的文档集大了 40%,同样多的正确内容被稀释到更多页面上,内部矛盾更多,搜索结果更差——而智能体的看板从头到尾都显示它很高产。

  • 互相矛盾比缺失更糟。两个页面用不同说法描述同一个接口,严格劣于只有一个页面:因为读者现在必须裁决,而他手上没有任何裁决依据。找出这类成对矛盾是模型真正的好用途,也是没有任何 linter 会做的事。
  • 给智能体一条删除通道,配上它自己的证据门槛:被记录的符号已不存在、页面连续两个季度零访问、内容是另一页的真子集、或者它引用的版本低于你的支持下限。每一条都可核查。
  • 要重定向,不要留孤儿。一个留下断链的删除 PR 是净亏损;智能体的删除只有在每一条入链都被重新指向后才算完成——而这恰是它擅长的机械活。
  • 给语料设预算。如果页面数被允许每季度上涨,就没有任何东西逼你做取舍。一个上限能把"该不该加这一页"变成一个真问题,而它是文档智能体身上最便宜的一道控制。
STEP 5

把它指向读者真正栽跟头的地方。

没有信号,智能体就会去改最容易改的东西——也就是那个已经有人在意、维护良好的页面。真正需要动的,是一年没人打开、而且是错的那些页。方向必须由你提供,它没法从仓库里推导出来。

  • 支持工单是你手上等级最高的输入。每一个用"这在文档里,喏"回复掉的工单,都是一次发现失败;每一个用文档里根本没有的事实回复掉的工单,都是一个覆盖缺口——而且正确措辞已经写在那条回复里了。
  • 零结果的搜索,以及搜完不点击的搜索。它们点出了读者对这东西的叫法与你的叫法之间的词汇鸿沟——通常是世上最便宜的文档修复。
  • 改了行为却没动文档的 diff。一个改了默认值、错误信息或公开签名却在 docs/ 下什么都没更新的 PR,是一次可以在发生当下就抓住、而不必一年后才发现的陈旧事件。
  • 你自己的编码智能体犯的错。当一个内部智能体误用了你的 API,那段轨迹就是一份来自异常字面化读者的文档缺陷报告——正是工具发现与文档为工具描述所讲的那条反馈回路,只是搬到了面向人的页面上。

每页引发的读者失败次数给积压排序,而不是按陈旧程度。一个三年没人读的老页面没关系;一个上线六周、每周制造一张工单的页面才是急件。

STEP 6

把它跑起来:小 PR、收窄的凭据,以及一个会往下走的指标。

运维上的失败不是某个写坏的页面,而是没人评审的数量。以下每一条都指向同一个目标:把每次改动的人工成本压到评审真的会发生的水平。

  • 一个 PR 只装一件事。重新生成的参考表可以自动合并,重写的概念页不行,删除也不行。混在一起,最严的评审门槛会套到整批上,然后这批就再也不动了。
  • 派生型参考每次合并都跑,散文类工作按周节奏跑。参考文档的漂移不该活过一次提交;解释型工作应当以评审者吸收得了的速率抵达,见定时与事件触发的智能体
  • 把凭据收窄。读仓库、读工单系统、推分支、开 PR。不能合并,不能发布到文档站,不能在分支之外碰重定向表。文档站是公开面,而一个被攻陷的文档智能体就是一条通往你自己用户浏览器的内容注入通道。
  • 把检索到的文本当作不可信输入。在多数产品里,issue 线程和支持工单是攻击者可写的,而这个智能体读着它们、旁边就挂着仓库写权限——沙箱与安全执行里的隔离论证在这里原样适用。
  • 报告新鲜度与读者失败率,永远不要报告写了多少页。"写了多少页"只会上涨,而且在智能体干着最没价值的活时涨得最快。派生型参考相对其源码的年龄中位数、以及每月由文档引发的工单数,这两个数在事情做对时会下降,做错时会上升。

在动任何智能体之前先做这件事:把团队最近二十张用"给个链接"回复掉的支持工单拿出来,逐个检查那个链接指向的页面里是否真的含有答案。含有的那些是发现问题——去修导航和搜索,不需要智能体。不含有的那些就是你的覆盖积压,而它们的答案已经写在你自己的支持回复里了;第一个月里,你应该只把文档智能体指向这一批。

相关:代码评审智能体——这些 PR 另一端的评审者;评估编码智能体——衡量上述任何一项;以及翻译与本地化智能体——当这份语料需要以不止一种语言存在时。