与大型PDF文件对话很酷。你可以与你的笔记、书籍和文档等进行聊天。这篇博客文章将帮助你构建一个基于Streamlit的多RAG web应用,通过对话式AI聊天机器人读取、处理和交互PDF数据。以下是该应用程序如何工作的分步说明,使用简单易懂的语言。
该应用程序开始时导入了各种强大的库:
- Streamlit: 用于创建网页界面。
- PyPDF2: 一个用于读取PDF文件的工具。
- Langchain: 一套用于自然语言处理和创建对话AI的工具。
- FAISS: 一个用于高效向量相似性搜索的库,在大型数据集中快速查找信息时非常有用。
import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.embeddings.spacy_embeddings import SpacyEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.tools.retriever import create_retriever_tool
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain.agents import AgentExecutor, create_tool_calling_agent
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
阅读和处理PDF文件
我们应用程序的第一个主要功能是设计来读取PDF文件的:
- PDF阅读器: 当用户上传一个或多个PDF文件时,应用程序会读取这些文档的每一页,并提取文本,将其合并成一个连续的字符串。
- 文本分割: 使用Langchain库将文本分割成每个1000字符的片段。这种分割有助于更高效地处理和分析文本。
def pdf_read(pdf_doc):
text = ""
for pdf in pdf_doc:
pdf_reader = PdfReader(pdf)
for page in pdf_reader.pages:
text += page.extract_text()
return text
def get_chunks(text):
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = text_splitter.split_text(text)
return chunks
创建可搜索的文本数据库并制作嵌入式向量
为了使文本可搜索,应用程序将文本片段转换为向量表示:
- 向量存储: 应用程序使用FAISS库将文本片段转换为向量,并将这些向量本地保存。这一转换至关重要,因为它允许系统在文本中执行快速和高效的搜索。
embeddings = SpacyEmbeddings(model_name="en_core_web_sm")
def vector_store(text_chunks):
vector_store = FAISS.from_texts(text_chunks, embedding=embeddings)
vector_store.save_local("faiss_db")
设置对话式AI
这个应用程序的核心是对话式AI,它使用了OpenAI的强大模型:
- AI配置: 应用程序使用OpenAI的GPT模型来设置对话式AI。这个AI被设计成根据处理过的PDF内容来回答问题。
- 对话链: AI使用一组提示来理解上下文并准确回答用户的查询。如果问题的答案不在文本中,AI会被编程回答“答案不在上下文中”,以确保用户不会收到错误信息。
def get_conversational_chain(tools, ques):
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0, api_key="")
prompt = ChatPromptTemplate.from_messages([...])
tool=[tools]
agent = create_tool_calling_agent(llm, tool, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tool, verbose=True)
response=agent_executor.invoke({"input": ques})
print(response)
st.write("回复: ", response['output'])
def user_input(user_question):
new_db = FAISS.load_local("faiss_db", embeddings,allow_dangerous_deserialization=True)
retriever=new_db.as_retriever()
retrieval_chain= create_retriever_tool(retriever,"pdf_extractor","此工具用于回答来自PDF的查询")
get_conversational_chain(retrieval_chain,user_question)
用户交互
在后端准备就绪后,应用程序使用Streamlit创建一个用户友好的界面:
- 用户界面: 用户会看到一个简单的文本输入框,可以在其中输入与PDF内容相关的问题。应用程序会直接在网页上显示AI的回答。
- 文件上传和处理: 用户可以随时上传新的PDF文件。应用程序会实时处理这些文件,并将新的文本更新到数据库中,供AI搜索。
def main():
st.set_page_config("Chat PDF")
st.header("基于RAG的PDF聊天")
user_question = st.text_input("从PDF文件中提问")
if user_question:
user_input(user_question)
with st.sidebar:
pdf_doc = st.file_uploader("上传您的PDF文件并点击提交和处理按钮", accept_multiple_files=True)
if st.button("提交并处理"):
with st.spinner("处理中..."):
raw_text = pdf_read(pdf_doc)
text_chunks = get_chunks(raw_text)
vector_store(text_chunks)
st.success("完成")
结论
答案流式的流程图
整个代码 import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.embeddings.spacy_embeddings import SpacyEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.tools.retriever import create_retriever_tool
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain.agents import AgentExecutor, create_tool_calling_agent
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
embeddings = SpacyEmbeddings(model_name="en_core_web_sm")
def pdf_read(pdf_doc):
text = ""
for pdf in pdf_doc:
pdf_reader = PdfReader(pdf)
for page in pdf_reader.pages:
text += page.extract_text()
return text
def get_chunks(text):
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = text_splitter.split_text(text)
return chunks
def vector_store(text_chunks):
vector_store = FAISS.from_texts(text_chunks, embedding=embeddings)
vector_store.save_local("faiss_db")
def get_conversational_chain(tools,ques):
#os.environ["ANTHROPIC_API_KEY"]=os.getenv["ANTHROPIC_API_KEY"]
#llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=0, api_key=os.getenv("ANTHROPIC_API_KEY"),verbose=True)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0, api_key="")
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"""您是一个乐于助人的助手。请根据提供的上下文尽可能详细地回答问题,确保提供所有细节。如果答案不在提供的上下文中,请回答“答案不在上下文中”,不要提供错误的答案。""",
),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
]
)
tool=[tools]
agent = create_tool_calling_agent(llm, tool, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tool, verbose=True)
response=agent_executor.invoke({"input": ques})
print(response)
st.write("回复: ", response['output'])
def user_input(user_question):
new_db = FAISS.load_local("faiss_db", embeddings,allow_dangerous_deserialization=True)
retriever=new_db.as_retriever()
retrieval_chain= create_retriever_tool(retriever,"pdf_extractor","此工具用于回答来自PDF的查询")
get_conversational_chain(retrieval_chain,user_question)
def main():
st.set_page_config("与PDF聊天")
st.header("基于RAG的PDF聊天")
user_question = st.text_input("从PDF文件中提问")
if user_question:
user_input(user_question)
with st.sidebar:
st.title("菜单:")
pdf_doc = st.file_uploader("上传您的PDF文件并点击提交和处理按钮", accept_multiple_files=True)
if st.button("提交并处理"):
with st.spinner("处理中..."):
raw_text = pdf_read(pdf_doc)
text_chunks = get_chunks(raw_text)
vector_store(text_chunks)
st.success("完成")
if __name__ == "__main__":
main()
通过将其保存为 app.py 然后运行来启动应用程序。
输出:执行 streamlit run app.py
看起来是这样的!
如果你喜欢这篇博客,也应该看看我在 Instagram 上发布的视频:https://www.instagram.com/parasmadan.in/
如有任何疑问,欢迎通过 hello@parasmadan.in 联系我。