很多人第一次做 RAG,路径都很相似:把文档转成文本,切成 chunk,丢进向量数据库,用户提问时召回 topK,再把结果塞给大模型。这个流程能跑起来,也能做出一个不错的演示。
但真正上线后,问题会接二连三出现:为什么搜不到明明存在的内容?为什么答案引用了过期文档?为什么同一个问题今天答 A 明天答 B?为什么模型把两个版本的接口混在一起?为什么用户看到了不该看的内部资料?
这些问题说明,RAG 不是“给大模型外挂知识库”这么简单。它更像一个知识系统的产品化过程:把分散、脏乱、持续变化的知识,变成可检索、可引用、可治理、可评测的系统能力。
RAG 的第一道坎是知识清洗
很多 RAG 项目效果差,不是模型弱,也不是向量数据库不行,而是知识源太脏。
真实知识库里常见的问题包括:
- PDF 提取后段落顺序错乱
- 表格被拆成无意义的短句
- 代码块丢了缩进
- 文档标题层级丢失
- 同一份文档多个版本同时存在
- 旧制度和新制度互相矛盾
- 会议纪要里夹杂大量口水话
- 图片里的关键信息没有 OCR
如果这些问题不处理,后面的向量化、重排、生成都只是在脏数据上做精致包装。
我会把知识入库前处理成一个管道:解析、清洗、结构识别、去重、版本标注、权限标注、质量检查。每一步都应该可回放。尤其是企业知识库,不能只保留清洗后的文本,还要保留原始来源和转换日志,否则后面无法追责。
切分不是按字数切一刀
chunk 是 RAG 的基本单位,但很多系统把它处理得太粗糙。固定 500 字一切,看似简单,实际会破坏语义结构。
不同内容应该有不同切分策略:
- API 文档适合按接口、参数、返回值、错误码切
- 教程适合按步骤和小节切
- FAQ 适合一问一答成块
- 制度文件适合保留章节和条款层级
- 会议纪要适合按议题、决策、行动项切
- 代码文档适合按模块、函数、类、示例切
好的 chunk 不只是文本片段,还应该带元数据:文档标题、章节路径、来源 URL、更新时间、作者、版本、权限、业务域、相邻片段 ID。这样检索和生成时才能知道它来自哪里、处在哪个上下文、是否仍然有效。
我更喜欢“结构优先,长度兜底”的切分方式。先尊重文档结构,再用长度限制控制模型上下文成本。不要为了整齐的 chunk 长度牺牲语义完整性。
检索不是一次向量相似度排序
向量检索很强,但它不是万能的。它擅长语义相似,却容易在数字、版本号、函数名、错误码、专有名词上翻车。
比如用户问“SDK 2.7.3 初始化报 E104 怎么办”,纯向量检索可能召回一堆“初始化失败排查”的文档,但漏掉真正包含 E104 的短条目。关键词检索在这里反而更可靠。
成熟 RAG 通常是混合检索:
1. 先按权限、业务域、版本过滤
2. 并行做关键词检索和向量检索
3. 合并召回结果并去重
4. 用重排模型或规则重排
5. 根据时效性、来源可信度、文档质量加权
6. 控制多样性,避免 topK 全来自同一篇文档
这个流程比简单 topK=5 麻烦,但可靠性高很多。尤其是技术知识库,关键词、代码符号、版本过滤往往和语义检索一样重要。
重排决定最后进入模型的证据
召回只是把可能相关的材料捞出来,重排才决定哪些材料真的进入模型上下文。
我会在重排时考虑几个因素:
- 与问题的语义相关性
- 是否包含精确关键词
- 文档是否过期
- 来源是否权威
- 用户是否有权限
- chunk 是否能独立解释问题
- 是否与其他 chunk 重复
- 是否包含可引用的原文
这里还有一个细节:不要盲目把 topK 全塞给模型。上下文不是越多越好。噪声越多,模型越容易综合出一个看似合理但实际混杂的答案。
我的经验是,RAG 的核心不是“召回更多”,而是“让模型看到更干净、更少、更准的证据”。
引用是信任的入口
专业场景里,RAG 的回答必须能被验证。用户不只想知道答案,还想知道答案从哪里来。
一个可信的 RAG 回答应该区分:
- 文档明确提到的事实
- 基于多个文档综合得到的结论
- 模型根据上下文做出的推断
- 当前资料不足,需要补充信息
引用也要具体。只说“参考公司文档”没有意义。最好能定位到文档、章节、段落,展示短原文片段,并允许用户点击查看来源。
没有引用的 RAG,即使答对,也很难建立长期信任。它更像一个自信的摘要器,而不是可靠的知识助手。
权限是 RAG 最容易被低估的部分
内部知识库通常不是所有人都能看所有内容。销售、研发、财务、管理层、外部客户看到的知识范围完全不同。
权限不能只在前端做,也不能只在最终答案阶段过滤。正确做法是在检索前就参与过滤:用户没有权限的文档,不应该进入召回候选,更不应该进入模型上下文。
否则即使最终回答没有直接泄露,模型也可能把敏感信息间接综合进答案里。
权限元数据要和知识一起入库,检索时做强过滤。对多租户系统来说,还要把租户 ID、组织 ID、项目 ID 都纳入过滤条件。这一点不性感,但决定系统能不能上线。
更新机制决定 RAG 能活多久
知识库不是一次性导入。文档会过期,接口会改名,产品会下线,流程会调整,旧方案会被废弃。
所以 RAG 需要生命周期管理:
- 草稿
- 生效
- 即将过期
- 已过期
- 已废弃
- 被新文档替代
检索时应该优先返回有效版本。如果用户问历史问题,可以允许检索旧版本,但回答里要明确“这是历史版本”。
我还建议对知识建立变更通知。某篇高频引用文档更新后,系统应该知道哪些问题、哪些回答模板、哪些评测样例可能受影响。否则你以为知识库更新了,实际上用户还在被旧答案影响。
评测不能只看人工感觉
RAG 很容易陷入“感觉还不错”。但感觉不能支撑长期迭代。
我会为 RAG 建一套评测集,至少包含:
- 标准问题
- 期望引用文档
- 关键事实点
- 不应该出现的错误答案
- 权限场景
- 过期文档干扰场景
- 多版本冲突场景
- 无答案场景
评测指标也要拆开看:
- 召回率:正确证据有没有被召回
- 精确率:召回内容里噪声多不多
- 引用准确率:引用是否真的支持答案
- 答案一致性:同类问题是否稳定
- 拒答质量:资料不足时是否敢说不知道
- 权限正确性:是否泄露不该看的内容
只有把检索、引用、生成拆开评测,才知道系统到底坏在哪一层。
RAG 的产品体验也很重要
技术人员容易只关注检索链路,但用户感知的是整个产品。
一个好用的 RAG 应该让用户知道:
- 正在查哪些范围
- 找到了哪些来源
- 答案置信度如何
- 哪些内容是引用,哪些是推断
- 为什么没有找到答案
- 用户如何反馈“这个答案不对”
反馈入口很关键。用户点“没用”时,系统应该记录问题、答案、引用、用户角色、检索结果,而不是只记一个负反馈。否则你无法判断是切分问题、召回问题、重排问题,还是生成问题。
我的结论
RAG 的本质不是让模型“知道更多”,而是让知识以可治理的方式进入模型。
它既是工程问题,也是内容问题、权限问题、产品问题和运营问题。真正成熟的 RAG,不会停在“文档向量化”这一步,而会建立完整的知识生命周期:采集、清洗、切分、索引、召回、重排、引用、反馈、更新、评测。
当你把 RAG 当成知识系统来做,它才有机会长期好用。
评论
评论默认审核后展示。你可以匿名留言,也可以登录后保留自己的互动记录。