你的 AI 助手分不清"用户说的"和"自己猜的"——这才是它越来越笨的真因

0 阅读6分钟

上篇聊了"修好上下文,省 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_generatedAI 生成/猜测的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-arbitermemory_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 实录,感兴趣可以关注。)