做 RAG 功能时,很容易一开始就想加很多高级能力:混合召回、rerank、多轮记忆、Self-RAG。
但我在知光知识社区里踩到的第一个坑更基础:项目里已经有一些 RAG 代码,但端到端闭环并没有真正跑起来。
这篇文章记录我当时的判断:先不要急着加新架构,先把最小可用链路修好。
1. 当时项目已经有什么
代码里并不是完全从零开始。
已经具备的部分包括:
| 能力 | 作用 |
|---|---|
| AI 基础配置 | 聊天模型负责回答,embedding 模型负责向量化 |
| 向量存储 | 使用 Elasticsearch 存储向量和元数据 |
| 入库条件 | 只处理公开且已发布的文章 |
| 幂等判断 | 用正文指纹判断是否需要重建索引 |
| 文档读取 | 根据正文链接拉取 Markdown 内容 |
| 文档分块 | 按 Markdown 标题分段,再按长度切片 |
| 流式回答 | 使用 SSE 把模型输出流式返回前端 |
这些东西看起来已经不少,但问题在于:用户真实提问时,链路并不完整。
2. 为什么先修闭环
如果闭环不可用,继续加 rerank 或查询改写,其实没有意义。
因为你很难判断:
- 是检索没有命中?
- 是切片没写入?
- 是接口没注册?
- 是前端没有收到 SSE?
- 是模型生成失败?
- 还是新增的 rerank 把结果排坏了?
所以第一步应该是让最基础的问题可以回答:
用户在前端提问
-> 后端收到问题
-> 检索当前文章相关 chunk
-> 拼接上下文
-> 调模型生成
-> 前端流式显示
只有这个链路可用,后面优化才有基线。
3. 最小修复范围
当时我把修复范围收得比较小:
- 恢复单篇文章问答接口。
- 恢复手动重建索引接口。
- 对
question、topK等参数做基础校验。 - 保持 SSE 协议不变,避免前端同时大改。
- 修正接口文档,避免文档说可用但运行时不可用。
这一步的目标不是把 RAG 做到最强,而是先建立一个可验证的基础版本。
4. 向量生命周期比想象中重要
RAG 入库不是只负责“新增向量”。
如果一篇文章从公开变成私密,或者从已发布变成草稿,旧向量也应该删除。
否则就会出现一个危险情况:
前台文章已经不可见
但向量库里还留着旧 chunk
全库 RAG 仍然可能检索到它
所以 RAG 的数据生命周期至少要考虑:
- 发布时写入向量。
- 修改正文时重建向量。
- 转私密时删除向量。
- 删除文章时删除向量。
- 指纹没变时跳过重复重建。
这类问题不够酷,但非常工程化,也非常关键。
5. 这次修复给我的教训
RAG 项目不要一开始就追求“功能名词很全”。
真正应该先问:
我能不能稳定把正确资料检索出来?
我能不能看到每一步拿到了什么?
我能不能证明前端收到的是基于资料生成的回答?
数据变化后旧索引会不会残留?
如果这些问题没有答案,系统看起来功能很多,但一旦效果不好,就很难定位。
所以我的 RAG 改造顺序变成:
先修闭环
-> 再加全库问答
-> 再加多轮记忆
-> 再补召回和排序优化
-> 最后做系统评估
这比一上来堆 HyDE、RRF、rerank 更慢一点,但更稳。
