大模型应用科普:RAG 检索增强生成技术详解
前面我们普及了大模型的基础知识,但是缺乏应用的大模型是没有价值的。当然你可能使用过 Kimi Chat、豆包这样的大模型工具,它们可能已经在生活中充当了我们的创作助手、咨询专家,甚至情感陪护等角色。但这样的通用应用还远远不能发挥出大模型的真正价值。我们期望大模型在更专业的生产领域发挥作用,提升生产力,引领真正的科技变革。
当前大模型被普遍看好的两个专业应用方向是 RAG(Retrieval-Augmented Generation,检索增强生成)与 Agent(AI 智能体)。本文将首先尝试用通俗易懂的语言帮助大家认识 RAG 这一重要应用形式。
01. 了解大模型的'幻觉'
在了解为什么出现 RAG 之前,我们首先需要了解大模型著名的'幻觉'问题。
**'幻觉'**指的是大模型在试图生成内容或回答问题时,输出的结果不完全正确甚至错误,即通常所说的'一本正经地胡说八道'。这种'幻觉'可以体现为对事实的错误陈述与编造、错误的复杂推理或者在复杂语境下处理能力不足等。其主要原因来自于:
(1)训练知识存在偏差
在训练大模型时输入的海量知识可能包含错误、过时,甚至带有偏见的信息。这些信息在被大模型学习后,就可能在未来的输出中被重现。例如,如果训练数据中包含过时的法律条文,模型可能会引用已废止的条款。
(2)过度泛化地推理
大模型尝试通过大量的语料来学习人类语言的普遍规律与模式,这可能导致'过度泛化'的现象,即把普通的模式推理用到某些特定场景,就会产生不准确的输出。比如将一般性的商业逻辑套用到特殊的医疗案例中。
(3)理解存在局限性
大模型并没有真正'理解'训练知识的深层含义,也不具备人类普遍的常识与经验,因此可能会在一些需要深入理解与复杂推理的任务中出错。它更多是基于概率预测下一个 token,而非基于逻辑推导。
(4)缺乏特定领域的知识
通用大模型就像一个掌握了大量人类通用知识且具备超强记忆与推理能力的优秀学生,但可能不是某个垂直领域的专家(比如医学或者法律专家)。当面临一些复杂度较高的领域性问题或私有知识相关的问题时(比如介绍企业的某个新产品),它就可能会编造信息并将其输出。
当然,除了'幻觉'问题,大模型还存在知识落后、输出难以解释、输出不确定等一些问题。这也决定了大模型在大规模商业生产应用中会面临着挑战:很多时候我们不仅需要理解力和创造力,还需要极高的准确性(不仅要会写作文,还要会准确解答数学题)。
02. RAG 如何优化'幻觉'问题
RAG(Retrieval-Augmented Generation),正是为了尽可能地解决大模型在实际应用中面临的一些问题,特别是'幻觉'问题而诞生的,也是最重要的一种优化方案。其基本思想可以简单表述如下:
将传统的生成式大模型与实时信息检索技术相结合,为大模型补充来自外部的相关数据与上下文,以帮助大模型生成更丰富、更准确、更可靠的内容。这允许大模型在生成内容时可以依赖实时与个性化的数据和知识,而不只是依赖训练知识。简单的说:RAG 给大模型增加了一个可以快速查找的知识外挂。
用一个例子帮助理解 RAG 的概念:
如果把大模型比喻成一个经过大量知识与技能训练的优秀学生,把大模型响应的过程比喻成考试,那么这个优秀学生在考试时仍然可能会遇到没有掌握的知识,从而编造答案(幻觉)。
RAG 就是在这个学生考试时临时给他的一本参考书。我们可以要求他在考试时尽量参考这本书作答,那么在遇到与这本书中的知识相关的问题时,他的得分是不是就高多了呢?
03. 模拟简单的 RAG 场景
假如你需要开发一个在线的自助产品咨询工具,允许客户使用自然语言进行交互式的产品问答,比如'请介绍一下您公司这款产品与××产品的不同之处'。为了让客户有更好的体验,你决定使用大模型来构造这样的咨询功能并将其嵌入公司的官方网站。
如果你直接使用通用大模型,那么结果很可能无法回答客户的问题,因为大模型显然不具备贵公司的最新手机产品知识,有时候甚至会尝试编造答案。
现在,如果你使用 RAG 的思想,那么可以先从企业私有的知识库中检索出下面一段相关的补充知识。你把检索出的补充知识组装到提示词中,将其输入大模型,并要求大模型基于提供的知识来回答你的问题。大模型很聪明地'吸收'了补充的外部知识,并结合自己已经掌握的知识,成功推理并给出了准确的答案。
是的,RAG 本质上就是一种借助'外挂'的提示工程,但绝不仅限于此。因为在这里简化了很多细节,只是为了展示 RAG 最核心的思想:给大模型补充外部知识以提高输出答案的质量。
04. RAG 与模型微调
要想提高大模型在特定行业与场景中输出的适应性与准确性,除了使用 RAG,还可以使用自己的数据对大模型进行微调。简单地说,微调就是对基础模型在少量(相对于预训练的数据量来说)的、已标注的数据上进行再次训练与强化学习,以使得模型更好地适应特定的场景与下游任务。 显然,微调是另外一种给大模型'灌输'新知识的方法。两者的主要差异在于:
| 特性 | RAG (检索增强生成) | 微调 (Fine-tuning) |
|---|
| 训练需求 | 无需额外训练 | 需要专门的数据准备和训练时间 |
| 知识更新 | 随时可以提供补充的知识 | 效果较难预测,不太适合更新频繁的知识 |
| 调试难度 | 调试简单 | 技术要求相对较高 |
| 性能影响 | 回答时性能略差(毕竟要现学现用) | 应用层面会更简单,推理速度可能更快 |
以前面的例子来说明微调和 RAG 的区别:
- RAG:在考试时给他提供某个领域的参考书,要求他现学现用,自己翻书理解后给出答案。
- 模型微调:在考试前一天对他进行突击辅导,使他掌握了新的领域知识,然后让他参加考试。
无法确切地说在什么场景中必须使用 RAG、在什么场景中必须使用微调。结合当前的一些研究及普遍的测试结果,可以认为在以下场景中更适合考虑微调的方案(在不考虑成本的前提下):
- 需要注入较大数据量且相对稳定、迭代周期较长的领域知识;需要形成一个相对通用的领域大模型用于对外服务或者运营。
- 执行需要极高准确率的部分关键任务,且其他手段无法满足要求,此时需要通过高效微调甚至全量微调来提高对这些任务的输出精度,比如医疗诊断。
- 在采用提示工程、RAG 等技术后,无法达到需要的指令理解准确、输出稳定或其他业务目标。
在除此之外的很多场景中,可以优先考虑使用 RAG 来增强大模型生成。当然,在实际条件允许的前提下,两者的融合应用或许是未来更佳的选择。
05. 初步认识 RAG 架构
最后,我们从技术层来看一个最基础、最常见的 RAG 应用的逻辑架构与流程。
通常情况下,可以把一个简单的 RAG 应用从整体上分为**数据索引(Indexing)与数据查询(Query)**两个大的阶段,而在每个阶段都包含不同的处理环节。
索引阶段
索引阶段就是编写考试时需要的参考书,这本书要容易快速查找特定知识。具体步骤包括:
- 数据清洗:去除无关字符、格式统一。
- 文本分块(Chunking):将长文档切分成适合模型处理的片段。
- 向量化(Embedding):使用 Embedding 模型将文本块转换为向量表示。
- 存储入库:将向量存入向量数据库(Vector Database)。
查询阶段
查询阶段就是考试时使用这本书的过程,先查找参考资料,然后解答问题。具体步骤包括:
- 用户提问:接收用户的自然语言问题。
- 查询向量化:将用户问题转换为向量。
- 相似度检索:在向量数据库中搜索与问题最相似的文本块。
- 上下文组装:将检索到的文本块与原始问题组合成 Prompt。
- 模型生成:将 Prompt 发送给大模型生成最终答案。
在实际 RAG 应用中,对于不同的应用场景、客观条件、工程要求,会有更多的模块、架构与流程的优化设计,以应对众多的技术细节与挑战。比如,自然语言表达的输入问题可能千变万化,你从哪里检索对应的外部知识?你需要用怎样的索引来查询外部知识?你怎样确保补充的外部知识是回答这个问题最需要的呢?就像上面例子中的学生,如果考试的知识点是英语语法,你却给他一本《微积分》,那显然是于事无补的。
06. RAG 核心实现细节
为了更深入地理解 RAG,我们需要关注几个核心技术点:
1. 文本分块策略
分块的大小和质量直接影响检索效果。常见的策略有固定长度分块、按语义分块、滑动窗口等。如果分块太小,可能丢失上下文信息;如果分块太大,可能引入噪声。最佳实践通常是结合业务场景调整。
2. 向量检索算法
向量数据库支持多种检索算法,如 HNSW(Hierarchical Navigable Small World)、IVF(Inverted File Index)等。HNSW 通常能提供更高的召回率和速度,适合大多数实时场景。
3. 重排序(Re-ranking)
初始检索可能返回多个相关文档,但顺序未必最优。引入重排序模型(Cross-Encoder)可以对候选文档进行精细打分,将最相关的文档排在前面,显著提升最终生成的质量。
4. 混合检索
单纯依靠向量检索(语义匹配)可能忽略关键词匹配。混合检索结合了关键词检索(BM25)和向量检索,能够兼顾语义理解和精确匹配,提高召回率。
07. 代码示例:Python + LangChain
以下是一个简化的 RAG 实现流程示例,展示了如何使用 Python 和 LangChain 框架构建基础的检索增强生成系统。
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
loader = TextLoader('knowledge_base.txt')
documents = loader.load()
splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
docs = splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 3})
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(),
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
query = "什么是 RAG 技术?"
result = qa_chain({"query": query})
print(result["result"])
这段代码演示了从文件加载、分块、向量化到最终查询的完整链路。实际生产中,还需考虑鉴权、缓存、监控等工程化能力。
08. 总结
RAG 技术通过引入外部知识库,有效缓解了大模型的幻觉问题,使其能够回答基于私有数据或最新事实的问题。相比于微调,RAG 具有成本低、更新快、可解释性强的优势,是目前企业落地大模型应用的首选方案之一。
随着技术的发展,RAG 也在不断演进,出现了多跳检索、图数据库结合、Agent 自主规划等高级形态。对于开发者而言,理解 RAG 的基本原理与架构,掌握向量检索与提示工程技巧,是构建高质量 AI 应用的关键一步。
希望本文能帮助你建立起对 RAG 技术的清晰认知,并在实际项目中灵活应用。