搭 RAG 的时候,模型这一格往往是最先定、也最容易定错的:别人说某版本好用,你接上去发现长上下文一塞就慢、结构化输出老是多包一层、账单还比预期高一截。这篇不讲协议也不讲客户端怎么配,只按「这份资料适合喂哪个版本、生成端怎么兜底、上线前拿什么验」这条工程线,给你一份能照着做的选型对照和验收清单。
搭 RAG 的时候,模型这一格往往是最先定、也最容易定错的。别人说某个版本好用,你接上去发现长上下文一塞就慢、结构化输出老是多包一层、账单还比预期高一截。这篇不讲协议也不讲客户端怎么配,只按「这份资料适合喂哪个版本、生成端怎么兜底、上线前拿什么验」这条工程线,给你一份能照着做的选型对照和验收清单。
核心思路是把 RAG 当成一条流水线,而不是一个模型调用。流水线上每一段对模型能力的要求并不一样,混在一起谈选型,最后一定是两个人各说各话。下面按进料、检索、拼装、生成四段拆开,每段给出判断标准和可执行动作,数据类的结论请到站内页面核对当时的数字。
先按任务切段,再谈选哪个版本
把 RAG 拆成四段:进料清洗、向量化与检索、上下文拼装、最终生成。四段对模型的要求完全不同。进料在意稳定和便宜,检索在意召回,拼装在意长度控制,生成在意指令遵循和格式。先把每段的职责写清楚,再讨论每一段用哪个版本,比笼统问「哪个模型适合 RAG」靠谱得多。
- 生成端按回答形态分三类:短事实抽取、长文档归纳、带格式的结构化输出。前两类对长上下文容忍度高,第三类更看指令遵循。
- 一个实用判据:把「检索质量问题」和「生成质量问题」分开测。检索没召回的内容,换任何版本都救不回来。
- 每段的验收指标不要混用:检索看召回率,生成看关键点覆盖和格式合规,拼装看上下文字符数分布。
- 什么情况下不适用:如果语料本身很少、问题基本是单文档事实问答,分段选型的收益有限,直接用一套配置即可。
| 链路环节 | 主要考量 | 先看什么 |
|---|---|---|
| 进料清洗 | 稳定性与吞吐 | 批量任务的重试与失败率 |
| 向量化与检索 | 召回质量 | 是否漏掉关键片段 |
| 上下文拼装 | 长度与顺序 | 拼装后字符数分布 |
| 最终生成 | 指令遵循 | 引用是否对得上片段 |
长上下文适配:塞得进不等于用得上
先量出真实需求:统计你库里单次召回片段拼起来后的字符数分布,取中位数和九十分位各记一个数,再决定要不要走长上下文路线。很多团队凭感觉说「我们文档很长」,真统计完发现九成请求并不需要那么长的输入,白白付了延迟和成本。
长上下文常见的两个坑:中间位置信息被忽略,俗称中段丢失;以及首字延迟明显拉长。前者靠把关键片段前置来缓解,后者靠控制拼装总长度来缓解。这两条不涉及具体数字,具体能压到多少、延迟差别多大,到 接口测速(/tools/speed-test) 用你自己的语料跑一遍最准。
- 量分布抓一周线上请求,记录每次拼装后的字符数,算中位数和九十分位,作为拼装策略的输入依据。
- 做对照实验同一批问题跑两次,一次全量塞入,一次只塞重排后的前几段,对比答案完整度。
- 看提升决定如果全量塞入没有提升,就说明该省这笔开销;有提升再评估延迟是否可接受。
结构化输出与失败兜底
RAG 里最实用的输出是「答案 + 引用来源 + 片段编号」三件套。要求模型返回固定字段时,字段越少越稳,别一次塞十几个键。字段一多,模型容易在某个嵌套层级上多包一层或漏一个括号,下游解析直接崩。
兜底顺序建议:严格模式解析失败,退到宽松解析,比如用正则抓 JSON 片段;再失败就退到纯文本回答并标注「未结构化」;还不行才换一个版本重试一次。重试要有上限,并且把重试次数写进日志字段,不然成本会悄悄翻倍。这类记录的口径可参考 质量监控(/tools/quality-monitor) 的思路。
| 失败层级 | 处理动作 | 还失败怎么办 |
|---|---|---|
| 严格 JSON 解析 | 直接取字段 | 退到宽松解析 |
| 宽松正则抓取 | 补全缺失字段 | 退到纯文本回答 |
| 纯文本回答 | 标注未结构化 | 换版本重试一次 |
| 再次失败 | 返回兜底文案 | 记录并人工抽查 |
什么样的场景不必做这么细:内部工具、人看着结果用的,解析失败直接给人看原文就行,别为它搭一套重试链路。反过来,如果输出要写回数据库或触发下游动作,兜底就必须做全。
上线前的小评测:二十条用例就够
固定一批二十条上下的问题,覆盖四类:单文档事实、跨文档对比、库里没有的问题、格式要求严格的。每条写清期望答案的关键点,别写成模糊的一句话,否则测完也不知道算不算过。
- 每次换版本或换拼装策略,重跑同一批,只记四个数:答对条数、引用正确条数、平均首字耗时、单次平均消耗。
- 接口层面的延迟基线先跑一遍测速,把网络和网关的波动和模型本身的速度分开看。
- 「库里没有的问题」这一类专门用来测模型会不会硬编答案,答「未找到」才算过。
- 什么情况下不适用:语料每周大改的场景,用例集也要跟着换,否则测的是过期知识,结论会误导。
这四个数就是你的选型依据。至于同类模型和各家官方接口当前的价格区间,去 价格追踪(/price-watch) 看当时的数字,别拿几个月前的印象做预算。
降级路径与要留的日志
降级可以是换版本,也可以是换策略:先减上下文、再减重排、最后才换模型。顺序反过来,成本和效果都会难看。因为大多数时候不是模型不行,而是你塞进去的东西太多太乱。
- 降级顺序
- 先减上下文长度,再关掉重排,最后才切换模型版本
- 重试上限
- 同一个请求只允许换版本重试一次,超了就走兜底文案
- 配置口径
- 把模型版本和拼装策略当成一组配置一起记录
日志至少留五项:请求 id、命中的片段 id 列表、拼装后的上下文长度、是否触发重试、最终产出走的是哪条路径。缺任何一项,效果变差时你都说不清是换了模型、改了拼装,还是语料变了。
判断标准很简单:只要出现过一次「效果变差但没人知道为什么」,这套日志就该补齐了。在这之前,先用最小字段跑起来比什么都强。
下一步先把你库里的拼装字符数分布量出来,再拿二十条用例跑一遍对照,选型结论自然就有了;顺路去站内核对当前的接口价格与可信度,预算和对齐口径一起定下来。→常见问题
RAG 是不是一定要用长上下文版本?
不一定。先看你实际召回片段拼起来有多长,如果大部分请求只用到几段,短上下文加好一点的重排往往更划算;反过来,跨文档推理多、片段天然零散的场景,长上下文才体现出价值。
生成端答案不好,先换模型还是先改检索?
先改检索。判断方法很简单:把你认为该出现的片段手工塞进提示词,如果这时答案变好了,问题在检索;如果还是不对,才轮到换版本或改提示词。跳过这一步直接换模型,多数时候是浪费。
多个版本混用会不会很难维护?
会,所以要限制组合数。常见做法是只分两档:一档用于需要结构化输出的场景,一档用于长文归纳。两档共用一个拼装策略和一份日志口径,版本一旦超过两三个,排查时基本对不上账。