RAG:先找证据,再回答
亲手做一个小型检索器,理解切块、召回与上下文拼接。
学完这一课,你将能够
- 区分检索与生成阶段
- 保存文档来源和版本
- 解释 Top-k 与召回质量的关系
学习目标
- 分清检索增强生成中的“检索”和“生成”。
- 为文本片段保存来源、版本和可定位标识。
- 实现一个离线词项检索器,观察召回失败。
前置要求:Python 数据结构与上下文预算。 本节使用人工标签演示检索,不需要向量数据库或模型 API。
为什么需要 RAG
模型可能不知道你的公司政策,也不会自动获取刚更新的文档。 检索增强生成通常先从受控资料中找到相关片段,再把片段交给生成步骤。 回答可以引用这些来源,方便用户核查。
RAG 不会自动保证事实正确。 错误可能来自文档过时、切块丢失语境、没有召回正确片段,或生成时误读证据。 排查时先看检索结果,再看生成结果,避免一律归因于提示词。
数据流分成两个阶段
建立索引:收集文档 → 提取文本 → 切块 → 保存来源 → 建立检索表示。
回答问题:理解查询 → 检索 → 选择证据 → 生成答案 → 检查引用。
第一个阶段通常在资料新增或更新时执行,第二个阶段在用户提问时执行。 资料权限必须在检索和取回原文时保持一致,不能先检索所有人的文档再让模型自行过滤。
切块不是平均切字符
按章节、标题和语义边界切分,通常比任意固定长度更容易保留意义。 例如“不得报销”与后面的例外条件不应被拆得毫无关联。 片段可以保存所属标题,并保留到原文位置的映射。
建议至少保存:chunk_id、document_id、version、text 和来源位置。
文档更新后,应替换旧版本的索引,或明确标记有效时间。
从最简单的检索开始
保存为 retrieve.py 并运行。
这里查询也使用标签列表,避免把中文分词细节混进第一版实现。
CHUNKS = [
{
"id": "expense-v2-1", "source": "报销制度", "version": "v2",
"text": "报销申请需在消费后 30 天内提交,并附有效发票。",
"terms": ["报销", "时间", "发票"],
},
{
"id": "leave-v1-1", "source": "请假制度", "version": "v1",
"text": "年假申请需提前 3 个工作日提交。",
"terms": ["年假", "申请", "时间"],
},
{
"id": "remote-v1-1", "source": "远程办公指南", "version": "v1",
"text": "远程办公需要在团队日历中标记工作地点。",
"terms": ["远程", "办公", "日历"],
},
]
def retrieve(query_terms, top_k=2):
query = set(query_terms)
ranked = []
for chunk in CHUNKS:
overlap = query.intersection(chunk["terms"])
score = len(overlap)
if score > 0:
ranked.append({**chunk, "score": score})
ranked.sort(key=lambda item: (-item["score"], item["id"]))
return ranked[:top_k]
for query in [["报销", "时间"], ["远程"], ["餐补"]]:
results = retrieve(query)
print("查询:", query)
for result in results:
print(result["id"], result["score"], result["text"])
if not results:
print("没有相关证据")“报销、时间”应把报销制度排在请假制度前面。 “餐补”没有匹配内容,应返回空结果,而不是随机挑一条。 这里的分数只是匹配词数量,不是事实正确率或置信度。
再理解向量检索
Embedding 把文本映射成可计算相似度的向量,适合匹配不同措辞但语义相近的内容。 词项检索擅长精确名称与关键词,向量检索擅长语义关联,实际可组合使用。 检索器应该用自己的问题集评估,而不是因为用了向量数据库就假设更好。
top_k 表示最多取多少条候选。
过小可能遗漏证据,过大可能引入无关内容并挤占上下文。
必要时对候选再次排序,或根据问题把相邻片段一起取回。
练习与验收
新增一份“差旅政策”,保存标题、版本、来源 ID 和标签。 写六个查询,其中至少两个没有答案。
- 每个有答案问题的目标证据都进入前两条结果。
- 未知问题不会被强制匹配。
- 输出保留来源和版本。
- 能指出一种因为关键词不一致导致的漏召回。
延伸阅读
- Microsoft:AI Agents for Beginners,查看知识检索相关实践。
- DeepLearning.AI:课程目录,选择检索与 RAG 课程补充实验。
下一课区分知识库与记忆,避免把所有历史混成一个大文本。
让这一课,真正成为你的收获
完成练习后标记完成,也可以随时回来复习。
笔记与进度保存在当前浏览器,无需登录