手搓生产级 RAG:不依赖 RAGFlow 的完整链路
我把 RAGFlow 摸透之后(见 RAGFlow 切片策略实战),反过来手搓了一套不依赖任何框架的 RAG。为什么还要手搓?三个理由:依赖轻、逻辑透明、能精细调每一环。这篇把完整链路和踩坑讲清楚。
一、链路全景
1 | 文档加载 → 切分 → 向量化 → 入库 → 检索 → 重排 → 拼 prompt → 生成 → 引用约束 |
框架帮我们封装了其中几步,但每步独立替换才是手搓的价值。
二、切分:比想象中重要
切得不对,检索必崩。我的经验(和 RAGFlow 切片那篇一致):
- 不要固定字数硬切,按语义/标题层级切,保留上下文窗口;
- 中文要指定语言,否则按空格断词直接废;
- 重叠窗口(overlap)能救「答案被切断」的case;
- 改了切分策略,旧文档必须删了重传重切,否则新旧混着检索会乱。
三、向量化:选对句向量模型
- 中文场景优先用中文优化的 embedding(bge / m3e 系),别拿英文模型硬上;
- 维度不是越大越好,768 维通常够;
- 入库前先 normalize,检索时用内积等价于余弦,省算力。
四、检索:混合检索才是基线
纯向量检索在「专有名词、精确匹配」上很弱。我的做法:
- 关键词(BM25)兜底精确匹配;
- 向量负责语义召回;
- 两者得分归一化后融合(RRF 或加权)。
这就是 RAGFlow「混合检索」的底层逻辑,手搓版一样能做。
五、重排:把 top-k 提纯
召回 20 条,重排后取 top-3 进 prompt,效果明显好于「召回几条边进」。开源 reranker(如 bge-reranker)几行代码就能接。
六、生成:引用约束防幻觉
最容易被忽略的一步:要求模型标注答案出处段落,回答里带 [1][2]。这样既能让用户核查,也能在「检索到了但没用上」时快速定位——我之前排查过这类问题,就是模型被无关段落带偏,加引用后肉眼可查。
七、手搓 vs RAGFlow 怎么选
| 维度 | 手搓 | RAGFlow |
|---|---|---|
| 上手成本 | 高(要写代码) | 低(可视化) |
| 可控性 | 每环可调 | 框架内调 |
| 文档解析 | 自己接 | 内置 DeepDoc 强 |
| 适合 | 工程团队/定制 | 快速验证/非技术 |
我的结论:验证阶段用 RAGFlow,要嵌进自己产品就手搓。两者打通同一套 embedding + 重排,迁移成本很低。
小结
手搓 RAG 不难,难在「每一环都调对」。把它拆成上面七步,每一步都有明确踩坑点,你就能在面试里讲出「我为什么不只用框架」。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 河岳日星的博客!

