玄同 765

大语言模型 (LLM) 开发工程师 | 中国传媒大学 · 数字媒体技术(智能交互与游戏设计)

CSDN · 个人主页 | GitHub · Follow


关于作者

  • 深耕领域:大语言模型开发 / RAG 知识库 / AI Agent 落地 / 模型微调
  • 技术栈:Python | RAG (LangChain / Dify + Milvus) | FastAPI + Docker
  • 工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案

「让 AI 交互更智能,让技术落地更高效」
欢迎技术探讨与项目合作,解锁大模型与智能交互的无限可能!


RAG基础原理与LangChain实战

摘要:本文系统介绍RAG(检索增强生成)的基础原理、核心工作流程,并通过LangChain 1.0实战演示如何构建完整的RAG系统,包括文档加载、切分、向量存储和混合检索。

一、RAG基础概念

1.1 什么是RAG

RAG = Retrieval(检索) + Augmented(增强) + Generation(生成)

RAG即检索增强生成,为LLM提供了从某些数据源检索到的信息,并基于此修正生成的答案。RAG基本上是Search + LLM提示,可以通过大模型回答查询,并将搜索所找到的信息作为大模型的上下文。查询和检索到的上下文都会被注入到发送到LLM的提示语中。

1.2 RAG工作原理

一个简单完整的RAG系统工作流程:

用户提问

知识库检索

获取Top-N相似结果

构建增强Prompt

大语言模型

生成答案

返回用户

用户进行提问后,问题会先去知识库里检索答案,检索到相似度最高的前N个答案,然后和用户的提问一起放入到Prompt里,交给大语言模型,大语言模型根据用户的提问和检索的知识进行整理总结,最终输出返回给用户结果。

1.3 为什么需要RAG

问题 传统LLM RAG解决方案
知识时效性 训练数据有截止日期 实时检索最新信息
幻觉问题 可能编造不存在的信息 基于检索到的真实文档生成
领域专业性 通用知识,缺乏专业深度 接入专业领域知识库
可解释性 黑盒生成 可追溯检索来源

二、RAG核心工作流程

RAG系统的工作流程分为两个阶段:

2.1 阶段一:准备阶段(建立知识库)

这个过程就像是为一个庞大的图书馆建立一本详尽的电子目录。

数据接入

文档解析

文档分割

向量化

向量存储

知识库建立完成

具体步骤:

  1. 数据接入:收集各种文档(PDF、Word、网页等)
  2. 文档解析:提取文本内容
  3. 文档分割:将长文档切分成小片段
  4. 向量化:将文本转换为数学向量(Embedding)
  5. 存储:将向量存入专门的向量数据库

2.2 阶段二:问答阶段(智能应答)

当用户提出问题时,系统开始工作。

用户提问

问题向量化

相似度检索

获取相关文档片段

构建增强提示

LLM生成答案

返回结果

具体步骤:

  1. 用户提问:输入问题
  2. 问题向量化:将问题也转换成向量
  3. 相似度检索:在向量数据库中寻找最相关的文档片段
  4. 构建增强提示:将检索到的文档+原始问题组合成新的提示
  5. 生成答案:大语言模型基于增强后的提示生成最终答案

三、企业RAG核心应用场景

3.1 企业知识库与智能问答

场景描述:企业拥有大量内部文档(员工手册、产品文档、技术规范、会议纪要等),员工需要快速找到准确信息。

实际案例

  • 新员工入职培训问答(降低培训成本)
  • 产品技术规格查询(文档分散在不同系统中)
  • 公司政策咨询(提升搜索效率)

3.2 专业客服与技术支持

场景描述:为客户提供准确、一致的技术支持和问题解答。

RAG优势

  • 基于最新产品文档和解决方案库
  • 提供标准化的准确回答
  • 减少培训时间,提高处理效率

四、LangChain 1.0 RAG实战

4.1 环境准备

依赖安装:

pip install langchain langchain-community langchain-openai langchain-chroma faiss-cpu rank_bm25

模型加载:

from langchain_deepseek import ChatDeepSeek
from langchain_openai.embeddings import OpenAIEmbeddings
from dotenv import load_dotenv

# 加载环境变量
load_dotenv(override=True)

# 使用DeepSeek模型
model = ChatDeepSeek(model="deepseek-chat", temperature=0)

# 使用OpenAI嵌入模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

4.2 文档加载

LangChain支持多种文档加载器:

from langchain_community.document_loaders import TextLoader, Docx2txtLoader

# 读取文本文件
loader = TextLoader("sample_document.txt", encoding="utf-8")
documents = loader.load()

# 读取Word文档
# loader = Docx2txtLoader("document.docx")
# documents = loader.load()

print(f"文档内容预览:\n{documents[0].page_content[:500]}")

4.3 文档切分

为什么需要切分?

  • 大模型有上下文长度限制
  • 细粒度切分提高检索精度
  • 避免无关信息干扰

RecursiveCharacterTextSplitter使用:

from langchain_text_splitters import RecursiveCharacterTextSplitter

# 定义文档切分器
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,                      # 切分文本块大小
    chunk_overlap=50,                    # 文本块重叠大小
    separators=["\n\n", "\n", " ", ""]   # 按照换行符、空格等符号进行切分
)

# 执行切分
texts = text_splitter.split_documents(documents)

print(f"分割后的文本块数量: {len(texts)}")
print(f"第一个文本块内容:\n{texts[0].page_content}")

参数说明:

参数 说明 建议值
chunk_size 每个文本块的最大字符数 500-1000
chunk_overlap 相邻文本块的重叠字符数 50-100
separators 切分优先级顺序 [“\n\n”, “\n”, " ", “”]

4.4 向量存储与检索

4.4.1 创建向量存储(FAISS)
from langchain_community.vectorstores import FAISS

# 创建向量数据库
vector_store = FAISS.from_documents(texts, embeddings)

# 保存到本地
vector_store.save_local("faiss_index")

# 从本地加载
vector_store = FAISS.load_local(
    "faiss_index",
    embeddings,
    allow_dangerous_deserialization=True
)
4.4.2 创建检索器
# 创建基础检索器
retriever = vector_store.as_retriever(
    search_type="similarity",    # 相似度搜索
    search_kwargs={"k": 3}       # 返回top3结果
)

# 执行检索
query = "LangChain的主要特性是什么?"
results = retriever.invoke(query)

for i, doc in enumerate(results):
    print(f"结果{i+1}:\n{doc.page_content}\n")

4.5 混合检索(向量检索 + 关键词检索)

为什么需要混合检索?

  • 向量检索:语义相似度高,但可能遗漏关键词匹配
  • 关键词检索(BM25):精确匹配关键词,但缺乏语义理解
  • 混合检索:结合两者优势,提高召回率和准确率

EnsembleRetriever实现:

from langchain_community.retrievers import BM25Retriever
from langchain_classic.retrievers import EnsembleRetriever

# 1. 创建BM25检索器(基于关键词)
bm25_retriever = BM25Retriever.from_documents(texts)
bm25_retriever.k = 3

# 2. 创建向量检索器(基于语义)
faiss_retriever = vector_store.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 3}
)

# 3. 创建混合检索器
ensemble_retriever = EnsembleRetriever(
    retrievers=[faiss_retriever, bm25_retriever],
    weights=[0.5, 0.5]  # 权重分配
)

# 执行混合检索
results = ensemble_retriever.invoke("LangChain RAG工作流程")

检索方式对比:

检索方式 优势 劣势 适用场景
向量检索 语义理解强,容错性好 对特定关键词不敏感 开放式问题、语义搜索
BM25检索 关键词匹配精确 缺乏语义理解 特定术语、精确匹配
混合检索 兼具语义和关键词优势 计算成本略高 生产环境推荐

五、完整RAG链构建

5.1 基础RAG链

from langchain.chains import RetrievalQA

# 创建RAG链
qa_chain = RetrievalQA.from_chain_type(
    llm=model,
    chain_type="stuff",           # 将所有文档拼接
    retriever=ensemble_retriever,  # 使用混合检索器
    return_source_documents=True   # 返回源文档
)

# 执行问答
query = "LangChain 1.0有哪些改进?"
result = qa_chain.invoke({"query": query})

print(f"答案:{result['result']}")
print(f"\n参考来源:")
for doc in result['source_documents']:
    print(f"- {doc.page_content[:100]}...")

5.2 自定义Prompt的RAG

from langchain.prompts import PromptTemplate

# 自定义Prompt模板
custom_prompt = PromptTemplate(
    template="""基于以下上下文信息回答问题。如果上下文不包含答案,请说"我无法从提供的文档中找到答案"。

上下文:
{context}

问题:{question}

请提供详细且准确的回答:""",
    input_variables=["context", "question"]
)

# 创建自定义RAG链
qa_chain = RetrievalQA.from_chain_type(
    llm=model,
    chain_type="stuff",
    retriever=ensemble_retriever,
    chain_type_kwargs={"prompt": custom_prompt}
)

六、敏感数据处理

6.1 分离存储策略

对于包含敏感信息的数据,建议单独存储:

# 敏感数据文档切分
sensitive_texts = text_splitter.split_documents(sensitive_documents)

# 创建敏感数据向量库
sensitive_vector_store = FAISS.from_documents(sensitive_texts, embeddings)
sensitive_vector_store.save_local("sensitive_faiss_index")

# 加载敏感数据检索器
sensitive_retriever = sensitive_vector_store.as_retriever(
    search_kwargs={"k": 3}
)

6.2 权限控制

def get_retriever(user_role):
    """根据用户角色返回对应的检索器"""
    if user_role == "admin":
        # 管理员可以访问所有数据
        return ensemble_retriever
    else:
        # 普通用户只能访问公开数据
        return public_retriever

七、总结

主题 核心内容
RAG基础 Retrieval + Augmented + Generation,解决知识时效性和幻觉问题
工作流程 准备阶段(文档处理+向量化)+ 问答阶段(检索+生成)
LangChain实战 文档加载、RecursiveCharacterTextSplitter切分、FAISS向量存储
混合检索 EnsembleRetriever结合向量检索和BM25关键词检索
最佳实践 敏感数据分离存储、自定义Prompt、权限控制

通过本文介绍的基础RAG流程,开发者可以构建一个功能完整的检索增强生成系统。在下一篇文章中,我们将探讨更高级的Agentic RAG架构,让RAG系统具备自主规划和迭代优化的能力。

参考资源

  • LangChain RAG文档:https://python.langchain.com/docs/use_cases/question_answering/
  • FAISS官方文档:https://github.com/facebookresearch/faiss
  • BM25算法详解:https://en.wikipedia.org/wiki/Okapi_BM25
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐