一、为什么需要 RAG:大模型的“知识困境”

当我们使用像 GPT 这样的大语言模型(LLM) 时,很快会发现一个核心问题:它的知识是静态的、有限的。其知识截止于训练数据的时间点,无法获知最新的新闻、公司内部文档或专业领域的细分知识。直接向它提问,它可能会“一本正经地胡说八道”(即产生幻觉),或者坦诚地表示“我无法获取最新信息”。

RAG(Retrieval-Augmented Generation,检索增强生成) 正是为了解决这个问题而诞生的。它的核心思想非常直观:先检索,再生成。就像我们人类在回答一个不确定的问题时,会先去查阅书籍或搜索资料,然后再基于找到的信息给出回答。RAG 赋予了大模型类似的能力,让它能够利用外部、实时的、特定的知识库来增强其生成回答的准确性和时效性。

提示:你可以将 RAG 理解为给一个博闻强记但不知变通的“大脑”(LLM)配备了一位高效的“图书管理员”(检索器)。管理员快速找到相关书籍的片段,大脑基于这些片段组织语言,生成最终答案。

二、RAG 的核心流程:检索、增强与生成

一个完整的 RAG 流程通常包含三个关键阶段,如下图所示:

  1. 索引(Indexing):这是离线准备阶段。将你的私有文档(如 PDF、网页、数据库记录)进行处理。核心是将文本分割成较小的文档块,使用嵌入模型将这些文本块转换为数值向量(嵌入向量),并存入一个向量数据库中。这个过程建立了从语义到向量的映射,为后续的相似度检索打下基础。
  2. 检索(Retrieval):这是在线查询阶段。当用户提出问题时,首先使用同一个嵌入模型将用户的问题也转换为向量。然后,在向量数据库中执行相似性搜索,找出与问题向量最相似的几个文档块(Top K)。
  3. 生成(Generation):这是最终回答阶段。将检索到的相关文档块作为上下文,与用户原始问题一起,构造一个提示词,发送给大语言模型。大模型基于这些“证据”生成最终的回答,使其有据可依,大大降低了幻觉风险。

三、关键组件详解:嵌入模型与向量数据库

RAG 的效能高度依赖于两个核心组件:

提示:在实践中,嵌入模型的选择有时比底层大模型(如GPT-4)更能影响最终效果,尤其是在处理专业领域文档时。需要对特定领域的嵌入模型进行微调或选择。

四、动手实践:一个简单的 RAG 实现

下面我们用 Python 代码演示一个最简单的 RAG 流程。我们将使用 LangChain 库来简化编排,并用 ChromaDB 作为向量存储。

首先,安装必要的库:pip install langchain chromadb openai

import os
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterText_splitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI

# 1. 加载文档(示例文本)
loader = TextLoader('my_knowledge.txt', encoding='utf-8')
documents = loader.load()

# 2. 文本分块(chunk_size 是关键参数)
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
docs = text_splitter.split_documents(documents)

# 3. 创建嵌入模型和向量数据库
embeddings = OpenAIEmbeddings() # 需要设置 OPENAI_API_KEY 环境变量
vectorstore = Chroma.from_documents(docs, embeddings)

# 4. 创建检索问答链
qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(temperature=0), # 使用一个简单的LLM
    chain_type="stuff", # 将所有检索到的文档拼接起来
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索最相关的3个文档块
)

# 5. 提问!
query = "我们公司的报销政策中,餐费的标准是多少?"
result = qa_chain.run(query)
print(result)

五、优化与进阶:让 RAG 更强大

上述基础 RAG 流程存在改进空间。以下是几个重要的优化方向:

# 示例:一个更复杂的提示词模板
from langchain.prompts import PromptTemplate

template = """
请严格根据以下上下文信息来回答最后的问题。如果上下文中没有包含答案所需的信息,请直接说“根据提供的资料,我无法回答这个问题”。

上下文:
{context}

问题:{question}

有用的回答:"""

PROMPT = PromptTemplate(template=template, input_variables=["context", "question"])

# 将此模板传入 RetrievalQA 链的 `chain_type_kwargs` 参数中

六、应用场景与局限性

典型应用场景

需要注意的局限性

提示:RAG 不是银弹。对于需要深度推理、创作或完全开放域的问题,它可能帮助有限。它最擅长的是需要精确、可溯源、基于事实的问答任务。