Featured image of post RAG 落地清单:从检索到评测的一套可复用实践

RAG 落地清单:从检索到评测的一套可复用实践

RAG 这东西,demo 很容易做得像模像样:把文档塞进向量库,检索几段,拼进 prompt。 真正上线后麻烦才开始:命中率飘、答案掺幻觉、延迟变长、成本拉满,还很难复盘到底哪里坏了。

我习惯把 RAG 拆成一条链路:数据 → 索引 → 检索 → 生成 → 评测/监控。下面是我做项目时会用的一份清单(偏工程,不追求“讲概念讲漂亮”)。

0. 先把目标写死:你希望它“宁可不答”,还是“宁可猜”?

别急着调 embedding、调 TopK。 先把三句话定下来(写在项目 README 里都行):

  • 答案必须来自哪里:只允许来自知识库?还是允许模型补常识?
  • 失败策略:证据不足时是直接说“不知道”,还是给一个不保证正确的建议?
  • 成功怎么衡量:命中率/用户点赞/转人工率,哪个是主指标?

这三句不定,后面所有优化都容易变成“谁声音大听谁的”。

1. 数据与切分:RAG 的大头在这里

1.1 清洗:先把垃圾去掉

常见噪声:页眉页脚、导航栏、重复版权、目录页、广告块。 这些东西会被 embedding 认真地向量化,最后把检索结果污染得一塌糊涂。

我一般会做一件很土但有效的事:

  • 随机抽 20 个 chunk,人肉读一遍

读完你就知道数据有没有救。

1.2 切分:别只按字数切

纯按字数切最容易把“标题”和“结论”拆开。 更稳的做法是:

  • 先按文档结构切(H1/H2/H3)
  • 再给每个 chunk 设一个上限(比如 300~800 tokens)
  • 把“父标题路径”写进元数据:产品A > 安装 > 常见问题

这样检索出来的段落通常是可读的,不像碎纸片。

1.3 元数据:别省

至少保留:

  • source(URL/文档 ID)
  • title / section_path
  • updated_at
  • doc_type(FAQ/手册/公告/工单)

很多“检索不准”的问题,其实是缺过滤:你想要最新版,结果把三年前的公告也召回了。

2. 索引:向量不是唯一答案

2.1 先做 BM25,再做向量(混合检索更稳)

  • BM25 对报错码、函数名、专有名词很强
  • 向量对“换个说法”很强

真正在业务里,我更偏向:BM25 + 向量 + 融合/重排

2.2 embedding 模型别靠信仰

选模型最靠谱的办法只有一个:用你自己的问题集跑一轮离线评测。 不要看营销文案。

3. 检索:TopK 只是起点

3.1 多路召回

建议至少两路:

  • 向量 TopK
  • BM25 TopK

合并去重后再排一次序。

3.2 rerank 往往是“最便宜的效果提升”

很多时候不是召不回来,而是排序把好段落排到后面了。 加一个 reranker,Top-1/Top-3 命中率通常能肉眼可见地改善。

3.3 控制上下文预算:别把 token 当不要钱

RAG 项目很容易因为“塞太多资料”把延迟和成本拖爆。

我的经验是:

  • TopK 别盲堆,先靠 rerank 提纯
  • 召回后做段内抽取/去重
  • 设硬上限:超过预算就截断

4. 生成:让答案可追溯

4.1 强制引用来源

最实用的格式:

  • 先给结论(两三句话)
  • 再给步骤/细节
  • 最后列出引用条目(文档名/链接)

用户能追溯,你自己也能复盘。

4.2 证据不足就别硬编

检索不到足够证据时:

  • 直接说“当前资料里没找到”
  • 告诉用户需要补什么信息
  • 返回 2~3 个可能相关的文档当引导

这比胡猜强太多。

5. 评测与监控:没有评测就没有 RAG

5.1 离线问题集先做起来

50~200 条就够用:

  • 来自真实用户/客服/工单
  • 每条至少标注:应该命中的 doc id 或答案要点

5.2 两类指标必须分开

  • 检索指标:Top-K recall / MRR
  • 生成指标:是否有证据支撑、是否乱编

别把“检索差”和“生成差”混在一起,不然你永远不知道该调哪一段。

5.3 线上要能回放

至少记录:query、召回文档、最终引用文档、延迟、用户反馈。

出了问题能复现,才有修的可能。

结尾

RAG 的关键不是提示词写得多花哨,而是把它做成一个可控系统:

  • 数据能检索
  • 检索能评测
  • 答案能追溯
  • 线上能回放

要是你愿意给你们的知识库类型(网页/飞书/Confluence/工单)和访问约束,我可以把这份清单改成更具体的“字段设计 + 评测表 + 监控项”。

build with Hugo, theme Stack, visits 0