一、RAG 技术核心概述
Retrieval-Augmented Generation(检索增强生成,简称 RAG)是当前大模型应用开发的核心技术范式,它解决了大模型 "知识过时""幻觉严重""无法处理私有数据" 三大核心问题。其核心逻辑是:先从私有知识库(如 PDF 文档)中检索与用户问题相关的信息,再将这些信息作为上下文传给大模型,让模型基于检索到的精准信息生成回答。
二、RAG 核心
2.1 整体代码
python
from langchain.chains import ConversationalRetrievalChain
from langchain_community.document_loaders import PyPDFLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_openai import ChatOpenAI
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import DashScopeEmbeddings
#嵌入模型
def qa_agent(openai_api_key, memory, uploaded_file, question):
model = ChatOpenAI(model="qwen3.5-plus",
openai_api_key="sk-8a107f8b6d8a48b0a19bca255554484a",
openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1")
file_content = uploaded_file.read()
temp_file_path = "卢浮宫.pdf"
with open(temp_file_path, "wb") as temp_file:
temp_file.write(file_content)
loader = PyPDFLoader(temp_file_path)
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n", "。", "!", "?", ",", "、", ""]
)
texts = text_splitter.split_documents(docs)
embeddings_model = DashScopeEmbeddings(model="text-embedding-v2",
dashscope_api_key="sk-0b717f29b6ee4852a2331cf1ffa30d4f",
)
db = FAISS.from_documents(texts, embeddings_model)
retriever = db.as_retriever()
qa = ConversationalRetrievalChain.from_llm(
llm=model,
retriever=retriever,
memory=memory
)
response = qa.invoke({"chat_history": memory, "question": question})
return response
2.2Document Loader(文档加载)
将不同格式的文档(PDF/Word/Markdown 等)加载为 LangChain 统一的Document对象,提取文档文本内容和元数据(如页码、文件路径)。
from langchain_community.document_loaders import PyPDFLoader
# 接收上传的PDF文件,先保存为本地临时文件
file_content = uploaded_file.read()
temp_file_path = "卢浮宫.pdf"
with open(temp_file_path, "wb") as temp_file:
temp_file.write(file_content)
# 核心:PyPDFLoader加载PDF文档
loader = PyPDFLoader(temp_file_path)
docs = loader.load()
-
PyPDFLoader:LangChain 针对 PDF 文件的专用加载器,load()方法会将 PDF 的每一页解析为一个Document对象,存储在docs列表中 -
适配性:除了
PyPDFLoader,LangChain 还提供Docx2txtLoader(Word)、TextLoader(纯文本)、UnstructuredFileLoader(通用格式)等,满足不同文档类型需求 -
注意点:上传的文件需先保存为本地文件(Streamlit 等 Web 框架的上传文件为二进制对象,无法直接被 Loader 读取)
2.3Text Splitter(文本分割)
解决大模型 "上下文窗口有限" 的问题:将长文档切割为大小适中的文本块(Chunk),既保证单个文本块能被模型处理,又通过 "重叠部分" 避免语义割裂。
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 初始化递归字符分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每个文本块的最大字符数
chunk_overlap=50, # 相邻文本块的重叠字符数(保证语义连续)
separators=["\n", "。", "!", "?", ",", "、", ""] # 中文分割符
)
texts = text_splitter.split_documents(docs)
RecursiveCharacterTextSplitter :最常用的分割器,优先按指定分隔符分割,若分割后仍超过chunk_size则递归拆分,适合中文文本;
关键参数:
chunk_size:需根据大模型上下文窗口调整(如 qwen3.5-plus 上下文窗口为 8k,可设为 500-1000)
chunk_overlap:一般设为chunk_size的 10%-20%,避免分割后语义断裂
separators:中文需指定中文标点,优先按自然语义分割(如换行、句号),而非强制截断
2.4Text Embedding(文本嵌入)
将文本块转换为计算机可理解的向量(Embedding),向量的余弦相似度可表征文本语义相似度 ------ 这是 "检索" 的核心基础。
from langchain_community.embeddings import DashScopeEmbeddings
# 初始化通义千问嵌入模型
embeddings_model = DashScopeEmbeddings(
model="text-embedding-v2", # 通义千问开源嵌入模型,适配中文
dashscope_api_key="sk-0b717f29b6ee4852a2331cf1ffa30d4f" # 阿里云API密钥
)
-
DashScopeEmbeddings:阿里云通义千问的嵌入模型封装,专为中文优化,效果优于通用的 OpenAI Embeddings -
替代方案:若使用 OpenAI,可替换为
OpenAIEmbeddings(需 OpenAI API 密钥),或使用本地嵌入模型(如 BGE、m3e) -
核心特性:嵌入模型输出的向量维度固定(如 text-embedding-v2 为 768 维),保证向量可被向量库存储和计算
2.5Vector Store(向量库)
存储文本块的向量,提供高效的 "相似性检索" 能力 ------ 用户提问后,先将问题转为向量,再在向量库中快速找到语义最相似的文本块。
from langchain_community.vectorstores import FAISS
# 基于文本块和嵌入模型构建FAISS向量库
db = FAISS.from_documents(texts, embeddings_model)
# 将向量库转为检索器(默认返回Top4相似文本块)
retriever = db.as_retriever()
-
FAISS:Facebook 开源的高效向量检索库,支持亿级向量的快速检索,适合本地 / 轻量级部署 -
核心方法:
-
from_documents:自动将文本块转为向量并存储到 FAISS -
as_retriever():将向量库转为 LangChain 检索器,可通过search_kwargs={"k": 5}调整返回的相似文本块数量
-
-
替代方案:生产环境可使用 Milvus、Pinecone、Weaviate 等分布式向量库。
2.6LLM(大语言模型)+ 对话链
接收检索到的文本块、用户问题和对话记忆,生成精准、有上下文的回答
from langchain_openai import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain
# 初始化通义千问大模型(兼容OpenAI接口)
model = ChatOpenAI(
model="qwen3.5-plus", # 通义千问3.5-plus,性价比高、适配中文
openai_api_key="sk-8a107f8b6d8a48b0a19bca255554484a", # 阿里云API密钥
openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1" # 通义千问兼容接口
)
# 构建对话式检索增强生成链
qa = ConversationalRetrievalChain.from_llm(
llm=model, # 大模型
retriever=retriever,# 检索器
memory=memory # 对话记忆(保存历史问答)
)
# 调用链生成回答
response = qa.invoke({"chat_history": memory, "question": question})
-
ChatOpenAI:LangChain 兼容 OpenAI 接口的大模型封装,可直接对接通义千问、智谱 AI 等兼容 OpenAI 接口的模型 -
ConversationalRetrievalChain:对话式 RAG 核心链,自动完成 "检索 + 生成 + 记忆" 全流程:
-
从
memory中读取历史对话 -
结合历史对话和当前问题,从向量库检索相关文本块
-
将检索结果、历史对话、当前问题传给大模型
-
生成回答并更新
memory
2.7 Memory(对话记忆)
保存历史问答记录,让 RAG 系统具备多轮对话能力
from langchain.memory import ConversationBufferMemory
# 初始化对话记忆
memory = ConversationBufferMemory(
memory_key="chat_history", # 与ConversationalRetrievalChain的参数对应
return_messages=True # 返回消息对象(而非纯文本)
)