RAG 最容易被描述成“给模型接上知识库”。这句话没错,却把最难的部分藏起来了:什么内容值得被检索,怎样切分,召回几段,如何判断召回结果真的回答了问题,回答里哪些句子可以回到原文。
我现在更愿意把 RAG 看成一个检索系统,模型只是最后负责组织语言的一环。输入先经过清洗和切分,文档要保留标题、来源、更新时间等元数据;向量召回得到的是“相似”,不是“正确”;重排或关键词检索可以补回专有名词和精确版本。每一步都应有可观察的中间结果。
切分长度没有通用答案。太短会把上下文拆散,太长又会把无关段落一起送进模型。更重要的是切分边界要尊重文档结构:配置项、代码块、表格和问答不应该被随便从中间截断。将标题和路径放进每个片段的元数据,模型才能知道“这段话属于哪里”。
召回测试也不能只拿几个漂亮问题。应该准备一组真实查询,标注相关片段,分别测召回率、排序位置和最终回答是否引用了正确来源。遇到“模型说得很顺但原文没有”时,先看召回内容,再看提示词,最后才考虑换模型。否则所有问题都会被归因成模型不够聪明。
上下文窗口越大也不代表答案越好。无关片段会稀释重点,重复内容会让模型过度自信,过时文档还可能覆盖最新说明。查询时带上时间、版本和权限过滤,通常比继续堆更多资料有效。对私有知识库尤其要在检索层过滤,而不是等模型自己遵守权限。
一套能维护的 RAG 还需要删除和更新策略。文档被修改以后,旧向量何时失效,索引如何重建,失败时能否继续服务,都要写成任务状态。把“上传成功”直接等同于“知识库已更新”,很快就会出现页面和回答互相矛盾的情况。
RAG 没有魔法。它把阅读、检索、排序和引用这些原本需要人做的动作拆成了可以测量的步骤。步骤越透明,模型越像一个有来源的助手;步骤越模糊,回答越容易只是语气很确定的猜测。
最后是引用。回答里的每个关键判断都应该能回到片段和原文位置,无法找到来源时就降低语气或直接说不知道。一个愿意承认缺口的检索系统,比一个永远给出完整句子的系统更值得长期使用。
检索系统的效果还要用样本衡量。准备几组用户问题,记录应该命中的文档和不能回答的文档,再比较召回结果、上下文长度和最终回答。没有这组基线,换模型或改提示词以后只能凭印象判断好坏。
RAG 也需要明确的停止条件:检索不到足够证据时,回答应该承认缺口;文档互相冲突时,应该把冲突呈现出来。系统愿意少说一句,通常比把不确定内容拼成完整答案更可靠。