我把 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 不难,难在「每一环都调对」。把它拆成上面七步,每一步都有明确踩坑点,你就能在面试里讲出「我为什么不只用框架」。