RAG 检索增强生成:减少幻觉的问答方案

FreeGuideOnline 最新 2026-06-13

RAG 检索增强生成:减少幻觉的问答方案

大语言模型(LLM)在自然语言处理领域展现出惊人的能力,但在实际应用中,它们存在一个致命缺陷——幻觉(Hallucination),即模型会自信地生成与事实不符的内容。这种问题在需要精确、可溯源的场景中(如企业知识库、医疗咨询、法律问答)是不可接受的。

RAG(Retrieval-Augmented Generation,检索增强生成) 正是为了解决这一问题而提出的架构。它通过将信息检索与文本生成相结合,让模型在回答时“有据可依”,显著降低了幻觉的发生率。本教程将从零开始,带你理解 RAG 的核心思想、工作流程,并动手实现一个最简单的 RAG 问答系统。

为什么需要 RAG?

传统 LLM 的局限

  • 知识截止期:模型训练数据具有时间窗口,无法获取最新信息。
  • 领域知识不足:通用大模型对垂直领域(如公司内部文档、特定医学文献)了解有限。
  • 无法溯源:即使答案正确,也没有办法证明其出处,信息可信度低。
  • 幻觉风险:当问题超出知识范围时,模型倾向于“编造”看似合理的回答。

RAG 是怎么解决的?

RAG 的核心思路是:先检索,再生成。在用户提问时,系统并不是直接让大模型凭空作答,而是:

  1. 从外部知识库(如文档、数据库)中检索与问题最相关的内容。
  2. 将这些检索到的内容作为“参考上下文”提供给大模型。
  3. 让模型基于给定的上下文生成最终回答。

这样一来,模型不再依赖自己模糊的记忆,而是基于实时获取的具体资料进行作答,幻觉大幅减少,而且答案的每一部分都可以对应到原始文档的片段,实现了事实层面的可解释性。

RAG 工作流程详解

一个标准的 RAG 系统通常由离线的索引构建在线的查询处理两部分组成。

离线阶段:知识库索引

目标是将外部文档转换成可供快速检索的向量数据库。

  1. 文档加载与切割
    读取多种格式的源文档(PDF、Markdown、网页),并使用文本分割器(Text Splitter)将长文档切分成较小的语义块(Chunk)。合适的块大小(如 512 token)能平衡语义完整性和检索精度。

  2. 向量嵌入(Embedding)
    使用嵌入模型(如 OpenAI 的 text-embedding-3-small,开源的 BAAI/bge-large-zh)将每个文本块转换为固定维度的向量。这个向量捕捉了文本的语义信息,语义相似的文本在向量空间中距离更近。

  3. 向量数据库存储
    将所有文本块的向量及其原始文本内容存入向量数据库(如 Chroma、Pinecone、Weaviate、Milvus)。向量数据库支持高效的近似最近邻(ANN)搜索,能够急速响应相似向量查询。

在线阶段:检索与生成

当用户提出问题后,系统执行以下步骤:

  1. 问题向量化
    使用同一个嵌入模型将用户查询转换为查询向量。

  2. 相似性检索
    在向量数据库中检索与查询向量最相似的 Top-K 个文本块(通常 K = 3~10)。这一步返回的是与问题最相关的文档片段。

  3. 提示组装
    将检索到的文本块与原始问题一起,按照预设的提示模板组合成完整的提示词,明确告知模型“请仅根据以下参考资料回答问题”。
    示例提示模板:

    请基于以下参考资料回答用户问题。如果资料中不存在相关信息,请直接说明“无法从提供的资料中找到答案”。
    
    参考资料:
    {检索到的文本块}
    
    用户问题:{用户原始问题}
    回答:
    
  4. 大模型生成
    将组装好的提示发送给生成模型(如 GPT-4、Llama 3),模型在强制的上下文约束下生成答案,从而大幅抑制幻觉。

动手实现一个最简单的 RAG 系统

以下示例使用 Python 和流行的 LangChain 框架,结合 OpenAI 的嵌入和对话模型,构建一个能回答基于本地文档的问题的系统。请确保已安装所需依赖:

pip install langchain langchain-openai chromadb unstructured

1. 准备文档并建立向量库

from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

# 加载本地文档
loader = TextLoader("./knowledge.txt", encoding="utf-8")
documents = loader.load()

# 切割文档为适当大小的块
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,        # 每块最大长度
    chunk_overlap=50,      # 块之间重叠长度,保持语义连贯
    separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
)
chunks = text_splitter.split_documents(documents)

# 初始化嵌入模型(这里用 OpenAI,需要 API key)
embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")

# 创建向量数据库并持久化
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embedding_model,
    persist_directory="./chroma_db"
)
vectorstore.persist()
print(f"索引完成,共处理 {len(chunks)} 个文档块")

2. 构建 RAG 问答链

from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

# 定义检索器(返回最相关的3个片段)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 自定义提示模板,强制模型仅使用上下文
prompt_template = """请严格根据以下参考资料回答问题。如果资料中没有相关信息,请回答“未找到相关信息”。

参考资料:
{context}

问题:{question}
回答:"""

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

# 初始化生成模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

# 创建检索增强生成链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",          # 将所有检索到的文档块拼接后一次性送给模型
    retriever=retriever,
    chain_type_kwargs={"prompt": PROMPT},
    return_source_documents=True  # 返回参考文档片段以便溯源
)

# 提问测试
query = "什么是RAG?"
result = qa_chain.invoke({"query": query})
print("答案:", result["result"])
print("\n参考来源:")
for doc in result["source_documents"]:
    print(f"- {doc.metadata.get('source', '未知来源')}: {doc.page_content[:100]}...")

3. 解读与进阶提示

  • 检索精度调优:可以通过调整 chunk_sizechunk_overlap 和检索参数 k 来平衡答案的完整性和相关性。
  • 混合检索:纯向量检索有时会漏掉精确的关键词匹配,可结合 BM25 等传统稀疏检索方法,形成混合检索(Hybrid Search),进一步提升召回率。
  • 重排序(Rerank):在初始检索后,可以再用一个轻量级模型(如 Cohere Rerank、bge-reranker)对候选片段进行重新打分,确保最相关的片段排在前面。
  • 多源数据连接:企业场景中通常需要对接多个数据源(数据库、API、知识库),LangChain 提供了丰富的 Retriever 组件,可以轻松定制。

RAG 的常见挑战与应对

挑战 描述 应对策略
检索失败 知识库中不存在相关信息,导致模型无上下文可依。 在提示中明确要求模型无信息时坦诚告知,并考虑接入网络搜索兜底。
上下文过大 检索到的文档过长,超出模型上下文窗口。 使用 MapReduce、Refine 等链类型分块处理,或对块大小进行更精细控制。
幻觉仍然存在 模型未严格遵循上下文,自行编造。 增强提示约束,使用更强大的模型,增加后校验步骤(如事实一致性检查)。
低质量嵌入 嵌入模型无法准确表达领域语义,导致检索不准。 使用领域专用嵌入模型,或在自有数据上微调嵌入模型。

总结

RAG 架起了大语言模型与外部知识之间的桥梁,是目前解决知识更新、领域适配和幻觉问题最主流的方案之一。通过将检索机制引入生成流程,我们让 AI 的回答不再是“黑箱猜测”,而是每一个论断都有文档支撑的可靠推理。掌握 RAG 的核心原理和基础实现,你就已经迈出了构建可信 AI 应用的关键一步。

从今天开始,试着为自己的私有知识库搭建第一个 RAG 问答机器人吧。你将立刻感受到“有据可查”带来的回答质量的飞跃。