引言:当ChatGPT“读”懂你的私人文件
ChatGPT、Claude等大语言模型(LLM)上知天文下知地理,但它们有一个共同的“缺陷”:它们不知道你的私有知识。它们没有读过你公司的内部文档,不了解你的项目报告,也无法访问你的个人知识库。
那么,如何让AI“学习”你的私有数据,并基于这些数据来回答问题呢?
答案就是目前AI应用领域最炙手可热的技术——RAG(Retrieval-Augmented Generation,检索增强生成)。
简单来说,RAG就是给大模型外挂一个“知识库”和“搜索引擎”。当用户提问时,系统先从你的知识库里检索出最相关的信息,然后把这些信息连同用户的问题一起交给大模型,让它基于你提供的“开卷材料”来生成答案。
这篇「保姆级」教程,就将带你一步步用Python构建一个可以与你的PDF文档对话的AI。
RAG的工作原理(三步走)
理解RAG的原理是关键。整个过程可以清晰地分为两个阶段:数据索引和检索生成。
阶段一:数据索引(Indexing)—— 制作“开卷材料”
这个阶段是预处理,把你的文档变成AI能够理解和检索的格式。
- 加载 (Load): 首先,程序需要把你的文档(比如一个PDF文件)加载进来。
- 分割 (Split): 一篇长文档对于模型来说太大了,需要把它切分成许多个更小的、有意义的文本块(Chunks)。
- 嵌入 (Embed): 这是最神奇的一步。使用一个“嵌入模型”(Embedding Model),将每一个文本块都转换成一串由几百上千个数字组成的列表,我们称之为“向量”(Vector)。这个向量就像是这个文本块在数学空间中的“语义坐标”。意思相近的文本块,它们的向量也更接近。
- 存储 (Store): 将所有文本块及其对应的向量,存入一个专门用于高效检索向量的数据库——“向量数据库”(Vector Database)中。
阶段二:检索与生成(Retrieval & Generation)—— “开卷考试”
这个阶段是当用户真正来提问时发生的。
- 用户提问 & 嵌入: 当用户输入问题时,程序使用相同的“嵌入模型”,将问题也转换成一个“问题向量”。
- 检索 (Retrieve): 用这个“问题向量”去向量数据库中进行搜索,找出与它“距离”最近、最相似的几个“文本块向量”。这些文本块就是与问题最相关的内容。
- 生成 (Generate): 将用户原始的问题,和上一步检索到的几个相关文本块,一起“打包”成一个新的、内容更丰富的Prompt,然后发送给大语言模型(LLM)。
最终,LLM会根据你提供的这些高度相关的“开卷材料”来回答问题,而不是依赖它自己固有的、可能过时或无关的知识。这样得到的答案就既准确又贴近你的私有数据了。
动手实践:构建PDF问答AI
理论讲完,让我们卷起袖子开始编码!
准备工作
-
安装必要的Python库:
langchain
: 强大的LLM应用开发框架。openai
: 用于调用OpenAI的模型(LLM和Embedding)。faiss-cpu
: Facebook开源的高性能向量相似度搜索库,这里作为我们的向量数据库。tiktoken
: OpenAI用于计算token的库。pypdf
: 用于加载PDF文件的库。pip install langchain openai faiss-cpu tiktoken pypdf
-
准备你的PDF文件: 找一个你想要AI学习的PDF文件,将它命名为
document.pdf
并放在与你的Python脚本相同的目录下。 -
获取OpenAI API Key: 你需要一个OpenAI账号并生成API Key,因为我们将使用它的GPT模型作为LLM,以及它的Embedding模型。获取后,将其设置为环境变量。
import os os.environ["OPENAI_API_KEY"] = "sk-Your-API-Key-Here"
完整代码
下面是实现这个PDF问答机器人的完整Python代码。我们已经将上述的RAG流程清晰地对应到了代码的每一步。
import os
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_retrieval_chain
# 在这里替换成你的OpenAI API Key
os.environ["OPENAI_API_KEY"] = "sk-..."
# --- 1. 数据索引阶段 ---
# 1a. 加载PDF文档
print("正在加载PDF文档...")
loader = PyPDFLoader("document.pdf") # 请确保你的PDF文件名是这个
docs = loader.load()
print(f"文档加载成功,共 {len(docs)} 页。")
# 1b. 分割文档成小块 (Chunks)
print("正在分割文档...")
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
print(f"文档分割成功,共得到 {len(splits)} 个文本块。")
# 1c. 嵌入文本并存入向量数据库 (FAISS)
print("正在创建向量数据库...")
# 使用OpenAI的嵌入模型,并将文本块存入FAISS向量存储中
vectorstore = FAISS.from_documents(documents=splits, embedding=OpenAIEmbeddings())
print("向量数据库创建成功!")
# --- 2. 检索与生成阶段 ---
# 2a. 定义大语言模型 (LLM) 和 Prompt模板
llm = ChatOpenAI(model="gpt-3.5-turbo")
prompt = ChatPromptTemplate.from_template("""请只根据以下上下文来回答问题:
<context>
{context}
</context>
Question: {input}""")
# 2b. 创建一个文档处理链 (Stuff Documents Chain)
# 这条链的作用是接收文档列表,将它们整合到prompt中,然后调用LLM
document_chain = create_stuff_documents_chain(llm, prompt)
# 2c. 从向量数据库创建一个检索器 (Retriever)
# 检索器的作用是根据用户的输入,从向量数据库中找出相关的文档
retriever = vectorstore.as_retriever()
# 2d. 创建核心的检索链 (Retrieval Chain)
# 这条链将检索器和文档处理链连接起来:
# 1. 它接收用户问题。
# 2. 将问题传给检索器,获取相关文档。
# 3. 将问题和相关文档传给文档处理链,获取最终答案。
retrieval_chain = create_retrieval_chain(retriever, document_chain)
# --- 3. 开始提问! ---
print("\n--- 准备就绪,可以开始提问了!(输入'exit'退出) ---")
while True:
user_question = input("你的问题是: ")
if user_question.lower() == 'exit':
break
# 调用检索链,传入问题
response = retrieval_chain.invoke({"input": user_question})
# 打印答案
print("AI的回答:", response["answer"])
print("-" * 20)
如何运行
- 将上述代码保存为一个Python文件(例如
pdf_chatbot.py
)。 - 确保
document.pdf
和该脚本在同一目录下。 - 在代码中填入你的OpenAI API Key。
- 打开终端,运行脚本:
python pdf_chatbot.py
- 等待所有索引步骤完成后,你就可以在终端里向你的PDF提问了!
总结与展望
恭喜你,你已经成功构建了一个属于自己的、具备私有知识问答能力的AI应用!
这只是RAG世界的起点。基于这个框架,你可以进行无限扩展:
- 更换知识源:加载的不仅可以是PDF,还可以是TXT文件、网页、Notion数据库等。
- 更换向量数据库:除了在内存中运行的FAISS,你还可以使用Chroma、Pinecone等更专业的持久化向量数据库。
- 更换LLM:将
ChatOpenAI
换成开源模型,比如通过Ollama
在本地运行的Llama 3,实现一个完全私有化的RAG系统。
希望这篇教程能帮助你打开AI应用开发的大门。快去用你自己的文档试试看吧!
...