解决大模型幻觉:LangChain+RAG 工程落地实践方案
摘要
大语言模型凭借强大的自然语言生成能力,广泛应用于智能问答、文档检索、企业知识库等场景,但模型幻觉(Hallucination) 始终是阻碍工程落地的核心痛点。模型幻觉指大模型在生成答案时编造不存在的事实、数据、结论,即便面对专业领域私有文档,依然容易输出虚假信息。单纯依靠调整提示词、降低采样温度等方式只能微弱缓解幻觉,无法从根本上解决问题。检索增强生成(RAG, Retrieval-Augmented Generation)通过外部知识库提供真实参考资料,约束模型基于检索到的素材生成回答,是工业界抑制幻觉主流方案。
本文基于LangChain技术栈,从零搭建完整RAG系统,逐层拆解文档预处理、文本分割、向量嵌入、多路检索、重排序、提示词约束、结果校验全链路优化手段。同时对比基础RAG、Self-RAG等方案在抑制幻觉上的优劣,附带完整可运行Python代码,梳理生产环境常见陷阱,提供一套能够有效降低幻觉发生率的工程实践方案。
关键词:大模型幻觉;LangChain;RAG;向量数据库;检索增强生成;幻觉抑制
1 引言
1.1 什么是大模型幻觉
大语言模型本质是基于概率预测下一个token,训练数据之外的问题场景中,模型为保证文本流畅性,倾向于生成看似合理、实则错误的内容,也就是幻觉。幻觉分为两类:
- 内在幻觉:答案与上下文检索文档内容相互冲突;
- 外在幻觉:答案包含知识库完全不存在的信息。
在企业知识库、法律咨询、医疗问答、技术文档答疑等场景,幻觉会带来严重风险。例如企业AI客服编造产品参数、智能文档系统输出不存在的条款,直接造成业务损失。
1.2 传统抑制幻觉方案局限性
很多开发者初期尝试以下方案缓解幻觉,但效果有限:
- Prompt约束:在提示词中要求“不知道就回答无法找到相关信息”。模型容易忽略指令,依然强行编造答案;
- 降低temperature:减小生成随机性。只能减少创造性输出,无法阻止模型依据错误记忆生成内容;
- 增大上下文窗口:把全部文档喂给模型。上下文存在长度限制,大量冗余文本会引入干扰,提升推理成本。
上述手段都没有改变模型依赖内部参数知识生成文本的本质。RAG的核心思路:不让模型依靠自身记忆作答,强制模型以外部检索文档作为唯一信息来源,从源头减少幻觉。
1.3 LangChain在RAG系统中的价值
原生实现RAG需要手动处理文档加载、文本切分、向量计算、检索拼接、模型调用等大量重复代码。LangChain封装标准化组件:文档加载器(DocumentLoader)、文本分割器(TextSplitter)、向量嵌入(Embedding)、向量存储(VectorStore)、链式调用(LCEL),开发者可以快速搭建RAG流水线,并且灵活扩展检索策略、后处理校验逻辑。
2 RAG基础架构与幻觉产生链路分析
标准基础RAG流程:
文档加载 → 文本分割 → Embedding向量化存入向量库 → 用户提问 → Query向量化 → 向量相似度检索 → 检索片段拼接进Prompt → LLM生成答案
即便搭建基础RAG,依然会产生幻觉,常见诱因:
- 文本切分不合理,关键信息被截断,检索片段信息缺失;
- 相似度检索召回无关文档,干扰模型判断;
- 只做粗粒度向量检索,缺少重排序步骤;
- Prompt没有严格限制模型不能脱离检索材料编造内容;
- 检索内容和用户问题不匹配,模型强行作答;
- 没有后置校验,无法识别生成内容与参考文档冲突。
想要高效抑制幻觉,需要对整条链路逐个环节优化。下文基于LangChain实现基础RAG,并逐层引入优化策略。
环境依赖安装
# 执行安装命令
# pip install langchain langchain-openai langchain-chroma langchain-text-splitters python-dotenv
3 基于LangChain搭建基础RAG系统
3.1 项目基础初始化
from dotenv import load_dotenv
import os
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.documents import Document
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 加载环境变量
load_dotenv()
# 初始化大模型与Embedding模型
llm = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0.0, # 温度置0,减少随机生成,初步缓解幻觉
api_key=os.getenv("OPENAI_API_KEY")
)
embedding = OpenAIEmbeddings(model="text-embedding-ada-002")
# 构建测试文档,模拟企业知识库数据
docs_content = [
Document(page_content="公司考勤制度:工作日上班时间9:00-18:00,午休12:00-13:30。月度迟到3次以内不处罚,超过3次每次扣款50元。"),
Document(page_content="年假规则:入职满1年享有5天年假,满3年享有8天年假,年假不可结转至下一年度。"),
Document(page_content="报销规范:差旅费报销需要提供发票,交通补贴上限200元/天,住宿补贴上限350元/天。")
]
3.2 文档切分与向量库构建
文本分割是影响检索质量的关键。递归字符分割器支持按段落、换行、标点逐层切割,相比简单固定长度分割,保留语义完整性。语义完整的片段能够提升检索准确度,减少幻觉。
# 文本分割器配置
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=60,
separators=["\n\n", "\n", "。", ",", " "]
)
split_docs = text_splitter.split_documents(docs_content)
# 持久化向量数据库
vectorstore = Chroma.from_documents(
documents=split_docs,
embedding=embedding,
persist_directory="./chroma_db"
)
# 创建检索器,默认返回top-4相关片段
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
3.3 基础RAG提示词设计(幻觉第一道防线)
提示词必须加入强约束,明确告知模型:只能使用提供的上下文作答,找不到信息直接坦白,禁止编造任何信息。
# 幻觉约束Prompt
prompt_template = """
你是企业内部知识库问答助手,请严格遵守以下规则:
1. 仅允许使用【参考上下文】中的信息回答用户问题;
2. 如果参考上下文不存在答案,直接回复:“知识库中未查询到相关信息,无法解答”;
3. 严禁编造制度、数据、条款,禁止凭借自身知识库回答;
4. 回答内容不能和参考上下文存在冲突;
【参考上下文】
{context}
【用户问题】
{question}
"""
prompt = PromptTemplate.from_template(prompt_template)
# 文档拼接工具函数
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# 构建RAG链式调用 LCEL
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 测试调用
if __name__ == "__main__":
res = rag_chain.invoke("公司年假最多可以结转几年?")
print(res)
运行结果预期输出:年假不可结转至下一年度。
测试幻觉场景提问:公司婚假有多少天?
理想输出:知识库中未查询到相关信息,无法解答。
但基础RAG仍然存在缺陷:检索可能召回无关文本;模型偶尔无视指令强行生成虚假内容。需要多层优化方案。
4 多层优化策略:系统性抑制大模型幻觉
4.1 优化策略1:检索优化 + 重排序(Rerank)
向量相似度检索仅依靠Embedding空间距离,容易出现语义不匹配但是向量接近的噪声文本。引入重排序模型,对初次召回的文档进行二次打分,过滤无关片段,减少干扰信息。
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
# 加载重排序模型
rerank_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")
compressor = CrossEncoderReranker(model=rerank_model, top_n=2)
# 封装压缩检索器:先粗召回,再重排序筛选
compression_retriever = ContextualCompressionRetriever(
base_retriever=retriever,
base_compressor=compressor
)
# 更新RAG链路,使用优化后的检索器
optimized_rag_chain = (
{"context": compression_retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
4.2 优化策略2:Self-RAG 自校正检索增强
基础RAG固定执行“先检索,再生成”,不管检索内容是否有效。Self-RAG让模型自主判断:是否需要检索、检索内容是否足够、生成答案是否存在幻觉,动态调整流程。借助LangGraph可以实现闭环自校正工作流。
核心逻辑:
- 用户提问,模型判断是否需要查询知识库;
- 执行检索,获取文档;
- 生成初稿;
- 校验:答案是否能够被检索文档支撑;
- 若无法支撑,重新检索或者直接回答信息不足。
4.3 优化策略3:后置幻觉校验模块
在LLM生成答案之后,增加校验链路,自动比对答案和检索文档,识别冲突信息,拦截幻觉输出。
# 幻觉校验Prompt
check_prompt_template = """
任务:判断【回答内容】是否存在幻觉。
判定标准:回答内容必须完全能够在【参考文档】找到依据;
如果出现文档不存在的信息、与文档冲突信息,判定为存在幻觉。
【参考文档】
{context}
【模型回答】
{answer}
输出要求:只输出True(存在幻觉)或者False(无幻觉)
"""
check_prompt = PromptTemplate.from_template(check_prompt)
check_chain = check_prompt | llm | StrOutputParser()
# 封装带幻觉校验的完整流程
def full_qa_flow(question):
# 1.检索文档
retrieved_docs = compression_retriever.invoke(question)
context_text = format_docs(retrieved_docs)
# 2.RAG生成答案
answer = optimized_rag_chain.invoke(question)
# 3.幻觉校验
check_result = check_chain.invoke({"context": context_text, "answer": answer})
if check_result == "True":
return "警告:检测到回答存在不实信息,无法提供有效答案"
return answer
# 测试
if __name__ == "__main__":
print(full_qa_flow("迟到超过3次扣款标准是什么?"))
5 离线本地化方案:Ollama + LangChain 私有RAG
很多企业要求数据不出内网,无法调用云端OpenAI接口。基于Ollama部署开源大模型,构建离线RAG,同样可以实现幻觉抑制。依赖不变,只替换模型初始化代码:
from langchain_ollama import ChatOllama, OllamaEmbeddings
# 本地开源模型
llm_local = ChatOllama(model="qwen2:7b", temperature=0)
embedding_local = OllamaEmbeddings(model="nomic-embed-text")
# 使用本地Embedding重建向量库
vectorstore_local = Chroma.from_documents(
documents=split_docs,
embedding=embedding_local,
persist_directory="./chroma_local_db"
)
retriever_local = vectorstore_local.as_retriever(search_kwargs={"k":4})
6 工程落地常见坑与幻觉防控经验总结
6.1 文档处理层面
- chunk_size不要过大。过长片段包含大量无关信息,增大模型混淆概率;不要过小,语义断裂。通用场景推荐200~400字符;
- 合理设置overlap重叠区域,避免知识点被切割断裂;
- 原始文档先清洗:去除乱码、重复内容、无效页眉页脚,脏数据是检索噪声重要来源。
6.2 检索链路层面
- 不要单纯依赖相似度检索,生产环境务必增加Rerank重排序;
- 混合检索方案:关键词检索(BM25)+向量检索融合,弥补Embedding无法精准匹配专有名词的缺陷;
- 控制召回文档数量,过多文档带来信息过载,更容易诱发幻觉。
6.3 模型与提示词层面
- temperature尽可能调低,知识库问答场景建议0~0.1;
- 提示词约束不能只是简单一句话,清晰定义违规后果;
- 区分“无法回答”标准,引导模型坦诚承认信息缺失,而不是强行编造。
6.4 系统架构层面
高可靠业务场景推荐三级防护:
优化检索链路 → 强约束Prompt → 后置幻觉校验
三级机制叠加,幻觉发生率可以降低60%以上。
7 总结与展望
大模型幻觉无法被100%根除,但通过LangChain搭建优化后的RAG系统,可以极大降低幻觉带来的业务风险。基础RAG只能实现初步约束,想要达到生产可用标准,必须在文档预处理、多路检索、重排序、自校正、结果校验多维度持续优化。
未来优化方向可以结合LangGraph构建Self-RAG、自适应检索智能体;引入结构化输出(JSON格式输出引用来源),让模型标注每一条答案对应的文档片段,方便人工溯源核查。对于金融、政务等高要求场景,还可以增加人工复核接口,形成人机协同的问答体系。RAG不是最终方案,却是当下平衡成本、落地难度、幻觉抑制效果最优的工程选择。
更多推荐



所有评论(0)