实施 RAG 构建多 PDF 聊天应用程序
检索增强生成(RAG)技术通过连接外部资源提高大模型准确性,减少幻觉。介绍 RAG 原理及两个阶段:预处理加载数据并嵌入向量数据库,推理时检索相关片段生成答案。基于 LangChain 和 ChromaDB,提供构建“多 PDF 聊天”应用的具体代码实现,涵盖文件加载、文本分块、向量化存储及查询链路的搭建流程。

检索增强生成(RAG)技术通过连接外部资源提高大模型准确性,减少幻觉。介绍 RAG 原理及两个阶段:预处理加载数据并嵌入向量数据库,推理时检索相关片段生成答案。基于 LangChain 和 ChromaDB,提供构建“多 PDF 聊天”应用的具体代码实现,涵盖文件加载、文本分块、向量化存储及查询链路的搭建流程。

在使用像 GPT、Claude、BERT 等 LLM 模型时,您可能遇到以下问题:
如果您对上述问题感同身受,是时候了解 RAG 了。
RAG (检索增强生成) 是一种通过从外部资源获取事实来提高生成 AI 模型准确性和可靠性的技术。RAG 是一种重要的技术,因为:
从高层次来看,整个 RAG 过程分为两个阶段:
![图片:RAG 整体流程图]
让我们深入了解这两个阶段。
![图片:数据加载与向量化流程]
这个过程在 langchain 框架的支持下很容易完成。
将文本拆分为小块,以优化信息的处理、存储和检索,同时提高 AI 系统的质量和准确性。
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 设置分块参数
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
)
向量数据库被认为是 RAG 实现堆栈中最常见的方式(在本文中,我也选择了一个可以轻松在本地磁盘上运行的向量数据库,即 Chroma)。选择最佳向量数据库的内容在本文中未涉及。
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
# 初始化向量存储
vector_store = Chroma.from_documents(documents=documents, embedding=OpenAIEmbeddings())
![图片:查询与生成流程]
输入查询的用户需要得到回答或处理。
使用嵌入模型将查询转换为嵌入。
使用查询的向量表示从包含嵌入文本的大型数据库中查找相关文本。
提取的文本将与原始查询一起用于生成新的答案或文本。生成器(通常是大型语言模型)将结合这些文本段落中的信息生成反馈。
创建的文本将作为完整答案返回给用户。
一旦你了解了 RAG 的工作原理,就该和我一起构建一个'与多个 PDF 聊天'的应用了。并看看我如何将 RAG 应用到实际应用中。
首先,我们需要安装所有必要的包。
pip install langchain chromadb pypdf streamlit openai python-dotenv
将 OPENAI_API_KEY 替换为您自己的密钥。在示例中,我们建议使用 .env 文件或 Streamlit Secret 来管理密钥。
import os
from dotenv import load_dotenv
load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
在 ChromaDB 中创建名为 'chat-with-pdf' 的集合。
from langchain.vectorstores import Chroma
persist_directory = "chroma_db"
vectorstore = Chroma(persist_directory=persist_directory, embedding_function=OpenAIEmbeddings())
为了与集合一起工作,我们将使用函数 get_collection。
def get_collection():
return Chroma(persist_directory=persist_directory, embedding_function=OpenAIEmbeddings())
当用户上传一些新文件时:
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
def process_pdf(file_path):
loader = PyPDFLoader(file_path)
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)
vectorstore = get_collection()
vectorstore.add_documents(texts)
return len(texts)
否则,当用户从列表中删除文件时,我们需要删除所有相关的块。
def delete_from_collection(file_name):
# 根据文件名过滤元数据并删除对应的文档 ID
# 注意:ChromaDB 删除操作通常基于 ID,需维护文件名与 ID 的映射
pass
将两个方法合并为一个函数,用于管理文件的增删逻辑。
def manage_documents(action, file_path=None):
if action == "add":
return process_pdf(file_path)
elif action == "delete":
return delete_from_collection(file_path)
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
llm = OpenAI(temperature=0, model_name="gpt-3.5-turbo-instruct")
qa_chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever)
每当你想使用 retriever_chain 时,可以调用 invoke。例如:
query = "这个 PDF 里关于 RAG 的定义是什么?"
result = qa_chain.invoke({"query": query})
print(result["result"])
为了让应用更易用,我们可以使用 Streamlit 构建一个简单的界面。
import streamlit as st
st.title("Chat with PDF")
uploaded_file = st.file_uploader("Choose a PDF file", type="pdf")
if uploaded_file is not None:
# 保存临时文件
with open("temp.pdf", "wb") as f:
f.write(uploaded_file.getvalue())
# 处理文件
count = process_pdf("temp.pdf")
st.success(f"Processed {count} chunks.")
# 查询
user_input = st.text_input("Ask a question:")
if user_input:
response = qa_chain.invoke({"query": user_input})
st.write(response["result"])
通过上述步骤,我们成功构建了一个基于 RAG 的多 PDF 聊天应用。该应用利用 LangChain 框架实现了数据的加载、分块、向量化以及检索增强生成的核心流程。用户不仅可以上传多个 PDF 文件进行知识库构建,还能通过自然语言提问来获取精准的信息片段。这种架构有效解决了大模型知识滞后和幻觉问题,为企业内部知识管理和智能问答提供了可行的解决方案。
在实际部署中,建议进一步优化向量检索策略(如混合检索),增加权限控制,并对长文档进行更精细的分块处理,以提升系统的响应速度和准确率。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online