building a rag model

接入与开发

讲清从零搭一套 RAG 的工程落地顺序:先定进料与切块口径,再做检索与拼装,最后补上超时、并发、降级、日志和评测五件套。

很多人第一次搭 RAG,代码跑通了,问题却出在别处:文档一多就超时,批量重建被限流,召回时好时坏没人说得清,出了错连日志都对不上。这篇不讲原理,只按「先跑通一条链路、再逐项加固」的顺序,把每一步该定什么口径、该测什么、什么时候可以先不做讲清楚,适合已经有模型接口、准备动手写第一版的人。

第一次搭 RAG,代码跑通只是起点。真正让人卡住的是文档一多就超时、批量重建被限流、召回时好时坏没人说得清、线上答错了翻日志什么都对不上。这些都不是算法问题,是工程口径问题。

下面的顺序只有一个原则:先跑通一条最短链路,再逐项加厚。每一步都写清楚该定什么口径、验收看什么、什么情况下可以先不做。已经有模型接口、准备写第一版的人可以直接照着走。

第一步:把进料和切块口径定死

进料这一步最容易被跳过,但它决定了后面全部结构。先想清楚文档是一次性导入还是定期增量:一次性导入可以简单粗暴地全量重建,定期增量就必须做去重、版本覆盖和删除标记,否则老内容会一直留在库里污染召回。

  • 切块先只定三个数:单块长度、块间重叠、是否按标题层级切;先按经验值跑,用真实问题回测再调,不要一次调到底;
  • 每个块必须带元数据:来源文件、章节位置、更新时间、权限标签,缺一项后面都难查;
  • 标题层级建议保留,因为很多答案就藏在「某个小节里」,切碎之后关系就丢了;
  • 解析失败的文件要单独落一份清单,别让它静默消失。
口径定什么不达标的表现
单块长度一个块能装多少字太长召回不精准,太短答案被切碎
块间重叠相邻块共享多少内容没有重叠时跨段答案经常缺半句
切分方式按长度还是按标题按长度切会打断小节结构
元数据来源、章节、时间、权限答错时无法定位到具体段落

第二步:召回、排序、拼上下文,先做最朴素的一条

第一版用单一向量召回就够了,别一上来就混合检索加重排。原因很实际:多层叠在一起出问题时,你分不清是哪一层坏了。单层跑通之后,每加一层都要能用回归集证明它确实带来改善。

  1. 先跑通单路召回用户问题直接转向量,取相似度最高的若干块,不做任何改写和重排。这一步的目标是链路通,不是效果好。
  2. 定上下文预算块数、总长度、是否带原文引用,三件事一起定死。超预算就按得分截断,不要指望模型自己忽略多余内容。
  3. 分开记日志把「检索到的内容」和「模型说的内容」分别记录,事后才能判断是召回没找到,还是模型看到了没用上。
  4. 回测再调用一批真实问题跑一遍,观察是切块问题、问题表述问题,还是嵌入模型选得不对。

召回效果不理想时,调整顺序建议是:先怀疑切块粒度,再怀疑用户问题的表述方式,最后才怀疑嵌入模型。嵌入模型怎么选,可以到 /embeddings 对照当时的资料。

第三步:超时、并发、降级,这三样不补迟早出事

这三件事在演示阶段都不明显,上线后集中爆发。超时没分层,量一大就整条链路一起挂;并发不限,批量建库时接口直接限流;没有降级方案,主模型一抖整个功能就不可用。

  • 超时至少分三档:检索、模型调用、整体链路各一个值;链路的必须大于前两者之和,否则永远先死在总超时上;
  • 批量建库和批量提问都要限并发,按接口额度分档排队,失败任务落盘后重投,而不是原地重试;
  • 降级顺序提前定:主模型失败换备用、检索为空时退回直答、重排失败退回原始顺序,每一级都在日志里打标记;
  • 限流和延迟基线不用猜,先到 /tools/speed-test 量出自己环境的真实数字再定参数。

判断标准很简单:把主模型接口临时关掉,系统应该仍能给出一个明确的结果或提示,而不是整体超时。做不到,说明降级没设计完。

第四步:日志和评测,让你知道改动是变好还是变坏

没有日志和评测,所有优化都是凭感觉。日志解决「这次为什么错」,评测解决「这次改动到底有没有用」,两件事缺一不可,而且都要在链路稳定后尽早补上。

记录项为什么必须记缺了会怎样
用户问题复盘的起点不知道当时问的是什么
召回块 ID定位召回是否命中无法区分召回错和生成错
上下文长度判断是否被截断超预算截断却看不出来
模型与耗时排查慢和抖出问题无参照
成本与失败标记看趋势和限流影响只能事后估算

评测准备一组固定的真实问题做回归集就够,不用一上来就搞复杂框架。每次改完切块、召回或提示词,跑一遍对比。先看两个指标:能不能找到(召回覆盖)、找到后有没有用上(引用一致性)。具体评测口径和工具可以到 /tools/quality-check 看当时的说明。

哪些先别做:给第一版的减法清单

第一版最该克制的是加功能。下面这些不是不能做,而是要在链路稳定之后再做,否则每加一层都会让排查难度翻倍。

  • 微调、图结构检索、多路召回并行、自动改写问题,都放到链路稳定之后;
  • 只有「切块口径已经定死、召回长期不达标、且确认不是数据质量问题」时,才值得引入重排或混合检索;
  • 多租户权限过滤要做在前端和检索层,不要指望模型自己不看没权限的块;
  • 两人以内的小团队,优先把进料和日志做扎实,多数效果提升来自数据质量而不是新算法。

如果连文档来源和更新方式都还没定,加再多检索层也没用。判断标准:当你无法用一句话说清「这个块从哪来、什么时候更新」,就说明还在第一步,先把基础补上。

下一步先量出你自己环境的延迟和限额基线,再回头定超时和并发参数;顺带把切块结果过一遍质量检查,避免在错误的分块上做调优。

常见问题

跑通第一版最少需要多少东西?

一份清洗过的文档、一个能切块的脚本、一个向量库、一个模型接口和一段拼提示词的代码,就这些。切块先按固定长度加重叠跑起来,召回只用单路向量,评测先拿五到十个真实问题人工看结果。先让链路能端到端跑一遍,再逐个位置加复杂度。

召回结果不稳定,从哪里开始查?

按顺序查四件事:切块是不是把一句话切断了;元数据有没有丢;问题表述和文档用词差多远;向量模型换一个会不会明显不同。查的时候固定同一批问题做对比,别每次换一批。如果四步都正常还是不行,再去考虑重排和混合检索,不要一开始就上。

批量建库老是失败或被限流怎么办?

先把并发降到很低跑一小批,确认是限流还是数据本身有问题。确认是限流就做分档排队,失败任务写文件等下一次重投,不要原地循环重试。接口额度、串流和计费口径的实时数字,到 /official-api 和 /price-watch 核对当天的口径。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。