你挂了 3 个文件:当前产品 spec、上个月同一份 spec 的草稿、关于某一节的 Slack 讨论串。模型产出的总结把三份都当同等权威拉进来。它引用了”草稿”里的一个需求(终稿已经否决),又忽略了当前版的一处变更(因为 Slack 里有人反对)。模型没办法知道哪份权威:它不看文件修改时间,不会从文件夹名里推断出”已否决”,脑子里也没有”canonical(权威版)“这个概念。默认它就是混合,而把”当前” + “已否决草稿” + “内部争论”混在一起,得到的是一个现实中根本不存在的杂交版本。
最快修复: 把每个来源包进一个带 role(角色)和日期的标签块里,写一行优先级规则,再要求逐条引用。三处小改动,混合就停了。下文给出具体该用哪些标签,以及怎么确认生效。
为什么模型会”平均”而不是做选择
这不是随机的。背后有两个有据可查的行为,认清是哪一个,就知道该用哪种修法。
1. 没有出处信号。 不打标签的话,模型看到的就是三块结构相似的文本,没有任何元数据。它分不清”已批准的 spec”和”已经枪毙的草稿”,没有时间字段、没有作者、没有状态——于是把三份当成同等权重的输入。
2. 是位置偏置,不是权威判断。 多个来源相互竞争时,模型靠的是文本在 prompt 里的位置,而不是它有多权威。有充分研究的”lost in the middle”(中间内容被遗漏)效应——到 2026 年仍在各前沿模型上观测到的 U 形注意力曲线——意味着长 prompt 最顶部和最底部的内容权重最高,中间部分则被低估。所以如果你那份已否决草稿恰好贴在最后,它可能纯粹因为位置就压过了正确答案。更新的模型(尤其是 Claude)衰减得比旧模型慢,但截至 2026 年 6 月,没有任何生产模型消除了位置偏置——你不能指望模型”自己就知道”最新那份才是真的。
#1 的修法是打标签 + 定优先级;#2 的修法是结构 + 摆位:把权威来源放在模型最关注的地方,并明确告诉它哪个标签胜出。
你属于哪一类
| 输出里的症状 | 可能原因 | 跳到 |
|---|---|---|
| 旧版本的事实冒出来 | 没有时间/状态标签,模型分不清新旧 | Step 1–3 |
| 输出偏向第三方博客、压过你自己的 spec | 没标一手 vs 三方 | Step 4 |
| 你看不出每条论断来自哪个来源 | 没要求逐条引用 | Step 5 |
| 文档和代码不一致,模型选错了 | 没有”文档 vs 代码谁赢”的规则 | Step 6 |
| 两个来源一致,却引了较弱的那个 | 没有”引用 canonical 那个”的指令 | Step 2、5 |
动手前先确认
- 列出 prompt 挂的每一个来源。
- 给每个定角色:
canonical、supplementary、context-only,或者直接删掉。 - 标时间顺序:哪个最新、哪个当前、哪个已否决。
- 定优先级规则,例如:“当前 spec 胜过草稿;spec 胜过 Slack;一手胜过三方。”
- 计划要求逐条引用,这样才能审计每条事实出自哪个来源。
需要收集的信息
- 你挂的全部来源,按你粘贴的顺序。
- 拉错来源的那段输出(留作 before/after 基线)。
- 你团队的真实优先级——谁说了算、谁定 canonical。
- 每个来源的元数据:日期、作者、状态。
- 用的模型和任何 system prompt(优先级规则应该放在 system prompt 里,见 FAQ)。
最短修复路径
Step 1:每个来源标上名字、日期、角色
用一个结构化的外壳,让模型有元数据可推理。对 Claude,官方文档记录的多文档约定是:用 <documents> 包住若干个 <document>,每份里放一个 <source> 标签和一个 <document_content> 标签。再加上你自己的 role/status/date 属性——XML 的标签名和属性名并不固定,用模型能读懂的描述性名称正是 Anthropic 推荐的做法。
<documents>
<document index="1" role="CANONICAL" date="2026-05-15" status="ratified">
<source>product-spec.md</source>
<document_content>
... 当前 spec 内容 ...
</document_content>
</document>
<document index="2" role="REJECTED_DRAFT" date="2026-04-01" status="superseded">
<source>spec-draft.md</source>
<document_content>
... 旧草稿,仅供对照 ...
</document_content>
</document>
<document index="3" role="DEBATE" date="2026-04-20" status="discussion">
<source>slack-debate.txt</source>
<document_content>
... slack 讨论 ...
</document_content>
</document>
</documents>
现在每条事实都带着可追溯的出处和一个模型能据以行动的状态。
Step 2:一行声明优先级
紧跟在文档块后面写(或者更好,放进 system prompt——见 FAQ):
优先级规则:
- CANONICAL 胜过 REJECTED_DRAFT 胜过 DEBATE。
- CANONICAL 与 DEBATE 冲突时,CANONICAL 赢。
- REJECTED_DRAFT 仅供对照;绝不可作权威引用。
- 来源一致时,引用 CANONICAL 那一个。
- 发现冲突时,明确指出来,不要悄悄选一边。
最后那一行很关键。让模型把冲突说出来、而不是默默替你拍板,这才是把”无声混合”变成”可审计的决定”。
Step 3:权威来源放最前,问题放最后
由于上面说的位置偏置,排序是个实打实的杠杆,不是表面功夫。两条摆位规则,都有 Anthropic 长上下文指南背书:
- 长的来源文档放在靠顶部,在你的指令和问题之上。
- 你真正的问题放在最底部,在所有文档之后。在 Anthropic 的测试里,把问题放在长多文档 prompt 的末尾(而不是开头),回答质量最多提升 30%。
如果你只能保留一个来源,就留 canonical 那个,其余删掉——来源越少,混合出错的机会越少。
Step 4:标注一手 vs 三方
<document role="FIRST_PARTY_CANONICAL"><source>our-spec.md</source>...</document>
<document role="THIRD_PARTY_CONTEXT"><source>competitor-blog.html</source>...</document>
规则:关于我们产品的事实论断,优先 FIRST_PARTY。
THIRD_PARTY 只用于行业背景,绝不用于关于我们自己产品的事实。
不标的话,模型可能仅仅因为营销文案往往比内部 spec 语气更自信、更斩钉截铁,就偏向第三方来源。
Step 5:要求逐条引用,并用引文做支撑
这是杠杆最高的一步。先让模型把证据引出来,再写——这就是 Anthropic 文档里的”用引文给回答做支撑”技巧,能去噪、也能暴露混合:
第一步:回答前,先把你要依据的原文引文抽出来。每条放进 <quotes> 标签并标明来源,
例如 <quote source="product-spec.md">...</quote>。
第二步:输出里每条事实论断都内联标注来源:
"[论断] [source=product-spec.md, section=2.3]"
无法对应到引文的论断,标 [UNCITED],让审稿人核查或删除。
引文先行做了两件事:逼模型锚定到真实文本、而不是一个模糊的平均;并让无声混合显形——没有引文支撑的论断会以 [UNCITED] 暴露出来。
Step 6:文档 vs 代码,声明谁赢
文档与代码不一致时:
- 行为问题("它实际怎么做?"):以代码为权威。
- 意图问题("它本该怎么做?"):以文档为权威。
- 用了哪个都必须标注,并把这处不一致点出来。
怎么确认已经修好
重跑 prompt,按顺序检查:
- 输出里每条事实论断都带引用(或明确标了
[UNCITED])。 - 引用指向 canonical 来源,而不是草稿或讨论串。
- 你 before 基线里那条具体的过期事实,不再出现。
- 同事能打开被引来源、找到被引章节、确认论断成立。
- 连跑两次,来源分布一致——如果某条事实在两次运行里来源来回跳,说明你的优先级规则太弱,得收紧。
如果还是没修好
- 干脆删掉次要来源。 模型只需要 canonical 文档,就只给它 canonical 文档。
- 把优先级搬进 system prompt。 在 Anthropic 和 OpenAI 的指令层级里,system/developer 级指令都高于用户消息里的内容,所以放在那里的优先级规则,比埋在文档堆里的更难被覆盖。
- 用带元数据的检索(RAG)。 给每个 chunk 都挂上它的
role、date、status,让出处在检索后依然在。 - 拆成两遍。 第一个 prompt 只从 canonical 来源抽事实;第二个 prompt 在抽出的事实上做分析。混合的机会根本不出现。
- 高风险工作放量前,手审每一条引用。
预防建议
- 默认:每个多源 prompt 都用一个块声明优先级。
- 文件名编码角色 + 日期(
spec-canonical-2026-05.md),还没打开文件标签就一目了然。 - 维护一份明确的”已过期、不可作权威使用”清单,记下那些只为对照而保留的来源。
- 任何分析型 prompt 都要求逐条引用。
- RAG 设置里,给每个 chunk 都挂来源元数据,而不只是文档头部。
- 把任何没有优先级规则的生产多源 prompt 都当成已知风险,看到就修。
FAQ
优先级规则应该放 system prompt 还是用户消息? 优先放 system prompt。在 Anthropic 和 OpenAI 的指令层级里,system/developer 指令都高于用户回合里的任何内容,所以放在那里的优先级规则,不太会被某份文档里语气自信的话覆盖掉。文档和问题放在用户回合,“CANONICAL 胜出”这条规则放在 system prompt。
我真的需要 XML 标签吗,还是写”Source 1 / Source 2”就够了?
两个短来源,纯文本标签够用。来源更长或更多时,结构化标签(<document>、<source>、<document_content>)能减少串味,因为模型能清楚看到一个来源在哪结束、下一个在哪开始。Anthropic 对多文档 prompt 明确推荐这个外壳;标签名本身不是魔法,但清晰的边界是。
模型为什么偏向更旧或已否决的那份文档? 通常是位置问题,不是判断问题。由于”lost in the middle”/近因偏置,贴在最后(或最前)的来源不论状态如何都会被更重地加权。把 canonical 来源放靠顶部、问题放在底部,并明确写出优先级规则,让决定权交给权威、而不是位置。
两个来源一致,模型却引错了那个,怎么强制它引 canonical? 加上明确指令”来源一致时引用 CANONICAL 那个”(Step 2),并要求引文先行做支撑(Step 5)。当模型必须给每条论断附上一段原文引文和来源名,它就没法引一个其实没从那里读到该事实的来源了。
遇到真实冲突、我自己也还不知道哪份对,怎么办? 让模型把冲突摆出来、而不是替你解决:“如果两个来源对某条事实有分歧,不要悄悄选一个——把两条论断、各自来源和日期都列出来,然后停下。“由你来拍板,而不是模型。
相关阅读
外部参考:Anthropic — 长上下文 prompt 技巧 与 Anthropic — 用 XML 标签组织 prompt。