Pular para o conteúdo principal

Capítulo 1: Construindo um Sistema de Q&A para Documentos

Visão Geral do Projeto​

Construa um sistema completo de perguntas e respostas para PDFs com:

  • Upload e processamento de PDF
  • Interface de chat com histórico
  • Citações de fontes

Arquitetura​

Passo 1: Configuração​

# requirements.txt
langchain==0.1.0
openai==1.3.0
chromadb==0.4.0
streamlit==1.28.0
pypdf==3.17.0

Passo 2: Processamento de Documentos​

# document_processor.py
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

def process_pdf(pdf_path, collection_name="docs"):
# Load
loader = PyPDFLoader(pdf_path)
documents = loader.load()

# Split
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
chunks = splitter.split_documents(documents)

# Embed and store
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(
chunks,
embeddings,
collection_name=collection_name,
persist_directory="./chroma_db"
)

return vectorstore

Passo 3: RAG Chain​

# rag_chain.py
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory

def create_qa_chain(vectorstore):
llm = ChatOpenAI(model="gpt-4", temperature=0)

memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer"
)

chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
memory=memory,
return_source_documents=True
)

return chain

Passo 4: Interface Streamlit​

# app.py
import streamlit as st
from document_processor import process_pdf
from rag_chain import create_qa_chain

st.title("📄 Q&A de Documentos")

# File upload
uploaded_file = st.file_uploader("Envie um PDF", type="pdf")

if uploaded_file:
# Process PDF
with st.spinner("Processando..."):
vectorstore = process_pdf(uploaded_file)
chain = create_qa_chain(vectorstore)

# Chat interface
if "messages" not in st.session_state:
st.session_state.messages = []

for msg in st.session_state.messages:
st.chat_message(msg["role"]).write(msg["content"])

if prompt := st.chat_input("Pergunte sobre seu documento"):
st.session_state.messages.append({"role": "user", "content": prompt})
st.chat_message("user").write(prompt)

response = chain({"question": prompt})
answer = response["answer"]

st.session_state.messages.append({"role": "assistant", "content": answer})
st.chat_message("assistant").write(answer)

# Show sources
with st.expander("Fontes"):
for doc in response["source_documents"]:
st.write(f"Página {doc.metadata.get('page', 'N/A')}")
st.write(doc.page_content[:200] + "...")

Executando o App​

streamlit run app.py

Melhorias​

  • Adicionar autenticação
  • Suportar múltiplos PDFs
  • Exportar conversas
  • Adicionar reranking