很多人第一次搭 RAG,代码跑通了,问题却出在别处:文档一多就超时,批量重建被限流,召回时好时坏没人说得清,出了错连日志都对不上。这篇不讲原理,只按「先跑通一条链路、再逐项加固」的顺序,把每一步该定什么口径、该测什么、什么时候可以先不做讲清楚,适合已经有模型接口、准备动手写第一版的人。
第一次搭 RAG,代码跑通只是起点。真正让人卡住的是文档一多就超时、批量重建被限流、召回时好时坏没人说得清、线上答错了翻日志什么都对不上。这些都不是算法问题,是工程口径问题。
下面的顺序只有一个原则:先跑通一条最短链路,再逐项加厚。每一步都写清楚该定什么口径、验收看什么、什么情况下可以先不做。已经有模型接口、准备写第一版的人可以直接照着走。
第一步:把进料和切块口径定死
进料这一步最容易被跳过,但它决定了后面全部结构。先想清楚文档是一次性导入还是定期增量:一次性导入可以简单粗暴地全量重建,定期增量就必须做去重、版本覆盖和删除标记,否则老内容会一直留在库里污染召回。
- 切块先只定三个数:单块长度、块间重叠、是否按标题层级切;先按经验值跑,用真实问题回测再调,不要一次调到底;
- 每个块必须带元数据:来源文件、章节位置、更新时间、权限标签,缺一项后面都难查;
- 标题层级建议保留,因为很多答案就藏在「某个小节里」,切碎之后关系就丢了;
- 解析失败的文件要单独落一份清单,别让它静默消失。
| 口径 | 定什么 | 不达标的表现 |
|---|---|---|
| 单块长度 | 一个块能装多少字 | 太长召回不精准,太短答案被切碎 |
| 块间重叠 | 相邻块共享多少内容 | 没有重叠时跨段答案经常缺半句 |
| 切分方式 | 按长度还是按标题 | 按长度切会打断小节结构 |
| 元数据 | 来源、章节、时间、权限 | 答错时无法定位到具体段落 |
第二步:召回、排序、拼上下文,先做最朴素的一条
第一版用单一向量召回就够了,别一上来就混合检索加重排。原因很实际:多层叠在一起出问题时,你分不清是哪一层坏了。单层跑通之后,每加一层都要能用回归集证明它确实带来改善。
- 先跑通单路召回用户问题直接转向量,取相似度最高的若干块,不做任何改写和重排。这一步的目标是链路通,不是效果好。
- 定上下文预算块数、总长度、是否带原文引用,三件事一起定死。超预算就按得分截断,不要指望模型自己忽略多余内容。
- 分开记日志把「检索到的内容」和「模型说的内容」分别记录,事后才能判断是召回没找到,还是模型看到了没用上。
- 回测再调用一批真实问题跑一遍,观察是切块问题、问题表述问题,还是嵌入模型选得不对。
召回效果不理想时,调整顺序建议是:先怀疑切块粒度,再怀疑用户问题的表述方式,最后才怀疑嵌入模型。嵌入模型怎么选,可以到 /embeddings 对照当时的资料。
第三步:超时、并发、降级,这三样不补迟早出事
这三件事在演示阶段都不明显,上线后集中爆发。超时没分层,量一大就整条链路一起挂;并发不限,批量建库时接口直接限流;没有降级方案,主模型一抖整个功能就不可用。
- 超时至少分三档:检索、模型调用、整体链路各一个值;链路的必须大于前两者之和,否则永远先死在总超时上;
- 批量建库和批量提问都要限并发,按接口额度分档排队,失败任务落盘后重投,而不是原地重试;
- 降级顺序提前定:主模型失败换备用、检索为空时退回直答、重排失败退回原始顺序,每一级都在日志里打标记;
- 限流和延迟基线不用猜,先到 /tools/speed-test 量出自己环境的真实数字再定参数。
判断标准很简单:把主模型接口临时关掉,系统应该仍能给出一个明确的结果或提示,而不是整体超时。做不到,说明降级没设计完。
第四步:日志和评测,让你知道改动是变好还是变坏
没有日志和评测,所有优化都是凭感觉。日志解决「这次为什么错」,评测解决「这次改动到底有没有用」,两件事缺一不可,而且都要在链路稳定后尽早补上。
| 记录项 | 为什么必须记 | 缺了会怎样 |
|---|---|---|
| 用户问题 | 复盘的起点 | 不知道当时问的是什么 |
| 召回块 ID | 定位召回是否命中 | 无法区分召回错和生成错 |
| 上下文长度 | 判断是否被截断 | 超预算截断却看不出来 |
| 模型与耗时 | 排查慢和抖 | 出问题无参照 |
| 成本与失败标记 | 看趋势和限流影响 | 只能事后估算 |
评测准备一组固定的真实问题做回归集就够,不用一上来就搞复杂框架。每次改完切块、召回或提示词,跑一遍对比。先看两个指标:能不能找到(召回覆盖)、找到后有没有用上(引用一致性)。具体评测口径和工具可以到 /tools/quality-check 看当时的说明。
哪些先别做:给第一版的减法清单
第一版最该克制的是加功能。下面这些不是不能做,而是要在链路稳定之后再做,否则每加一层都会让排查难度翻倍。
- 微调、图结构检索、多路召回并行、自动改写问题,都放到链路稳定之后;
- 只有「切块口径已经定死、召回长期不达标、且确认不是数据质量问题」时,才值得引入重排或混合检索;
- 多租户权限过滤要做在前端和检索层,不要指望模型自己不看没权限的块;
- 两人以内的小团队,优先把进料和日志做扎实,多数效果提升来自数据质量而不是新算法。
如果连文档来源和更新方式都还没定,加再多检索层也没用。判断标准:当你无法用一句话说清「这个块从哪来、什么时候更新」,就说明还在第一步,先把基础补上。
下一步先量出你自己环境的延迟和限额基线,再回头定超时和并发参数;顺带把切块结果过一遍质量检查,避免在错误的分块上做调优。→常见问题
跑通第一版最少需要多少东西?
一份清洗过的文档、一个能切块的脚本、一个向量库、一个模型接口和一段拼提示词的代码,就这些。切块先按固定长度加重叠跑起来,召回只用单路向量,评测先拿五到十个真实问题人工看结果。先让链路能端到端跑一遍,再逐个位置加复杂度。
召回结果不稳定,从哪里开始查?
按顺序查四件事:切块是不是把一句话切断了;元数据有没有丢;问题表述和文档用词差多远;向量模型换一个会不会明显不同。查的时候固定同一批问题做对比,别每次换一批。如果四步都正常还是不行,再去考虑重排和混合检索,不要一开始就上。
批量建库老是失败或被限流怎么办?
先把并发降到很低跑一小批,确认是限流还是数据本身有问题。确认是限流就做分档排队,失败任务写文件等下一次重投,不要原地循环重试。接口额度、串流和计费口径的实时数字,到 /official-api 和 /price-watch 核对当天的口径。