做 RAG 最常卡住的一步不是检索算法,而是选 embedding 模型:别人说好的换到你的语料上召回就掉,换成自建又担心显存和延迟。这篇按工程落地的顺序给一套筛选流程——先定硬约束,再动手跑一版小评测,最后用评测结果和线上日志决定留谁、什么时候该换。
做 RAG 最常卡住的一步不是检索算法,而是选 embedding 模型。别人说好的模型换到你的语料上,召回说掉就掉;换成自建又担心显存、延迟和批量灌库撑不住。这事没有通用最优解,只有在你自己的约束里筛出来的最合适。
所以别上来就比模型,按工程落地的顺序走:先定硬约束砍掉一批候选,再用一版小评测缩到两三个,然后把延迟、吞吐、重刷成本算清楚,最后上线靠日志判断留谁、什么时候该换。评测方法怎么设计、公开榜单怎么读、各家规格怎么核,先到 /benchmarks 和 /rankings 摸个底,注意榜单口径和你的业务语料不是一回事。
第一步:先把硬约束定下来,别急着比模型
先确认语料形态。中英混排、纯中文长文档、含代码或表格的文档,对分词方式和最大输入长度的要求差得很远。这一步不是选型细节,是先卡边界:切块长度如果超过模型能吃的上限,尾部会被静默截断,召回质量会莫名其妙地变差,而且很难从表象上看出来。
- 语种与语料形态:中英混排、纯中文长文、含代码或表格,先按这条排除不合适的候选
- 部署形态:走 API 还是本地推理,直接决定你能不能调参、能不能批量重刷全库
- 资源边界:自建的话要看单卡能不能同时装下模型和向量库,别装得下模型装不下库
- 切块长度:和模型最大输入长度对齐,超长会被截断,先测一遍再定切块策略
- 产出物:一张候选表,不是结论
这一步的产出是候选表,不是最终结论。具体有哪些模型在售、各自规格参数是什么,到 /embeddings 按当时的清单核对,别用记在脑子里的旧数。
第二步:用一版小评测把候选缩到两三个
自己造 30 到 50 条真实问题,每条标出唯一正确答案所在的文档片段。这是你后面所有判断的基准,比任何公开榜单都贴近业务。别嫌少,关键是问题要真、标注要准,一份糊弄的评测集比没评测还糟,因为它会给你错误的信心。
- 造评测集从线上真实提问和客服记录里捞 30 到 50 条,逐条标出正确片段 ID,存成固定文件,后面每次换模型都跑同一份
- 跑第一轮用原始问题检索,只看两件事:正确片段有没有进前 K 条,以及它在排序里排在第几
- 跑第二轮把问题同义改写成另一种说法再跑一遍,第二轮的命中掉幅就是模型的鲁棒性,掉得多说明它对措辞太敏感
- 停手判断候选缩到两三个就停,继续往下比收益很小,把时间留给后面的部署和成本核算
| 观察项 | 看什么 | 掉下来意味着什么 |
|---|---|---|
| 前 K 召回 | 正确片段是否进前 K 条 | 切块或语种不匹配 |
| 排序位置 | 正确片段排在第几位 | 后续重排成本变高 |
| 改写鲁棒性 | 同义改写后掉多少 | 对措辞敏感,用户换句话就查不到 |
| 长文表现 | 长文档中部片段的召回情况 | 切块长度或输入截断有问题 |
第三步:把延迟、吞吐和成本算清楚再定
API 形态要看单次请求的延迟分位,以及批量接口支不支持。建库时是批量灌数据、线上是单条查询,两种压力的瓶颈点不一样,别拿建库的体验去判断线上的表现。自建形态要看批大小拉高之后显存和吞吐怎么变、单卡能跑多大并发,给向量库留够位置。
- 建库压力
- 一次性批量灌全库,瓶颈通常在吞吐和接口限流
- 线上压力
- 单条查询的高频请求,瓶颈通常在延迟分位而不是均值
- 重刷成本
- 换模型等于全库重新向量化,是最大的一次性开销,选型时就要算进去
换模型意味着全库重新向量化,这是最大的一次性成本。选型时把重刷一遍的时间和调用量都算进去,具体单价到 /tools/model-cost-calculator 和 /official-api 按当时的数字算,别用印象里的价。成本压不下来时优先调切块和批量,而不是先降维。
- 短文档别急着降维,语义区分度本来就低,降完更容易混
- 明细类问答别降维,它对细粒度差异敏感
- 长文档为主、语义跨度大的场景可以考虑,但要先测召回再决定
- 降维前先把切块和批量调好,多数成本问题出在前面而不是维度上
第四步:上线怎么观测,什么时候该换
把每次检索的查询文本、召回片段 ID 和排序打日志。模型好坏最终要靠线上真实问题的命中情况判断,光看离线评测不够,因为线上提问的措辞比你造的问题更杂。日志字段的口径可以参考 /tools/quality-monitor,别只记一个总成功率,那样出问题查不出原因。
设两个观察信号:一是用户追问「不是这个意思」的比例,二是人工抽检里召回片段的相关性。这两个任一持续变差,才考虑换模型。别因为出了新版就换,模型迭代快,你的语料和业务问题没变,换模型带来的往往是重刷成本和新的不确定性。
- 打日志记录查询文本、召回片段 ID、排序位置,字段口径对齐质量监控页面
- 灰度切换新旧向量各存一份或按流量切分,跑一段时间对比同一批评测问题,确认不掉再全量重刷
- 排除非模型问题语料本身脏、切块策略有问题、查询改写缺失,这些表现和模型差很像,先排掉再谈换模型
- 全量重刷确认无损后再全量重建向量库,重刷期间保留旧索引兜底
RAG 选 embedding 模型不是找最强的那个,是找在你的语种、切块和预算里最不拖后腿的那个。下一步拿你手头的语料和真实问题跑一版小评测,再去核对各模型当时的规格和价格,别凭印象下单。→
常见问题
选 embedding 模型要不要直接抄公开榜单的前几名?
可以当候选来源,但不能当结论。榜单用的语料、切块长度和查询分布跟你不一样,前几名在你的场景掉出前十很常见。正确做法是拿榜单缩候选,再造几十条自己的问题跑一版命中评测,用你自己的数字决定,公开榜单到 /benchmarks 看当时的版本即可。
中文 RAG 是不是只能用国产 embedding 模型?
不是,多语种模型在中英混排语料上往往更省事,尤其是文档里夹英文术语、代码或表格时。判断标准是拿你的真实文档跑一次召回评测,看中文长句和英文短语两类问题的命中率是否都过得去,只偏一类就说明该换或该做双路检索。
线上召回效果变差,怎么判断是模型的问题还是切块的问题?
先固定模型,只调切块长度和重叠比例跑一轮评测,如果命中明显回升就是切块问题。切块调到稳定后仍然不行,再换 embedding 模型做对比。顺序反了最容易浪费一次全库重刷的时间和成本,排查步骤可参考 /tools/quality-check 的做法。