上篇聊了"修好上下文,省 80% token"。这篇聊一个更隐蔽、也更致命的问题:
你的 AI 助手,分不清"你告诉它的"和"它自己猜的"。
用 Claude Code、Cursor 久了,你大概率遇到过这种时刻:
- 你明明说过"这个项目用方案 A",过几天它又给你推荐方案 B
- 它信誓旦旦地说"这个接口返回 200",其实那是它上周猜的,早就改成 404 了
- 你问它"为什么这么做",它给你一个听起来很合理的理由——但那个理由是它事后编的,真正的决策依据早被覆盖了
这些不是模型笨。是它不知道该信谁。
真正的问题:记忆没有"可信度"
大部分 AI 工具的记忆,是这样的:
所有记忆 → 一坨文本 → 全部塞给模型 → 模型自己看着办
这里有个致命缺陷:"用户亲口说的" 和 "AI 上次瞎猜的",在记忆里长一个样。
模型每次读记忆,分不清哪条是事实、哪条是幻觉的残留。它只能按"最近读到的"或"出现次数多的"来判断——于是旧的事实被新的猜测覆盖,越用越偏。
这就是为什么你的 AI 助手越聊越笨:不是它忘了,是它的记忆里噪音盖过了信号。
memory-arbiter 怎么解决:给记忆打上"可信度标签"
我做的这个开源 MCP 工具 memory-arbiter,核心思路是给每条记忆打上来源标签:
| source_type | 含义 | 信任分 |
|---|---|---|
user_confirmed | 用户确认过的 | 100(自动锁定,谁都改不了) |
document_extracted | 从文档抽取的 | 70 |
agent_generated | AI 生成/猜测的 | 45 |
unknown | 来源不明 | 10 |
模型下次读记忆时,一眼就知道哪条该信、哪条只是参考。
user_confirmed 的记忆会被自动锁定(protection_level = locked),任何 agent 都无法自动覆盖——你想让它变,必须显式授权。这一条直接堵死了"AI 用自己的猜测覆盖你定的事实"。
但光有标签还不够:新旧记忆打架怎么办?
真正有意思的是冲突仲裁。
假设今天发生这种情况:
- 上周记录:
"接口 /api/foo 返回 200"(来源:agent_generated,事件时间:7月1日) - 今天记录:
"接口 /api/foo 返回 404"(来源:agent_generated,事件时间:7月6日)
两条都是 AI 观察到的、来源相同。该信谁?
传统做法是让 LLM 逐条去比对所有记忆——N² 复杂度,烧 token 还不准。memory-arbiter 的做法是用规则化仲裁:
memory_compare(left_id=12, right_id=15)
返回一个结构化裁决:
{
"winner_side": "right",
"winner_id": 15,
"loser_id": 12,
"manual_review": false,
"reasons": ["right has newer event_time; fact occurrence time has priority"],
"rule_order": ["user_confirmed/locked protection", "event_time", "source_type", "confidence", "ingest_time"]
}
关键在于理由是可解释的:右侧赢了,因为它的事件时间更新(描述的是更新的现状)。规则顺序也一目了然:用户确认 > 事件发生时间 > 来源可信度 > 置信度 > 写入时间。
这意味着——模型不需要自己判断该信谁了,仲裁引擎已经告诉它了。 模型只负责"确认"这个动作,不负责"推理"。前者便宜,后者又贵又不稳。
仲裁规则的优先级(这个设计我挺得意)
冲突发生时,按这个顺序判断胜负:
1. user_confirmed / locked 保护 ← 用户确认过的,永远赢,不接受自动覆盖
2. event_time(事实发生时间) ← 描述的是更新的事实,赢
3. source_type(来源可信度) ← 文档 > AI 猜测
4. confidence(置信度) ← 高分赢
5. ingest_time(写入时间) ← 最后的兜底
第一优先级是最关键的防线:用户确认过的记忆,任何 agent 都不能覆盖。这就保证了 AI 不会"自作主张"推翻你定下的东西。
第二优先级解决"事实更新":旧信息和新信息打架时,描述更新现状的那条赢——比如"接口现在返回404"压过"接口曾经返回200",这是对的。
每一条裁决都留痕:谁裁的、依据哪条规则、什么时候裁的,全在 conflicts 表里。出了问题你能追溯,而不是一个黑箱告诉你"我们觉得这条是对的"。
一个真实的场景:跨工具协作时的记忆冲突
这才是仲裁真正发挥威力的地方。
我平时同时用好几个 AI 工具——Claude Code 写代码、Cursor 改前端、Codex 跑任务。它们共用 memory-arbiter 的一个记忆库。于是会出现这种情况:
- Claude Code 觉得"这个模块应该用 React Query"
- Cursor 觉得"这个模块应该用 SWR"
两个 AI 工具,对同一件事,写了不同的记忆。没有仲裁的话,后写入的直接覆盖前面的,你根本不知道发生过冲突。
有了仲裁:
memory_arbitrate(left_id=20, right_id=21, mark_conflict=True, apply=True)
系统会按规则判一个赢、标记冲突、记录理由。更重要的是——如果两条都是 AI 生成的(都不是用户确认的),你可以让它返回 manual_review,把决定权交还给你。
AI 之间意见不合时,不该让其中一个 AI 悄悄赢,而该让你(用户)来拍板。这才是"可信"的记忆系统。
和"让 LLM 自己判断"相比,省了多少
这是个实际的成本对比:
| 做法 | 流程 | Token 消耗 |
|---|---|---|
| 传统:LLM 逐条比对 | 把所有记忆塞进去,让模型两两比对、推理谁对 | ~2000+ tokens / 次,且不稳 |
| memory-arbiter | memory_compare 返回结构化裁决,模型只确认 | ~200 tokens / 次 |
省 90%,而且更稳——规则是确定性的,不会因为模型今天心情不好就判错。
怎么用
一行装:
pip install memory-arbiter-mcp
接到任意支持 MCP 的客户端(Claude Code / Cursor / Codex / ZCode)。完整工具列表和集成方式:
👉 github.com/billy12151/… star / issue)
写在最后
很多人觉得 AI 助手"变笨"是模型问题,于是不断换更强的模型、塞更多的 context。
但很多时候,问题不在模型,在于你喂给它的记忆里,事实和猜测混成一团,它根本分不清该信谁。
memory-arbiter 想做的,就是给记忆装上"可信度"和"仲裁机制"——让 AI 知道什么是你说的、什么是它猜的、新旧冲突时该听谁的。
与其换更贵的模型,不如先把记忆理清楚。
(这是 memory-arbiter 系列第二篇。第一篇讲"省 token + 跨工具共享",这篇专讲"冲突仲裁"。下一篇可能会写"我是怎么用 memory-arbiter 管理 memory-arbiter 自己的开发记忆的"——dogfooding 实录,感兴趣可以关注。)