Sistema RAG em Python: como criar um bot que responde perguntas a partir de PDFs
Neste guia você vai aprender a criar um sistema RAG que responde perguntas com base em PDFs, usando Python, LangChain e a API da OpenAI.
Um sistema RAG (Retrieval-Augmented Generation) em Python combina busca em documentos com um modelo de IA: os PDFs são divididos em trechos, transformados em embeddings e guardados em um banco vetorial (como o Chroma); a cada pergunta, o sistema recupera os trechos mais relevantes e o modelo responde com base neles.
O exemplo que utilizaremos aqui usa um PDF com FAQs do curso de Python da Hashtag Programação, mas você pode adaptar para qualquer documento.
O projeto é dividido em dois scripts: um para criar um banco de dados vetorizado e outro para o chatbot interativo.
Faça o download aqui embaixo e bora aprender!
Para fazer o download do(s) arquivo(s) utilizados na aula, preencha com o seu e-mail:
Não vamos te encaminhar nenhum tipo de SPAM! A Hashtag Treinamentos é uma empresa preocupada com a proteção de seus dados e realiza o tratamento de acordo com a Lei Geral de Proteção de Dados (Lei n. 13.709/18). Qualquer dúvida, nos contate.
O que é RAG e como funciona?
RAG combina recuperação de informações com geração de respostas por modelos de linguagem (LLMs). O sistema busca trechos relevantes (chunks) em uma base de conhecimento (ex.: um PDF) e usa esses trechos para gerar respostas precisas.
- Como funciona um sistema RAG?
- Carrega documentos: Lê PDFs, por exemplo, e extrai texto.
- Divide em chunks: Separa o texto em pedaços, para eficiência.
- Vetorize: Converte chunks em vetores numéricos (embeddings) para busca semântica.
- Consulta: Compara a pergunta do usuário (vetorizada) com a base vetorizada.
- Responde: Usa a LLM para gerar respostas com base nos chunks selecionados.
Vantagens:
- Respostas específicas com base na sua base de conhecimento.
- Menor custo (menos tokens enviados à LLM).
- Maior velocidade de resposta.
Estrutura do projeto
- Pastas e arquivos:
- /base: Contém o(s) PDF(s) da base de conhecimento.
- criar_db.py: Cria o banco de dados vetorizado.
- main.py: Script do chatbot para interagir com o usuário.
Passo a passo: Código do sistema RAG
1. Instalando bibliotecas
Instale as bibliotecas necessárias no console:
pip install python-dotenv langchain langchain-openai langchain-community langchain-chroma chromadb openai pypdf
- python-dotenv: Carrega a chave da API da OpenAI.
- langchain: Framework para RAG.
- langchain-openai: Integração com OpenAI.
- langchain-community: Ferramentas para leitura de PDFs.
- langchain-chroma: Banco de dados vetorizado Chroma.
- chromadb: Suporte ao Chroma.
- pypdf: Extrai texto de PDFs.
Crie um arquivo .env com sua chave da API da OpenAI (obtida em platform.openai.com):
OPENAI_API_KEY=sk-xxx
2. Criando o banco de dados vetorizado (criar_db.py)
Este script carrega PDFs da pasta /base, divide em chunks e armazena em um banco vetorizado com Chroma.
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from dotenv import load_dotenv
load_dotenv()
def perguntar():
caminho_db = "db"
funcao_embedding = OpenAIEmbeddings()
db = Chroma(persist_directory=caminho_db, embedding_function=funcao_embedding)
pergunta = input("Escreva sua pergunta: ")
resultados = db.similarity_search_with_relevance_scores(pergunta, k=3)
if not resultados or resultados[0][1] < 0.7:
print("Não consegui encontrar informação relevante na base.")
return
textos_resultados = [resultado[0].page_content for resultado in resultados]
base_conhecimento = "\n\n----\n\n".join(textos_resultados)
prompt_template = ChatPromptTemplate.from_template(
"Responda à pergunta do usuário com base nas informações abaixo:\n\n{base_conhecimento}\n\nPergunta: {pergunta}"
)
prompt = prompt_template.invoke({"pergunta": pergunta, "base_conhecimento": base_conhecimento})
modelo = ChatOpenAI()
texto_resposta = modelo.invoke(prompt).content
print(f"Resposta da IA: {texto_resposta}")
if __Name__ == "__main__":
perguntar()- Explicação:
- carregar_documentos: Lê todos os PDFs da pasta /base.
- dividir_em_chunks: Divide documentos em pedaços de 2000 caracteres com 500 caracteres de sobreposição para evitar cortes.
- vetorizar_chunks: Converte chunks em vetores com OpenAIEmbeddings e salva no banco Chroma na pasta /db.
- criar_banco_de_dados: Orquestra as três etapas.
Saída esperada: “Total de chunks: 19” (dependendo do PDF) e criação da pasta /db.
3. Criando o chatbot interativo (main.py)
Este script permite que o usuário faça perguntas e receba respostas com base no banco vetorizado.
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from dotenv import load_dotenv
load_dotenv()
def perguntar():
caminho_db = "db"
funcao_embedding = OpenAIEmbeddings()
db = Chroma(persist_directory=caminho_db, embedding_function=funcao_embedding)
pergunta = input("Escreva sua pergunta: ")
resultados = db.similarity_search_with_relevance_scores(pergunta, k=3)
if not resultados or resultados[0][1] < 0.7:
print("Não consegui encontrar informação relevante na base.")
return
textos_resultados = [resultado[0].page_content for resultado in resultados]
base_conhecimento = "\n\n----\n\n".join(textos_resultados)
prompt_template = ChatPromptTemplate.from_template(
"Responda à pergunta do usuário com base nas informações abaixo:\n\n{base_conhecimento}\n\nPergunta: {pergunta}"
)
prompt = prompt_template.invoke({"pergunta": pergunta, "base_conhecimento": base_conhecimento})
modelo = ChatOpenAI()
texto_resposta = modelo.invoke(prompt).content
print(f"Resposta da IA: {texto_resposta}")
if __Name__ == "__main__":
perguntar()- Explicação:
- load_dotenv: Carrega a chave da API.
- Chroma: Carrega o banco vetorizado de /db.
- similarity_search_with_relevance_scores: Busca até 3 chunks com relevância mínima de 0.7.
- ChatPromptTemplate: Monta o prompt com a pergunta e os chunks.
- ChatOpenAI: Gera a resposta usando a API da OpenAI.
Exemplo de uso:
- Pergunta: “Quais os projetos do Python Impressionador?”
- Resposta: “Os projetos incluem automação de processos, inteligência artificial, web scraping, criação de sites, aplicativos e e-commerce.”
Como otimizar o sistema RAG?
- Chunk size: Aumente para 3000 caracteres se as respostas estiverem incompletas.
- Chunk overlap: Mantenha 500-1000 caracteres para evitar cortes.
- Relevance score: Ajuste o limite (ex.: 0.5 para mais resultados, 0.7 para precisão).
- Parâmetro k: Aumente para 4 chunks se precisar de mais contexto.
- Prompt: Use instruções claras, como “Responda com base nas informações fornecidas”, evitando “Não sei” para forçar o uso dos chunks.
Perguntas frequentes
1. O que é RAG?
RAG, ou Retrieval-Augmented Generation, é a técnica que conecta um modelo de linguagem aos seus próprios documentos: antes de responder, o sistema busca os trechos mais relevantes da base e os entrega ao modelo como contexto. A resposta sai fundamentada no seu conteúdo, e não só no conhecimento genérico da IA.
2. Por que usar RAG em vez de perguntar direto ao modelo?
Porque o modelo sozinho não conhece seus arquivos internos e pode inventar detalhes. Com RAG, a resposta é ancorada nos documentos recuperados — manuais, contratos, apostilas —, reduzindo alucinações e permitindo citar a fonte. É o caminho padrão para chatbots corporativos com conhecimento próprio.
3. O que é um banco vetorial como o Chroma?
É um banco que armazena embeddings — vetores numéricos que representam o significado de cada trecho de texto. Na consulta, a pergunta também vira vetor, e o banco retorna os trechos semanticamente mais próximos, mesmo sem palavras idênticas. O Chroma é uma opção open source simples de usar no Python.
4. Preciso da API da OpenAI para montar um RAG?
O projeto do post usa a API da OpenAI junto com LangChain e Chroma, mas a arquitetura aceita alternativas: modelos locais via Ollama, outras APIs de IA e diferentes bancos vetoriais. Mudam as credenciais e o custo por chamada; o fluxo de ingestão, busca e resposta continua o mesmo.
Conclusão
Com este sistema RAG, você pode criar assistentes de IA que respondem perguntas com base em PDFs de forma eficiente.
Se quiser desenvolver seu sistema, experimente integrar uma interface com Streamlit, adicionar mais PDFs à pasta /base ou testar diferentes valores de chunk_size, chunk_overlap e k.
Se você gostou deste conteúdo, vai gostar também dos nossos outros conteúdos sobre Python em nosso blog!
E caso prefira esse conteúdo no formato de vídeo, assista aqui embaixo ou acesse o nosso canal do YouTube!
O que você aprende neste vídeo
Resposta rápida: Um sistema RAG divide os documentos em pedaços, transforma cada pedaço em uma lista de números e guarda tudo em um banco vetorial. A cada pergunta ele compara os números, recupera só os trechos mais próximos e manda apenas eles para o modelo responder. Isso corta custo e tempo, e a vetorização acontece uma vez só, não a cada pergunta.
Neste vídeo (61 min):
- 1:00 - O que a sigla significa, e o que muda em relação a perguntar direto ao chat.
- 2:00 - As três peças do sistema: quem pergunta, o modelo e o banco vetorial.
- 3:00 - Por que a base de conhecimento é dividida em pedaços antes de qualquer coisa.
- 4:00 - Os dois motivos de não mandar o documento inteiro: velocidade e custo.
- 5:00 - O que é embedding: transformar um trecho de texto em uma lista de números.
- 7:00 - A comparação por distância entre vetores, e como ela escolhe o trecho certo.
- 10:00 - Os dois scripts do projeto, e por que a vetorização acontece uma vez só.
- 11:00 - As bibliotecas necessárias e para que serve cada uma delas.
- 14:40 - O mesmo modelo de embedding tem de valer para a base e para a pergunta.
- 20:00 - O tamanho de cada pedaço, e como ele depende do tipo de resposta esperada.
- 23:00 - A sobreposição entre pedaços, que evita resposta cortada ao meio.
- 29:00 - Gerar os embeddings e gravar o banco vetorial no disco.
- 40:00 - A busca por similaridade e a nota que cada resultado recebe.
- 44:00 - O corte mínimo de nota, para o sistema admitir que não encontrou a resposta.
Trechos do vídeo:
- Os pedaços se sobrepõem de propósito: sem isso, uma resposta que começa no fim de um pedaço e termina no começo do outro chegaria pela metade ao modelo.
- Cada resultado da busca vem com uma nota de proximidade. Definir um corte mínimo é o que permite ao sistema responder que não encontrou, em vez de inventar a partir de um trecho pouco relacionado.
Hashtag Treinamentos
Para acessar outras publicações de Python, clique aqui!
Posts mais recentes de Python
- Curso Básico de Python: Saia do Zero em 10 Aulas GrátisAprenda com o curso básico de Python gratuito da Hashtag: 10 aulas práticas, exercícios e projetos reais para sair do zero em programação.
- Agentes RAG com Python: como criar um assistente de IAAprenda a criar Agentes RAG com Python do zero: LangChain, FAISS e OpenAI para montar um assistente de IA que responde com base nos seus documentos.
- 25 Tipos de Gráficos em Python: Guia Completo com CódigoAprenda a criar os principais tipos de gráficos em Python com Plotly: barras, pizza, mapas e mais, com código pronto para copiar e usar.
Posts mais recentes da Hashtag Treinamentos
- Planilha de Controle de Notas Fiscais no Excel [Grátis]Baixe a planilha de controle de notas fiscais no Excel grátis: calcule ISS e retenções, veja o que está em aberto e gere a cobrança de cada nota de serviço.
- Qual IA usar na empresa: ChatGPT, Claude ou Perplexity?Qual IA usar na empresa: veja as diferenças entre ChatGPT, Claude e Perplexity e quando cada um rende mais em cada área da sua equipe.
- Apostilas Gratuitas em PDF: Excel, Power BI, Python e IABaixe apostilas gratuitas em PDF de Excel, Power BI, Python, Claude e agentes de IA, com exercícios e gabarito. Escolha a sua e comece hoje.








