教学项目 · 虚构文档 · 最近核验:2026-10。附标准库代码,不需要模型 API;完整的模型生成与部署不在本例中。

“连上向量数据库,再把结果塞给 LLM”,确实能做出一个 RAG 演示。真正用起来,问题通常出在别处:规定已经改了,助手还在引用旧版;答案看着对,引用却支撑不了它;文档搜到了,但这个用户本来就没有权限看。

这几篇从一个小知识库开始,讲清数据怎样更新、资料怎样检索(retrieval),以及答案怎样检查。RAG(retrieval-augmented generation,检索增强生成)的基本做法是先找资料,再让模型参考资料回答。但“搜到了”不等于“搜对了”,还要检查版本、权限和内容本身。原始论文

报名日期改了,助手知道吗?

虚构的社区有一份活动规则。旧版写“报名截止到周五”,新版改成了“周三”;另有一份只有组织者可见的预算说明。普通成员问:“这次最晚哪天报名?”

文档 内容 能否作为这次回答的依据
rules-v1 报名截止到周五 不能:已被新版取代
rules-v2 报名截止到周三 可以:当前生效、成员可见
budget-v1 组织者内部预算 不能:无权限,也不回答这个问题

理想回答很简单:“周三截止,依据是活动规则 v2。”难点在于,新版已经生效,索引却可能还没更新完。我们在这个项目中选择:暂时查不到当前规则,就说明情况,不拿旧日期来凑答案。其他场景是否允许展示带日期的旧资料,需要另行约定。

文档更新和用户提问,分开处理

  1. 01 / 文档更新规则改为周三记录文档版本与权限,不能只替换正文。
  2. 02 / 准备证据按章节切块保留原文位置;需要向量时,在这里编码。
  3. 03 / 更新索引v2 成为当前版本旧片段不能继续充当现行规则。
  4. 04 / 用户提问最晚哪天报名?结合身份,只查询可见且生效的内容。
  5. 05 / 选择证据把 v2 放进上下文合并、去重、重排,再选择长度允许的段落。
  6. 06 / 形成回答周三,依据是 v2证据不足时说明缺什么,不偷偷引用 v1。
1–3 处理文档更新,4–6 处理用户提问。每段资料保留来源和版本,方便最后核查答案。

前 3 格是更新路径,后 3 格是请求路径。文档更新时可以提前算向量;用户提问时才知道身份和问题,不能把权限交给提前算好的向量来保证。

生成模型拿到的也不应该只是一串段落。至少要带可引用的 ID、版本和原文位置。这样模型说错了,我们才分得清:材料没找到、找错了版本,还是材料在眼前却读错了。

先从关键词检索开始

第一步做什么 能回答的工程问题 暂时不解决什么
关键词匹配 + 当前版本/权限过滤 数据是否进来了、限制是否生效 同义改写和复杂语义
再加 embedding 检索 问法不同但含义相近时,是否找得更全 数字正确性、权限、引用真实性
在少量候选(candidate)上重排(reranking) 前几段是否更贴近当前问题 不在候选里的证据
接生成模型 能否把证据组织成清楚的回答 系统是否允许看这份文档

例如,文档用“截止日期”,用户问“最晚哪天报名”,简单的词项匹配可能漏掉它。这时值得加入向量检索,比较它能否找回同义表达。可如果搜到的一直是旧版,首先要修的是更新流程,而不是换模型。

选择模型时,我们比较同一份文档快照、同一批问题、同一上下文预算。否则多塞几倍文字带来的收益,很容易被误写成 encoder 更好。

这 3 篇怎么读

  1. 本篇确定要回答什么、哪些错误不能接受。
  2. 文档怎么进来,证据怎么找:版本、权限、切块、两路召回和上下文预算;附可运行 Python。
  3. 答案有引用,就算答对了吗:证据不足、来源冲突、拒答与回归测试。我们先只处理文本,不把图片理解也算进来。

代码只用 Python 标准库。它让你看见每一步输入输出,不模拟一个已经训练好的检索器,也不声称测过模型回答质量。

第一版要通过哪些检查?

第一版先看这 4 种情况:

  • 规则更新后,不再把旧版当成当前依据。
  • 换成没有权限的用户,私有文档不进入模型上下文。
  • 删掉支持答案的段落,系统能指出依据不足。
  • 检索服务故障时,返回故障状态,不误报成“知识库里没有答案”。

这些检查通过后,再接生成模型,比较回答质量、延迟和成本。这样遇到错误时,至少知道该从哪一步查起。

返回工程实践 · 先补检索原理

本页术语 2
检索 retrieval
从外部语料里找出相关内容
候选 candidate
召回阶段捞出来、等待精排挑选的内容