AI-03 连接知识:构建 RAG 知识库¶
让模型先查资料、再回答,并给出可以核对的来源¶
RAG 的价值不是让模型什么都知道,而是让回答有依据
通用大模型不一定了解学校最新办事流程、项目内部文档或课程资料。即使模型能够生成通顺的回答,也可能遗漏条件、混淆版本或虚构细节。
RAG(Retrieval-Augmented Generation,检索增强生成)会先从指定知识资料中检索相关片段,再把片段连同问题交给大模型生成回答。用户不仅能看到回答,还能查看引用来源,判断回答是否可信。
本节以“校园办事指南问答”为例,完成文档整理、文本分块、向量化、相似度检索、带来源回答和固定问题评测。学生也可以替换为课程资料、项目使用手册、设备维护说明或其他有明确来源的知识场景。
本节学习目标
理解 RAG 与模型训练的区别,建立“文档 → 分块 → 向量 → 检索 → 生成 → 引用”的基本流程,完成一个能够拒绝无依据问题、展示来源并支持知识更新的最小知识库。
返回上一节:实现流式问答 返回扩展篇导读 进入下一节:智能生成、分类与推荐
🎯 本节完成后,你要交付¶
| 成果 | 要求 |
|---|---|
| RAG 场景说明 | 明确目标用户、知识范围、允许回答和拒绝回答的边界 |
| 知识来源清单 | 每份资料有标题、来源、版本、更新时间和访问权限 |
| 文档入库流程 | 能将资料清理、分块、向量化并保存元数据 |
| 检索问答接口 | 能检索相关片段,基于片段生成回答并返回引用 |
| 知识库页面 | 用户可以提问、查看回答、来源和“无法确认”提示 |
| 评测记录 | 使用固定问题检查检索命中、回答依据和拒答效果 |
| 更新与降级方案 | 资料更新可重新入库,模型不可用时仍可展示检索结果 |
RAG 属于选学功能
不要为了搭建知识库推迟核心业务、测试和部署。第一次实践只选择一个范围小、来源清楚、能够稳定验证的知识场景。
一、RAG 解决什么问题¶
1. 直接问模型的局限¶
假设用户提问:
通用模型可能:
- 不知道本校的具体规定;
- 使用其他学校的经验进行推测;
- 引用已经过期的流程;
- 给出听起来合理但没有来源的数字;
- 无法告诉用户答案来自哪份材料。
RAG 会先检索学校提供的真实资料:
2. RAG 不是模型训练¶
| 方式 | 做了什么 | 适合解决的问题 |
|---|---|---|
| 提示词 | 在本次请求中说明任务和规则 | 控制回答方式 |
| RAG | 每次回答前检索外部知识片段 | 连接可更新、可引用的资料 |
| 微调 | 使用样例调整模型行为 | 固定表达风格或任务模式 |
| 重新训练 | 改变模型内部参数和知识 | 通常不属于课程项目范围 |
把文档放进知识库不会自动“训练”模型。RAG 的知识仍然保存在项目的文档和向量存储中,需要时再检索。
3. 适合课程项目的 RAG 场景¶
| 项目 | 知识来源 | 问答示例 |
|---|---|---|
| 校园办事平台 | 办事指南、管理制度 | “补办学生证需要哪些材料?” |
| 图书管理系统 | 借阅规则、服务说明 | “图书逾期后还能续借吗?” |
| 宿舍报修系统 | 报修指南、常见故障说明 | “停水应该选择哪个报修类型?” |
| 课程学习平台 | 教学大纲、实验手册 | “实验报告需要提交哪些文件?” |
| 软件项目 | README、接口和部署文档 | “怎样初始化数据库?” |
| 设备管理系统 | 设备说明书、操作规范 | “设备启动前要检查什么?” |
4. 不适合的场景¶
- 资料来源不明确,无法判断真假;
- 文档中包含不能上传或不能被当前用户查看的数据;
- 只需要精确字段查询,SQL 就能可靠完成;
- 需要实时库存、余额或订单状态,却只检索旧文档;
- 问答会直接替代医疗、法律或财务专业判断;
- 资料频繁变化,但项目没有更新机制;
- 团队无法准备固定问题验证回答。
结构化数据优先使用业务查询
“我的报修处理到哪一步”应查询业务数据库并校验当前用户,而不是把报修记录做成公开知识库。RAG 更适合非结构化说明文档。
二、设计知识范围与回答边界¶
1. 填写 RAG 任务卡¶
| 项目 | 内容 |
|---|---|
| 功能名称 | 【填写】 |
| 目标用户 | 【谁会提问】 |
| 当前问题 | 【查资料时有什么困难】 |
| 知识主题 | 【只覆盖哪些主题】 |
| 资料来源 | 【文件、网页或项目文档】 |
| 更新责任人 | 【谁确认资料和版本】 |
| 允许回答 | 【哪些问题可以回答】 |
| 必须拒答 | 【哪些问题超出范围】 |
| 引用方式 | 【标题、章节、页码、链接】 |
| 权限规则 | 【谁能检索哪些资料】 |
| 降级方式 | 【模型不可用时如何继续】 |
| 验证问题 | 【准备哪些有答案和无答案的问题】 |
2. 示例:校园办事指南问答¶
3. 建立知识来源清单¶
| 文档编号 | 标题 | 来源 | 版本 | 更新时间 | 权限 | 状态 |
|---|---|---|---|---|---|---|
| DOC-001 | 学生证补办指南 | 学工处 | 2026版 | 2026-03-01 | 公开 | 有效 |
| DOC-002 | 教室借用办法 | 教务处 | V2.1 | 2026-02-15 | 公开 | 有效 |
| DOC-003 | 实验室设备借用办法 | 实验中心 | 2026版 | 2026-04-10 | 校内 | 有效 |
每份资料至少需要确认:
- 来源是否可靠;
- 是否有权保存和展示;
- 当前版本是否有效;
- 哪些用户可以访问;
- 引用链接是否可用;
- 资料过期后由谁更新或下架。
不要把“网上搜到的内容”直接当作知识库
RAG 能找到某段文字,不代表文字本身正确。知识质量首先取决于资料来源,然后才是分块、向量和模型。
三、理解 RAG 的两条流程¶
RAG 包含“知识入库”和“用户问答”两条流程。
1. 知识入库流程¶
入库通常在管理员上传或资料更新时执行,不需要用户每次提问都重新处理全部文档。
2. 用户问答流程¶
3. 最小系统结构¶
模型调用可以分成两类:
| 调用 | 输入 | 输出 |
|---|---|---|
| Embedding | 文本 | 一组浮点数向量 |
| 文本生成 | 问题 + 检索片段 | 最终自然语言回答 |
生成模型和向量模型承担不同任务,不要把聊天接口返回的文字当作向量。
四、准备并清理知识文档¶
1. 第一版选择简单格式¶
建议优先使用:
- Markdown;
- TXT;
- 能稳定提取文本的 DOCX;
- 文字型 PDF。
扫描版 PDF 只有图片,需要 OCR 才能提取文字。复杂表格、双栏排版、页眉页脚和脚注也可能导致文本顺序混乱。第一次实践可以先把少量可信资料人工整理成 Markdown。
2. 清理文档¶
可以删除或规范:
- 重复页眉、页脚和页码;
- 导航栏、版权栏等无关内容;
- 多余空格、空行和乱码;
- 重复章节;
- 已废止内容;
- 与问答范围无关的附件。
需要保留:
- 标题和章节层级;
- 条款编号;
- 时间、地点、条件和例外;
- 表格中的关键含义;
- 来源、版本和更新时间;
- 可以返回给用户的引用链接。
3. 文档清理记录¶
五、把文档切成可检索片段¶
1. 为什么不能整份文档直接检索¶
一份几十页的文档包含多个主题。整份生成一个向量,会把不同主题混在一起;整份发送给模型,也可能超过上下文限制并增加费用。
因此需要将文档切成若干 Chunk(片段):
2. 分块原则¶
- 优先按标题、段落和条款分块;
- 一个片段尽量只表达一个相对完整的主题;
- 不在一句话或一项规则中间切断;
- 片段要保留必要的章节标题;
- 相邻片段可以保留少量重叠内容;
- 片段过短会缺少上下文,过长会混入无关内容;
- 使用固定测试问题反复调整,而不是只追求某个长度数字。
3. 简单分块示例¶
原文:
片段 1:
片段 2:
4. 片段元数据¶
每个片段不能只保存正文,还应保存:
| 字段 | 作用 |
|---|---|
documentId |
关联原文档 |
chunkIndex |
保持原文顺序 |
title |
文档标题 |
section |
章节或条款 |
content |
片段正文 |
sourceUrl |
用户可核对的来源 |
version |
确认知识版本 |
visibility |
访问权限 |
embeddingModel |
记录向量模型 |
contentHash |
判断内容是否变化 |
引用和知识更新都依赖这些元数据。
六、生成并保存文本向量¶
1. 什么是 Embedding¶
Embedding 会把文本转换成一组数字:
语义相近的文本,其向量通常也更接近。用户提问后,可以比较“问题向量”与“片段向量”,找出可能相关的资料。
2. 定义向量客户端¶
如果所选平台提供 OpenAI 兼容的 /v1/embeddings 接口,请求通常包含模型和文本:
常见响应结构示意:
必须阅读所选平台文档
接口路径、字段、批量能力、向量维度和模型名称可能不同。应沿用第一节的后端密钥、超时、状态码和安全日志方案,不要根据示例猜测平台实现。
3. 向量模型必须保持一致¶
以下两类文本必须使用同一个向量模型:
- 入库时的知识片段;
- 查询时的用户问题。
更换向量模型后,原有向量通常不能继续混用,应重新为全部片段生成向量。还需要检查向量维度是否一致。
4. 第一版怎样保存向量¶
| 方案 | 优点 | 局限 | 适用情况 |
|---|---|---|---|
| 内存列表 | 最容易理解 | 重启丢失,不适合更新 | 极小演示 |
| MySQL JSON | 复用已有数据库 | 需要在 Java 中逐条计算 | 小型课程知识库 |
| 专用向量数据库 | 检索能力完整 | 增加部署和学习成本 | 资料较多的进阶项目 |
| 数据库向量扩展 | 数据集中管理 | 依赖具体数据库能力 | 已熟悉相关技术的团队 |
课程第一次实践可以将少量向量保存为 JSON,在 Java 中计算余弦相似度。目标是理解完整 RAG 流程,而不是一开始搭建复杂基础设施。
七、设计最小知识库数据表¶
还应根据真实项目考虑:
- 删除文档时怎样删除关联片段;
- 管理员是否可以停用旧文档;
- 是否保留历史版本;
- 校内资料怎样限制访问;
- 入库失败时是否保留半成品数据。
不要先删旧数据再重新入库
如果新版本处理到一半失败,先删除旧知识会导致整个资料不可用。更稳妥的做法是:先生成并验证新版本,成功后再切换状态并清理旧版本。
八、完成相似度检索¶
1. 余弦相似度¶
余弦相似度用于比较两个向量方向是否接近:
Java 示例:
2. 检索结果对象¶
3. 最小检索流程¶
其中:
topK表示最多取多少个片段;minimumScore表示最低相关度;- 两者都应通过固定问题调试;
- 必须先按用户权限过滤候选文档;
- 不能先检索所有私有资料,再在返回页面时隐藏来源。
相似度分数没有通用及格线
不同向量模型、语言、分块方式和资料类型的分数分布不同。不要照抄一个固定阈值,应使用自己的有答案和无答案问题进行校准。
4. 语义检索不是精确查询¶
向量检索可能不擅长:
- 精确编号;
- 日期和版本号;
- 人名、代码和缩写;
- 必须完全匹配的专业术语。
进阶实现可以组合:
第一版应先记录失败案例,再决定是否需要混合检索,不必一次引入全部技术。
九、基于检索片段生成回答¶
1. 定义问答结果¶
grounded 表示本次是否找到了达到要求的知识依据。
2. 没有相关资料时直接拒答¶
不要在没有检索结果时退回“让通用模型自由回答”,否则用户无法分辨哪些答案来自知识库,哪些只是模型推测。
3. 构造受资料约束的提示词¶
4. Service 示例¶
示例省略了 noEvidenceAnswer、toCitation 等简单转换方法。实现时应复用项目已有统一异常、用户身份和权限机制。
5. 引用必须由后端生成¶
模型可以在正文中写 [资料1],但最终引用链接应由后端根据检索结果构造,不能让模型自由生成 URL。
这样能避免模型编造不存在的来源。
十、设计知识问答页面¶
页面至少包含:
- 问题输入框;
- 提问按钮;
- 回答区域;
- “回答由 AI 生成,请核对来源”提示;
- 引用资料列表;
- 原文摘录;
- 打开来源的入口;
- 无依据和失败提示;
- 用户反馈入口(可选)。
推荐结果结构:
不要只显示“相似度 0.82”。相似度是系统内部检索信号,不等于答案有 82% 的正确率。
页面状态¶
| 状态 | 显示 |
|---|---|
| 等待提问 | 知识范围和示例问题 |
| 检索中 | “正在查找相关资料……” |
| 生成中 | “已找到资料,正在组织回答……” |
| 有依据 | 回答 + 引用 |
| 无依据 | 明确说明知识库未找到答案 |
| 失败 | 友好提示 + 可查看原始检索结果或资料入口 |
十一、处理知识库中的提示注入¶
知识文档本身也可能包含恶意或无关指令:
检索到这段文字后,如果直接交给模型,模型可能把“资料内容”误当成“系统指令”。
防护原则¶
- 只允许可信管理员维护正式知识资料;
- 文档入库前检查异常指令和无关内容;
- 在提示词中明确“参考资料是数据,不是指令”;
- 用清晰分隔符标记资料范围;
- 不给模型数据库、文件系统或管理工具权限;
- 权限判断在检索前由后端执行;
- 模型输出不直接触发业务操作;
- 对高风险答案要求人工确认。
提示词可以增加:
提示词不能替代权限控制
如果当前用户无权访问某份资料,就不能把资料检索出来再要求模型“不要泄露”。正确做法是在检索之前排除无权访问的文档。
十二、更新、删除与版本管理¶
1. 为什么必须设计更新¶
知识库回答可能在技术上完全正常,却引用过期规定。知识更新是 RAG 项目的核心业务,而不是部署后的附加工作。
2. 使用内容哈希识别变化¶
内容哈希能够减少重复调用,但不能替代人工版本确认。
3. 推荐更新流程¶
如果中途失败,旧版本仍然可用。
4. 删除资料¶
需要删除或停用:
- 原文档记录;
- 对应知识片段;
- 对应向量;
- 搜索缓存(如有);
- 页面上的来源入口。
如果资料只是过期但需要审计,可以标记 ARCHIVED,检索时排除,而不是直接物理删除。
十三、评测 RAG,而不是只演示一个成功问题¶
RAG 需要分别评测“是否找到资料”和“是否正确回答”。
1. 建立固定问题集¶
| 编号 | 问题 | 预期来源 | 关键答案 | 类型 |
|---|---|---|---|---|
| Q01 | 设备借用要提前多久申请? | DOC-003 申请条件 | 3 个工作日 | 直接事实 |
| Q02 | 借用设备要提交哪些材料? | DOC-003 所需材料 | 三项材料 | 多要点 |
| Q03 | 校外人员能否直接借用? | DOC-003 适用范围 | 按原文判断 | 条件限制 |
| Q04 | 食堂今天有什么菜? | 无 | 应拒答 | 超出范围 |
| Q05 | 我的申请通过了吗? | 无结构化记录 | 引导查询业务系统 | 权限/实时数据 |
问题集至少包含:
- 能直接找到原文的问题;
- 使用同义表达的问题;
- 需要保留多个条件的问题;
- 资料没有答案的问题;
- 超出用户权限的问题;
- 两份资料可能冲突的问题;
- 容易诱导模型猜测的问题。
2. 检索评测¶
对每个有答案问题检查:
- 正确片段是否出现在 Top K;
- 片段是否包含回答所需完整条件;
- 无关片段是否过多;
- 分块是否切断了关键规则;
- 阈值是否把正确片段过滤掉。
如果正确片段没有被找到,先修复资料、分块、向量或检索,不要只修改最终提示词。
3. 回答评测¶
| 维度 | 检查问题 |
|---|---|
| 有依据 | 每个关键事实能否在引用片段中找到 |
| 完整 | 是否遗漏条件、例外和时间范围 |
| 忠实 | 是否添加资料中不存在的事实 |
| 引用正确 | 引用编号是否指向真实相关资料 |
| 拒答 | 无依据时是否明确说明无法确认 |
| 表达 | 是否清晰、简洁、适合目标用户 |
4. 评测记录¶
不要只记录“回答看起来不错”。固定问题和来源依据才能支持回归测试。
十四、失败与降级方案¶
| 失败情况 | 处理方式 |
|---|---|
| 文档解析失败 | 不发布该版本,提示管理员人工检查 |
| 向量生成失败 | 保留旧版本,不产生半成品知识 |
| 问题向量失败 | 提示知识检索暂不可用 |
| 没有相关片段 | 明确拒答,提供资料目录或人工咨询入口 |
| 生成模型失败 | 展示检索到的原文片段和来源 |
| 引用链接失效 | 显示标题、章节和摘录,记录待修复 |
| 用户无权访问 | 不检索、不返回、不记录正文到普通日志 |
| 知识版本过期 | 停用旧版本并显示维护提示 |
最有价值的降级是:
RAG 不应成为查看正式资料的唯一入口。
十五、🤖 让 AI 帮你设计 RAG,但必须核对¶
人工必须核对:
- 资料是否真实、有效并允许使用;
- 文档提取后是否与原文一致;
- 分块是否保留完整规则和章节;
- 入库和查询是否使用同一向量模型;
- 权限是否在检索前执行;
- 引用是否由真实元数据生成;
- 无依据问题是否拒答;
- 资料更新后是否完成回归测试。
十六、常见问题与修正方法¶
| 常见问题 | 后果 | 修正方法 |
|---|---|---|
| 把 RAG 说成训练模型 | 错误理解技术过程 | 区分外部检索与模型参数 |
| 资料来源不可靠 | 回答有依据但依据本身错误 | 建立来源、版本和责任人清单 |
| 整份文档生成一个向量 | 不同主题混在一起 | 按章节和语义分块 |
| 片段切得过碎 | 缺少条件和上下文 | 合并相关条款并保留标题 |
| 入库和查询使用不同模型 | 向量不可比较 | 统一模型并记录版本 |
| 先检索私有资料再隐藏 | 内容已经可能泄露给模型 | 检索前执行权限过滤 |
| 没有结果时让模型自由回答 | 产生无依据答案 | 明确拒答或返回资料目录 |
| 让模型生成来源链接 | 出现虚假引用 | 后端根据元数据生成引用 |
| 只测试一个成功问题 | 无法发现检索和拒答问题 | 建立固定评测问题集 |
| 更新前删除旧知识 | 新版本失败后无资料可用 | 新版本验证成功后再切换 |
| 只优化提示词 | 掩盖检索没有命中的问题 | 分别评测检索与回答 |
| 用相似度表示正确率 | 误导用户 | 将分数作为内部排序信号 |
十七、提交前自查¶
知识与权限¶
- 知识范围明确,不试图回答所有问题;
- 每份资料有可靠来源、版本、更新时间和责任人;
- 已确认资料允许保存、处理和展示;
- 私有资料在检索前按当前用户权限过滤;
- 结构化实时数据仍通过业务接口查询。
入库与检索¶
- 文档提取结果已经人工核对;
- 分块保留完整语义、章节和必要条件;
- 每个片段保存来源和版本元数据;
- 入库和查询使用同一个向量模型;
- 更换向量模型时会重新生成全部向量;
- Top K 和最低相关度通过固定问题调试;
- 资料更新失败时旧版本仍可使用。
回答与引用¶
- 没有相关资料时明确拒答;
- 回答只依据检索片段,不自由补充事实;
- 引用标题、章节和链接由后端生成;
- 页面能够查看原文摘录和来源;
- 模型失败时可以展示检索片段;
- 模型输出不会直接执行高风险业务操作。
测试与交付¶
- 问题集包含有答案、无答案、冲突和越权问题;
- 已分别记录检索命中和回答质量;
- 知识更新后会重新执行固定问题;
- README 说明知识来源、配置、入库和更新方法;
- 演示包含一次正确回答和一次正确拒答;
- API Key、私有文档和用户问题没有泄露到仓库或日志。
本节小结¶
一个可信的 RAG 功能不是“上传文件后可以聊天”,而是一条可以检查和维护的知识链:
可信资料 → 清理与分块 → 统一向量模型 → 权限过滤 → 相似度检索 → 有依据生成 → 后端引用 → 固定问题评测 → 版本更新
完成本节后,项目已经能够使用自己的知识资料回答问题,并在没有依据时诚实拒答。下一节将介绍怎样把模型能力进一步嵌入具体业务,用于文本生成、分类和推荐,同时保持人工确认与业务规则。