[[RAG]] 的工作流我一般分成两条线看:一条是离线建知识库,一条是在线回答问题。离线把资料处理成可检索的知识单元,在线再根据用户问题把相关知识找出来,拼给大模型生成答案。
离线阶段先做文档处理。原始资料可能是 PDF、网页、Word、数据库记录,先要清洗掉页眉页脚、广告、重复模板这些噪声。然后做 chunk,把长文档切成适合检索的片段。这里不能只按长度硬切,最好结合标题、段落、语义边界,否则一个答案被切到两个块里,检索和生成都会受影响。切完之后,用 [[Embedding]] 模型把每个 chunk 转成向量,连同标题、来源、时间、权限标签这些 metadata 一起写入[[向量库]]或搜索引擎。
在线阶段先进入检索。用户问题进来后,也会被转成向量,到向量库里找 TopK 相似片段。实际项目里我一般不会只靠向量检索,因为专有名词、编号、缩写这类问题,[[BM25]] 反而更稳。所以会用 hybrid search,把向量召回和关键词召回合并,再用 reranker 做精排,把真正能回答问题的内容排到前面。
检索之后是增强。这个阶段表面上是拼 prompt,本质上是上下文选择和上下文治理。要把重复片段去掉,把低相关片段过滤掉,把来源信息保留下来,还要控制总 token 长度。通常我会按“相关性、可信度、时间新旧、权限”来排序,最后组成一个结构化 prompt,比如先给参考资料,再给用户问题,再明确要求模型只能基于资料回答,资料不足就说明不足。
最后是生成。大模型拿到增强后的 prompt 后生成答案,但这里还要加几个工程约束。一个是引用溯源,让答案里的关键结论能对应到来源文档;一个是拒答机制,如果检索分数太低或者资料互相冲突,就不要硬编;还有一个是后处理,比如检查格式、敏感信息、引用是否存在。
所以 RAG 不是简单的“搜一下再回答”,而是从文档处理、召回、[[重排]]、上下文组装到生成约束的一整套链路。任何一环出问题,最后答案都会受影响。比如检索没找对,prompt 写得再好也没用;检索找对但上下文塞太多噪声,模型也可能被带偏。
我会特别强调一点:RAG 的上限往往先由检索结果决定,再由生成模型决定。一个成熟系统要同时评估检索侧的 Recall@K、MRR,也要评估生成侧的[[忠实度]]和答案正确率。