当 AI 团队的人数出现三个版本:我们如何用元规则修复数字漂移
从同一系统出现44/46/50三个agent人数的真实事故出发,剖析多文件维护场景下数字漂移的根因并提出Fact-SSOT元规则
- 同一事实在三个文档里出现三个版本,AI 会悄悄选一个继续跑
- 根因是 AI 知识库缺乏"单一事实来源"机制,不同于人类文档
- 解法:Fact-SSOT 三条元规则——隔离、收窄写权限、冲突强制报错
- 半天落地,两周内冲突检测触发三次,全部真实命中,零误报
- 适用场景:变化频率以天/周计、多任务共引用的配置型事实
上周我们的系统里同时存在三个"正确答案"
44、46、50。这三个数字都是我们 AI agent 团队的成员人数,分别来自三个不同的文档文件,在同一套系统里安静地共存了将近两周,直到某个需要跨文件决策的任务把它们同时拉进了上下文窗口。没有人故意制造这个混乱——每次更新都有理由:有人把兼职 agent 算进去写成了 50,有人只统计全职写成了 46,原始的 44 则留在日志摘要的历史快照里没被清理。三种"真相",互不干扰,直到系统被迫同时看见它们。
这不是一个哲学问题,是一个工程问题。而且它比你想象的更常见——只要你的 AI 系统依赖超过两个文档文件,这个风险就已经存在了。
为什么这个问题难排查:AI 不会像人一样停下来质疑
我们一开始以为这只是个文档管理的疏漏,找到三个文件对齐一下就完事了。但复现实验让我们意识到问题更深:当我们把三个版本的文档同时喂给 AI 执行同一个任务时,它没有报错,而是悄悄地选了其中一个数字继续跑。更麻烦的是,结果不稳定——有时用 46,有时用 50,取决于文档在上下文里的排列顺序。
实际上,人类读者在遇到数字不一致时会本能地停下来质疑,会去找原始依据;但 AI 在大多数情况下会默默消化矛盾,用某种内部权重决定相信哪个版本,然后继续执行。这意味着人类文档管理里的小毛病,在 AI 系统里会被放大成持续的、不可预测的系统性偏差——你不知道它选了哪个,也不知道选择依据是什么。这就是数字漂移真正危险的地方:不是一次性的崩溃,而是静默的、难以溯源的错误。
根因:AI 知识库缺少"事实注册表"机制
问题的根因不在于某次手误,而在于文档体系没有对"事实性数据"做专门管理。代码工程里有 Single Source of Truth 的概念——一个常量只在一个地方定义,其他地方引用它。但在 AI 知识库里,我们习惯于在每个文件里把相关信息写完整,导致同一个事实被反复陈述,每次陈述都可能产生微小偏差。
我们引入了一个叫 Fact-SSOT(Fact Single Source of Truth) 的元规则体系,核心逻辑是三条:
第一条:事实隔离——把数字从叙述文档里抽出来
把所有会变化的定量事实(人数、版本号、日期、阈值等)集中存放在一个专用的事实注册表(Fact Registry)里,其他文档使用明确的引用标记而不是直接写死数值。我们用一个有版本控制的 YAML 文件实现这个注册表:
# fact_registry.yaml
# 唯一权威来源,其他文档禁止直接写死以下数值
team:
agent_count_fulltime: 46
agent_count_including_parttime: 50
last_updated: "2025-01-15"
updated_by: "lysander"
system:
prompt_version: "v2.3.1"
context_window_limit: 128000
max_parallel_tasks: 8
其他文档引用时用占位标记,在渲染/注入阶段替换为注册表数值,而不是把数字硬编码进文本里。
第二条:写入权限收窄——让修改事实变得有仪式感
事实注册表设定明确的 Git commit 规范,让"修改事实"这个行为显式化:
# 修改注册表时必须遵循的 commit 格式
git commit -m "fact(team): agent_count_fulltime 44 -> 46
原因: Q1 新增 2 名全职 agent 完成入职
影响文档: system_prompt_v2.md, team_config.md, weekly_report_template.md
验证人: @team-lead"
不需要复杂工具,只需要让团队知道:改注册表不是顺手的事,是需要留记录、通知下游的事。
第三条:AI 读取时的冲突检测——把"悄悄选择"变成"显式报错"
在系统提示里加入一条元指令,强制要求 AI 在检测到数字冲突时停止并上报,而不是自行决断:
# 系统提示中的冲突检测元规则片段
conflict_detection:
enabled: true
instruction: |
当你在上下文中发现同一实体存在不一致的定量描述时(如同一团队
在不同文档中出现不同的人数),立即停止执行当前任务,输出以下
格式的冲突报告,等待人工确认后再继续:
[FACT_CONFLICT]
实体: {entity_name}
冲突值: {value_a}(来源: {source_a}) vs {value_b}(来源: {source_b})
建议参考: fact_registry.yaml
[/FACT_CONFLICT]
可移植的原则:如果你也在维护多文件 AI 知识库
如果你在构建任何依赖多文档的 AI 系统,把"文档一致性"当作一等公民来设计,而不是事后校对的工作——注意力是不可靠的资源,结构才是。
- 如果你在维护超过两个需要引用相同数字的文档,把事实数据从叙述文档里物理隔离出来,建一个哪怕只有十行的 YAML 注册表,总比分散在各处好。
- 如果你在团队协作更新 AI 配置文件,让修改关键数值这个行为变得有仪式感——一条规范的 commit message 比口头约定"下次注意"可靠得多。
- 如果你发现 AI 在处理矛盾信息时"静默通过",在系统提示里加冲突检测元规则,让隐性风险变成可见异常,宁可多几次中断也不要不可预测的偏差。
- 如果你的数据变化频率是实时级别的,Fact-SSOT 帮不了你——那种场景需要真正的数据库和 API,文档规范只适合变化以天或周计的配置型事实。
落地情况与边界
这套规则落地大概花了半天:迁移现有文档两小时,写事实注册表一小时,更新系统提示半小时。运行两周后,冲突检测触发了三次,每次都是真实的数据不一致被及时发现,没有一次误报。更值得记录的是一个副作用:团队成员在更新数字时开始有意识地先去改注册表,这个习惯本身就是收益,不需要额外监督。
需要说清楚的是,Fact-SSOT 不是银弹。它解决的是结构性不一致,不解决数据本身的准确性——如果注册表里的数字一开始就是错的,这套规则帮不了你。数字漂移是个小问题,但它暴露的是系统对自身事实掌控力的脆弱性。在 AI 大量介入决策的系统里,这个脆弱性值得认真对待。
如果你也遇到过类似的多文档一致性问题,或者在考虑如何给 AI 系统设计更健壮的知识库结构,欢迎在评论区聊——我们在 Synapse 框架里把 Fact-SSOT 和其他几条元规则都整合进去了,下一篇我会具体写冲突检测的提示词设计和我们踩过的坑。