📖 本章学习目标
- 解释大语言模型的三项核心局限,以及 RAG 如何针对性地解决它们
- 画出 RAG 的经典三阶段工作流,并描述每个阶段的职责
- 区分 RAG、Fine-tuning 和 Long Context 三种方案的适用边界
- 判断一个业务场景是否适合采用 RAG 方案
大语言模型发展至今,无论是写代码、翻译文档,还是总结长文、推理计算,都早已不在话下。尽管它们展现出的卓越能力时常让我们叹为观止,但相信你也一定遇到过AI回答不准确甚至AI胡说八道的情况。这在某些情况下(比如写段子、创意)是无关紧要的,但是在一些场景里(比如法律、公司内部资料)是不可接受的。然而,编造一个看起来合理但完全错误的答案,是大语言模型底层工作原理决定决定的。
解决这个问题的其中一种方案就是使用RAG技术。本章将从 LLM 的固有局限出发,帮你建立对 RAG 的直觉理解。
一、大语言模型的局限性
1. 知识与信息滞后缺失
LLM 的知识停留在训练数据收集的截止日期,有明确的训练数据边界。如果你的公司内部在上周更新了一些文档或者世界近期发生了一些事情,模型对此都是一无所知的。
(1)信息更新滞后
对于快速迭代的技术栈,比如前端框架每几个月一个大版本,模型的"知识快照"迅速过时。React 19 发布后,模型仍然按照 React 18 的 API 给出建议;TypeScript 5.0 引入了新的类型系统特性,模型却浑然不知。这种滞后本身不是 bug,而是 LLM 训练机制的必然结果。因为训练一次大型语言模型需要数千万美元的算力和数月时间,不可能每次知识库更新都重新训练。
在实际工程中,这意味着你不能依赖 LLM 回答任何涉及"最新"的问题。当开发者询问"Next.js 14 的 App Router 如何使用"时,如果模型的训练数据截止于 Next.js 13 时代,它会用旧版 Pages Router 的方式回答,或者直接承认自己不了解这个新功能。
(2)私有知识真空
公司内部的代码库、设计文档、会议纪要从未进入过公开训练语料,模型对这些内容完全陌生。这是企业应用 LLM 时面临的最大障碍。你的团队可能有上千份 Confluence 文档、数百个 Git 仓库、数万条 Slack 聊天记录,但这些私有知识对 LLM 来说都是空白。
即使你把所有内部文档整理成 PDF 发给 ChatGPT,它也只能处理有限的上下文窗口(目前通常是几万到百万 token),无法真正"记住"这些内容供下次对话使用。更重要的是,将敏感的内部文档上传到第三方服务存在严重的数据安全风险。
2. 幻觉问题
LLM 的本质是预测下一个 token 的概率分布,并非从事实数据库中检索答案。当它面对一个没有训练见过的具体问题时,不会诚实地回答"我不知道",而是根据语言模式"编造"一个听起来通顺的答案。这种现象被称为"幻觉"(Hallucination)。
typescript
// 幻觉示例:模型可能编造一个不存在的 API 方法
const answer = await llm.invoke("如何在 LangChain 中使用 createRAGPipeline?");
// 模型可能回复:"您可以使用 createRAGPipeline() 方法,它接受以下参数..."
// 但实际上这个方法根本不存在,这是模型根据命名惯例"推理"出来的幻觉
console.log(answer);
// 输出可能包含看似合理但完全虚构的代码示例
幻觉问题的根源在于 LLM 的训练目标。模型在预训练阶段学习的是"给定上文,预测下一个词最可能是什么",而不是"给定问题,从事实库中检索正确答案"。当模型遇到训练数据中未覆盖的内容时,它会基于统计规律生成一个"看起来像正确答案"的文本,但这个答案可能与事实完全不符。
在企业场景中,幻觉的危害被放大。假设你构建了一个内部技术支持机器人,员工询问"如何重置测试环境的数据库密码"。如果模型编造了一套看似合理的操作步骤,而这套步骤实际上是错误的,可能导致测试环境瘫痪,甚至误操作生产环境。
研究表明,即使是当下最顶流的大型模型,在开放域问答任务中的幻觉率也能达到10%甚至更高。对于需要高准确率的业务场景,这个数字是不可接受的。
3. 数据无法溯源
LLM 给出回答时,你无法知道这个结论来自哪份文档、哪个段落。对于法律、医疗、金融等对信息准确性有严格要求的领域,不可溯源意味着不可信赖。
想象一下这样的场景:律师询问 AI 助手"根据《民法典》第 584 条,违约损害赔偿的范围如何确定"。AI 给出了详细的解答,但律师无法验证这个解答是否真的基于法条原文,还是模型根据自己的理解进行了演绎。在法律实践中,每一个论断都需要有明确的法律依据,无法溯源的回答无法被采信。
同样的问题也出现在医疗诊断辅助、财务审计、合规检查等场景。在这些领域,"答案是什么"和"答案从哪里来"同等重要。医生需要知道 AI 给出的诊断建议基于哪些医学文献,审计师需要确认财务分析引用的数据来源,合规官需要追溯监管要求的原始条款。
⚠️ 注意
幻觉问题并非 RAG 能完全消除的,在《第8章:RAG 的局限性及应对策略》中会详细讨论 RAG 场景下幻觉依然存在的场景。RAG 的作用是大幅降低幻觉概率,同时提供可溯源的信息来源。
那么,RAG是如何应对这三个局限的呢?大致的方式如下:
| LLM 的局限 | RAG 的应对方式 | 技术实现要点 |
|---|---|---|
| 知识截止日期 | 从外部知识库实时检索最新文档 | 向量数据库支持增量索引,文档更新后几分钟内即可被检索到 |
| 幻觉问题 | 用检索到的真实文档内容约束模型生成 | Prompt 中明确要求"仅基于提供的参考资料回答",减少自由发挥空间 |
| 无法溯源 | 检索结果天然包含来源元数据,可标注引文 | 每条检索结果保留 document_id、page_number、source_url 等元数据 |
二、RAG 的核心思想
1. 一句话定义
RAG(Retrieval-Augmented Generation,检索增强生成)的核心思路很简单:在 LLM 回答问题之前,先从外部知识库中检索相关信息,把这些信息连同问题一起交给模型。
打个比方,没有 RAG 的 LLM,就像是一个参加"闭卷考试"的学霸,遇到知识盲区只能凭记忆联想,可能会拼凑出错误的答案;而搭载了 RAG 的 LLM,则变成了一场"开卷考试"的考生。当遇到问题时,他不需要死记硬背,而是先翻阅桌上的教科书和参考资料,找到最相关的章节,再基于这些准确的信息整理出逻辑清晰的答案。
当然,这个开卷给的资料是有几个关键点的:
第一,参考资料不是随便给的,而是通过语义相似度算法精准检索出来的。系统需要理解用户问题的含义,然后在海量文档中找到最相关的片段。这涉及到自然语言理解、向量空间模型、相似度计算等一系列技术,后续章节会逐一展开。
第二,学霸并不是简单地复述参考资料,而是要进行理解和综合。如果检索到三段相关的文档,模型需要判断哪些信息是冗余的,哪些是互补的,然后用连贯的语言组织成答案。这个过程考验的是模型的阅读理解能力和语言生成能力。
第三,参考资料的质量直接决定了答案的质量。如果检索到的文档与问题无关,或者文档本身包含错误信息,那么即使模型再强大,也无法给出正确答案。这就是为什么 RAG 系统中"检索"环节的重要性不亚于"生成"环节。
2. RAG经典三阶段工作流
(1)检索阶段:从知识库中找到相关信息
这个阶段的核心任务是将用户的自然语言问题转化为查询,在知识库中找到语义最相关的文档片段。
检索的质量取决于三个要素:
首先是知识库的组织方式。传统的关键词搜索(如 Elasticsearch)基于词频和倒排索引,适合精确匹配场景。但对于语义理解,比如用户问"怎么部署代码",而文档中用的是"发布流程"这个词,关键词搜索可能失效。RAG 通常采用向量搜索,将文本转换为高维向量,通过计算向量距离来判断语义相似度。这种方式能够捕捉到词汇不同但含义相近的情况。
其次是检索策略的选择。最简单的策略是 Top-K 检索,即返回与问题最相似的 K 个文档片段。但这种策略存在两个问题:一是可能检索到大量冗余信息,二是可能遗漏重要但不那么相似的内容。进阶的策略包括混合检索(结合关键词和向量搜索)、多路召回(从不同索引中分别检索再合并)、重排序(先用快速算法召回候选集,再用精细算法重新排序)等。
最后是检索粒度的控制。是把整篇文档作为检索单元,还是将文档切分成小片段?粒度太粗会导致检索结果包含大量无关内容,占用宝贵的上下文窗口;粒度太细则可能丢失上下文信息,导致模型无法理解片段的完整含义。这个问题在第 5 章会有专门讨论。
(2)增强阶段:将检索结果与问题组装成 Prompt
这个阶段看似简单,无非是把检索到的文档片段拼接到 Prompt 中。但实际上有很多工程细节需要考虑。
第一个挑战是上下文窗口的限制。即使是最先进的 LLM,上下文窗口也有上限(目前比较支持比较长的上下文是百万级别)。如果检索到 10 个文档片段,每个片段 1000 token,再加上系统指令和用户问题,很容易超出限制。解决方案包括:限制检索数量、对检索结果进行压缩、使用支持更长上下文的模型等。
第二个挑战是噪声干扰 。检索到的文档片段不一定都与问题高度相关。如果 Prompt 中包含大量无关信息,模型可能被误导,产生所谓的 "Lost in the Middle" 现象,即模型倾向于关注 Prompt 开头和结尾的内容,而忽略中间部分。解决方法是在组装 Prompt 前对检索结果进行过滤或重排序,只保留最相关的片段。
第三个挑战是Prompt 模板的设计。如何组织系统指令、参考资料、用户问题的顺序?如何标注引用来源?如何处理多个参考资料之间的矛盾?这些问题没有标准答案,需要根据具体业务场景进行调整。第 11 章会深入探讨 Prompt 工程的技巧。
(3)生成阶段:LLM 基于增强后的 Prompt 生成答案
这是 RAG 流程的最后一步,也是最容易被误解的一步。很多人认为既然已经把参考资料给了模型,模型就应该原封不动地复述这些资料。但实际上,模型需要做的是理解和综合。
模型在这个阶段的任务包括:
- 信息抽取:从参考资料中提取与问题直接相关的信息
- 去重合并:如果多个参考资料提到相同的内容,需要进行整合而非重复罗列
- 逻辑推理:如果答案需要多步推理,模型需要基于参考资料进行推导
- 语言组织:用流畅、连贯的自然语言组织答案,而不是简单拼接句子
- 引用标注:在答案中标明信息来源,方便用户追溯
需要注意的是,模型在生成答案时仍然有一定的自由度。即使提供了参考资料,模型也可能加入自己的理解或推断。为了控制这种行为,需要在 Prompt 中明确指令,比如"严格基于提供的参考资料回答,不要添加额外信息"或"如果参考资料中没有相关信息,请明确说明"。
3. 一个极简的"伪 RAG"演示
下面这段代码展示了 RAG 的核心思想,虽然它用的是硬编码的"检索结果"而非真正的向量搜索,但能帮你直观理解三阶段的串联逻辑:
typescript
// 步骤 1:模拟知识库(实际项目中会从文件或数据库加载)
const knowledgeBase = [
"公司的部署流程分为三步:代码审查、预发环境验证、生产发布。",
"预发环境地址为 https://staging.example.com,需要 VPN 访问。",
"生产发布由 SRE 团队负责,需要提交 Jira 工单。",
];
// 步骤 2:检索阶段 ------ 找到与问题最相关的信息
async function retrieve(query: string): Promise<string[]> {
// 此处用简单的关键词匹配模拟检索
// 实际项目中会替换为向量相似度搜索(见第 2、3 章)
const keywords = query.toLowerCase().split(" ");
return knowledgeBase.filter((doc) =>
keywords.some((keyword) => doc.toLowerCase().includes(keyword))
);
}
// 步骤 3:增强阶段 ------ 组装 Prompt
function augment(query: string, docs: string[]): string {
// 为每条参考资料添加编号,便于后续引用
const context = docs
.map((doc, index) => `[参考资料 ${index + 1}] ${doc}`)
.join("\n");
return `你是一个企业知识库助手。请根据以下参考资料回答问题。
如果参考资料中没有相关信息,请明确说明"根据现有资料无法回答",不要编造答案。
## 参考资料
${context}
## 用户问题
${query}
## 你的回答`;
}
// 步骤 4:生成阶段 ------ 调用 LLM 生成答案
async function generate(prompt: string): Promise<string> {
// 实际项目中会调用如 OpenAI / Anthropic API
// 这里仅作示意
const response = await llm.invoke(prompt);
return response.content;
}
// 完整流程串联
async function rag(query: string): Promise<string> {
console.log("【检索】查找相关文档...");
const docs = await retrieve(query);
console.log(`找到 ${docs.length} 条相关文档`);
console.log("【增强】组装 Prompt...");
const prompt = augment(query, docs);
console.log("【生成】调用 LLM 生成答案...");
const answer = await generate(prompt);
return answer;
}
// 测试运行
const question = "预发环境的部署步骤是什么?";
const answer = await rag(question);
console.log("\n最终答案:", answer);
这段代码虽然简单,但已经包含了 RAG 的核心骨架。你可以尝试运行这段代码(需要配置 LLM API Key),观察不同问题下的检索效果和生成的答案质量。
后续章节会对每个阶段进行持续升级:
- 检索阶段:从关键词匹配走向向量搜索(第 2、3 章)、混合检索(第 9 章)
- 增强阶段:从简单拼接走向上下文压缩和智能组装(第 11 章)
- 生成阶段:从单次调用走向 Agent 循环和多轮对话(第 15 章)
三、RAG vs Fine-tuning vs Long Context
这是三个常被放在一起讨论的增强模型的技术方向,但它们解决的问题和适用场景截然不同。然而,对于很多初学者而言,刚接触这几个技术时会困惑于到底应该如何选择用 RAG、微调还是长上下文模型。要回答这个问题,需要先理解三者的本质差异。
1. RAG:动态知识注入
RAG 的核心价值在于将知识与模型解耦。知识存储在外部数据库中,模型在运行时动态检索。这种架构带来了几个显著优势:
知识更新的即时性:当你更新知识库中的文档后,只需重新生成该文档的 Embedding 并存入向量数据库,新的知识立即可被检索到。整个过程通常在几分钟内完成,无需重新训练模型。这对于快速变化的领域(如技术文档、新闻、政策法规)至关重要。
成本可控:RAG 不需要昂贵的 GPU 资源进行模型训练,只需要维护向量数据库和调用 LLM API。对于中小企业来说,这是最具性价比的方案。
可解释性强:每一条回答都可以追溯到具体的参考文档,用户可以验证答案的准确性。这在法律、医疗等对准确性要求高的场景中是刚需。
但 RAG 也有局限性。它只能利用检索到的局部信息,无法进行全局推理。如果问题需要综合整个知识库的信息(比如"统计所有产品文档中提到的错误码"),RAG 的 Top-K 检索会遗漏大量相关内容。此外,检索质量直接影响答案质量,如果检索失败,再强大的 LLM 也无能为力。
2. Fine-tuning:模型行为定制
Fine-tuning(微调)是在预训练模型的基础上,用特定领域的数据继续训练,让模型学会该领域的知识、风格或任务模式。
微调的典型应用场景包括:
- 风格适配:让模型学会用特定的语气、格式或术语回答问题。比如让客服机器人学会公司的标准话术,让代码助手遵循团队的代码规范。
- 任务专精:让模型擅长某类特定任务。比如训练一个专门做情感分析的模型,或者一个专门提取合同条款的模型。
- 领域知识内化:将某些高频使用的知识"固化"到模型参数中,避免每次都检索。比如医学术语、法律条文等专业领域的核心概念。
微调的优势:
- 响应速度快,无需检索环节
- 可以学习到复杂的模式和风格,不仅仅是知识记忆
- 对于固定不变的知识,微调比 RAG 更稳定
微调的劣势:
- 训练成本高,需要标注数据和 GPU 资源
- 知识更新困难,每次更新都需要重新训练
- 容易产生"灾难性遗忘",学会新知识的同时忘记旧知识
- 无法追溯答案来源,黑盒性质更强
💡 小贴士
微调不是用来"教模型新知识"的最佳方式。如果你只是想让它了解最新的产品手册,用 RAG 更合适。微调更适合让模型学会"如何回答问题",而不是"回答什么"。
3. Long Context:全量信息处理
Long Context(长上下文)是指支持超长输入窗口的 LLM,比如 GPT-5.5 Pro 和Claude Opus 4.7均支持 1M token(约50万汉字)。这意味着你可以把整本书、整个代码库一次性塞进 Prompt。
长上下文的适用场景:
- 全文分析:需要对整篇文档进行理解和分析,比如长文总结、文档对比、代码审查。
- 跨段落推理:答案需要综合文档中分散在多处的信息,RAG 的局部检索可能遗漏关键内容。
- 零样本学习:在 Prompt 中提供大量示例(Few-shot Learning),让模型通过上下文学习新任务。
长上下文的局限性:
- 成本高:长 Prompt 意味着更高的 API 调用费用
- 延迟大:处理数十万 token 的输入需要更长的推理时间
- "迷失在中间"现象:研究表明,当上下文过长时,模型倾向于关注开头和结尾的内容,而忽略中间部分。这意味着即使你把整本书塞进去,模型也不一定能充分利用所有信息。
- 无法动态更新:长上下文模型的知识仍然受限于训练数据,无法像 RAG 那样实时检索最新信息。
4. 三者对比总结
| 维度 | RAG | Fine-tuning | Long Context |
|---|---|---|---|
| 知识更新方式 | 更新知识库即可,即时生效 | 重新训练,周期长、成本高 | 无法更新,依赖模型训练数据 |
| 幻觉控制 | 答案受检索内容约束,幻觉率低 | 可能"记住"错误知识,幻觉中等 | 长文本中容易忽略关键信息,幻觉中高 |
| 可溯源性 | 天然支持引文标注 | 不支持,无法追溯答案来源 | 理论上可追溯,但长文本中难以精确定位 |
| 实施成本 | 中等(需维护向量数据库和检索管道) | 高(需标注数据、GPU 资源) | 低(仅需选择长上下文模型) |
| 响应延迟 | 增加检索环节,约 100-500ms | 与普通 LLM 调用相同 | 长 Prompt 导致延迟显著增加 |
| 适用知识类型 | 结构化/半结构化文档,频繁更新 | 固定的领域知识和风格 | 需要全局理解的长文档 |
| 典型应用场景 | 企业知识库、客服系统、文档问答 | 代码风格适配、角色扮演、专业术语 | 长文总结、多文档对比、代码审查 |
实际中,RAG 和 Fine-tuning 不是二选一的关系。在成熟的生产系统中,两者经常配合使用:RAG 负责注入时效性知识,Fine-tuning 负责让模型学会特定的指令遵循风格。典型的实践路径是:先用 RAG 解决知识新鲜度问题,观察系统表现,如果发现模型在某些固定模式上表现不佳(比如总是用错误的格式回答),再考虑用 Fine-tuning 优化。
四、RAG 的适用场景
1. 适合使用 RAG 的场景
(1)企业知识库问答
内部文档、SOP、技术 Wiki 数量庞大且持续更新,RAG 是最直接的方案。典型特征包括:
- 文档总量大(数百到数千份),人工检索效率低
- 文档更新频繁(每周都有新版本)
- 问题多样,无法预先定义所有问答对
- 需要追溯答案来源,确保准确性
典型案例:互联网公司的内部技术文档平台,包含成百上千篇的技术文章、API 文档、最佳实践指南。工程师可以通过自然语言提问,比如"如何使用公司的消息队列 SDK",系统自动检索相关文档并生成答案,同时标注引用来源。
(2)客服系统
产品手册、FAQ 是天然的结构化知识源,RAG 能让客服机器人基于最新产品文档回答。相比传统的关键字匹配客服,RAG 客服的优势在于:
- 能理解语义,即使用户表述与文档不完全一致也能匹配
- 能综合多段信息,给出更完整的答案
- 产品更新后,只需更新文档库,无需重新训练模型
典型案例:电商平台的智能客服,接入了产品说明书、退换货政策、常见问题解答等文档。用户询问"这款手机支持快充吗",系统检索产品规格文档,提取充电功率信息,生成准确回答。
(3)法律/医疗辅助
法规条文和医学文献有明确的权威来源,可溯源是第一优先级。这类场景的特殊要求包括:
- 答案必须有明确的出处,不能含糊其辞
- 对准确性要求极高,宁可回答"不知道"也不能出错
- 需要处理专业术语和复杂逻辑
典型案例:某律所的法律研究助手,接入了《民法典》、司法解释、判例库等法律文档。律师询问"合同中约定违约金过高,法院如何调整",系统检索相关法条和判例,生成带有引用的分析报告。
(4)代码库问答
团队代码在持续迭代,RAG 可以在开发者提问时检索相关代码片段辅助回答。应用场景包括:
- 新人入职时快速了解项目结构
- 开发过程中查询某个功能的实现方式
- Code Review 时理解某段代码的上下文
典型案例:某大型前端项目的智能助手,接入了项目的所有 TypeScript 文件、组件文档、API 定义。开发者询问"用户登录功能在哪里实现",系统检索相关的组件文件、路由配置、API 调用代码,给出定位和解释。
2. 不太适合使用 RAG 的场景
(1)纯创意写作
写小说、诗歌、营销文案等不需要外部知识的任务,直接用 LLM 即可。RAG 反而可能限制创造力,因为模型会被参考资料束缚,难以跳出既定框架。
(2)超低延迟场景
检索环节增加至少 100-500ms 延迟,对于实时对话游戏、高频交易等场景可能不适用。如果业务要求响应时间在 100ms 以内,RAG 的检索开销可能成为瓶颈。
(3)知识库高度同质化
如果所有文档内容高度相似(如大量模板化合同、标准化报告),检索精准度会急剧下降。向量搜索依赖语义差异来区分文档,如果文档之间差异太小,很难检索到真正相关的内容。
(4)需要全局理解的聚合分析
比如"统计所有文档中出现过的所有错误码"、"对比过去一年的政策变化趋势"这类需要遍历全库的问题,RAG 的 Top-K 检索会遗漏重要信息。这类任务更适合用 Long Context 模型直接处理全量数据,或者用传统的数据分析方法。
(5)知识高度结构化且查询模式固定
如果知识库是高度结构化的数据库(如 SQL 数据库),且用户的查询模式可以预先定义(如"查询某用户的订单"),直接用传统的数据查询更高效。RAG 适合处理非结构化或半结构化文档,对于结构化数据的精确查询并无优势。
FAQ
Q1:RAG 和搜索引擎有什么区别?
搜索引擎返回的是文档列表,用户需要自己阅读和整合信息。RAG 在此基础上多了一层 LLM 的理解和总结。它替你读文档、整合答案。可以把 RAG 理解为"搜索 + 阅读理解"。
从技术实现上看,传统搜索引擎基于关键词匹配和 PageRank 等算法,而 RAG 基于向量相似度搜索和 LLM 生成。搜索引擎的目标是"找到相关文档",RAG 的目标是"给出准确答案"。
Q2:知识库更新后,RAG 需要重新训练吗?
不需要。RAG 的核心优势就是知识更新不涉及模型训练。你只需要重新索引新文档(生成 Embedding 并存入向量数据库),旧的检索管道和 LLM 都无需改动。
具体来说,更新流程如下:
- 检测文档变更(新增、修改、删除)
- 对新增或修改的文档进行切分(见第 5 章)
- 调用 Embedding API 生成向量(见第 2 章)
- 将向量存入向量数据库(见第 3 章)
- 如果是修改或删除,需要从数据库中移除旧版本的向量
整个过程可以在几分钟内完成,具体时间取决于文档数量和 Embedding API 的响应速度。
Q3:向量数据库和传统数据库有什么区别?
传统数据库做的是精确匹配("查找标题为 X 的文档"),向量数据库做的是语义相似度搜索("查找与这段文字含义最接近的文档")。第 3 章会详细展开。
从数据结构上看,传统数据库存储的是结构化数据(表格、字段),向量数据库存储的是高维向量(浮点数数组)。从查询方式上看,传统数据库用 SQL 进行精确查询或模糊匹配,向量数据库用向量距离算法(如余弦相似度、欧氏距离)进行相似度排序。
Q4:RAG 是不是把整个文档塞进 Prompt 就行了?
不行。LLM 的上下文窗口有 Token 限制,而且当检索结果包含大量无关内容时,模型反而容易被噪声干扰------这叫"Lost in the Middle"现象。第 5 章(文档切分)和第 11 章(上下文组装)会深入讨论这个问题的解决方案。
正确的做法是:
- 将长文档切分成合理大小的片段(通常 200-1000 token)
- 检索时只返回与问题最相关的几个片段(通常 3-10 个)
- 在组装 Prompt 时对片段进行筛选和排序,优先保留最相关的内容
- 如果片段过多,可以使用上下文压缩技术(见第 11 章)
Q5:为什么叫"检索增强生成"?
因为核心动作是三个:从知识库检索 相关信息,用检索结果增强 Prompt 的上下文,最后交给 LLM 生成答案。"增强"是关键------不是用检索替换生成,而是在生成的基础上提供信息支撑。
这个名字来源于 Meta AI 在 2020 年发表的论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》。论文提出了一种将检索系统和生成模型结合的架构,用于解决知识密集型任务(如开放域问答、事实验证)中的知识缺失问题。
Q6:RAG 能完全消除幻觉吗?
不能。RAG 可以大幅降低幻觉概率,但无法完全消除。原因包括:
- 检索可能失败,返回不相关或错误的文档
- 模型可能误解检索到的内容,做出错误推断
- 模型可能在参考资料之外添加自己的"知识"
- 多个参考资料之间可能存在矛盾,模型需要判断哪个正确
在《第8章:RAG 的局限性及应对策略》中,我们会详细讨论 RAG 场景下幻觉的来源和缓解方法。
Q7:RAG 的性能瓶颈在哪里?
RAG 系统的性能瓶颈通常不在 LLM 生成环节,而在检索环节。具体来说:
- Embedding 生成:如果需要实时为查询生成向量,这会带来额外的 API 调用延迟
- 向量搜索:当向量库规模达到百万级时,搜索延迟会显著增加
- 文档加载和切分:如果检索结果需要动态加载和切分,会增加处理时间
优化策略包括:缓存常用查询的 Embedding、使用高效的向量索引算法(如 HNSW)、预切分文档并存储等。这些内容会在《第17章:RAG 性能优化实战》中详细讨论。
练习
练习 1:识别 RAG 适用场景
阅读以下场景描述,判断哪些适合使用 RAG 方案,并说明理由:
- 某电商需要 7x24 小时客服机器人,产品目录每周更新
- 某作家想用 AI 辅助写一部奇幻小说
- 某律所需要 AI 根据最新的《民法典》回答用户咨询
- 某公司想让 AI 用 CEO 的语气回复邮件,但 CEO 从未写过公开邮件
- 某医院需要 AI 根据最新的临床指南辅助诊断
- 某游戏公司需要 AI 实时生成 NPC 对话,要求响应时间低于 50ms
验证标准:
- 场景 1、3、5 适合 RAG:有明确的知识源(产品目录、法律条文、临床指南),知识需要时效性,答案需要可溯源
- 场景 2 不适合:纯创意写作,不需要外部知识
- 场景 4 不适合:需要学习特定风格,更适合 Fine-tuning,且缺乏可用于检索的知识源
- 场景 6 不适合:超低延迟要求,RAG 的检索开销无法满足
练习 2:画出 RAG 工作流
在不参考正文的情况下,画出 RAG 的经典三阶段工作流,并用一句话描述每个阶段的职责。
验证标准:
- 三个阶段完整:检索(Retrieve)→ 增强(Augment)→ 生成(Generate)
- 职责描述准确:
- 检索:从知识库中找到与问题语义最相关的文档片段
- 增强:将检索结果与用户问题组装成完整的 Prompt
- 生成:LLM 基于增强后的 Prompt 生成最终答案
练习 3:扩展"伪 RAG"代码
在第 2 节给出的"伪 RAG"代码基础上,增加一个简单的"引用来源"功能:让 augment 函数在 Prompt 中保留每条参考资料的索引号,并要求 LLM 在回答中标注引用了哪条资料。
提示:
- 修改
augment函数,在每条参考资料前添加编号(如[1]、[2]) - 在 Prompt 中明确要求"在回答中使用 数字 标注引用来源"
- 测试不同问题,观察 LLM 是否能正确标注引用
验证标准:
- Prompt 模板中包含编号的参考资料
- LLM 的回答中出现了类似"1"、"2"的引用标注
- 引用标注与实际的参考资料对应
练习 4:对比 RAG 与非 RAG 的回答
选择一个你熟悉的专业领域(如编程、法律、医学),构造一个问题,该问题的答案在你最近的學習资料中,但不在 LLM 的训练数据中。分别用以下方式获取答案:
- 直接使用 LLM(不使用 RAG)
- 手动模拟 RAG:将相关资料粘贴到 Prompt 中,让 LLM 基于资料回答
对比两种方式的回答质量,记录以下指标:
- 准确性:答案是否正确
- 完整性:是否覆盖了关键信息
- 可溯源性:是否能指出答案的来源
- 幻觉程度:是否有编造的内容
验证标准:能够清晰描述两种方式的差异,并理解 RAG 在准确性、可溯源性方面的优势。
📚 延伸阅读
- Retrieval Augmented Generation: Streamlining the creation of intelligent natural language processing models --- Meta AI 于 2020 年提出的原始 RAG 论文博客,通俗易懂地介绍了 RAG 的动机和基本思想
- Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks --- RAG 原始论文(Lewis et al., NeurIPS 2020),学术论文版本,适合想深入了解技术细节的读者
- OpenAI Embeddings Guide --- OpenAI 官方文档,详细介绍了向量嵌入的概念、使用方法和最佳实践
- LangChain RAG Tutorial --- LangChain 的 RAG 官方教程(Python 版),虽然语言不同,但架构思想与 TypeScript 版一致
- Lost in the Middle: How Language Models Use Long Contexts --- 研究论文,揭示了 LLM 在处理长上下文时的"中间位置忽视"现象,对理解 RAG 的局限性有帮助