Construindo um Agente RAG Local com Python, Ollama (Llama 3) e CPU
Introdução
Nos dias de hoje, a segurança da informação é uma das maiores preocupações nas empresas, especialmente ao lidar com inteligência artificial generativa. Enviar dados corporativos confidenciais (como relatórios de auditoria, políticas de conformidade ISO ou balanços financeiros) para APIs proprietárias externas pode violar políticas rígidas de governança de dados.
A solução? RAG (Retrieval-Augmented Generation) 100% Local.
Neste artigo, vamos construir passo a passo um agente de RAG local que roda inteiramente em sua máquina (mesmo utilizando apenas CPU) usando Python, Ollama (com o modelo Llama 3) e LangChain/ChromaDB.
O que é RAG (Retrieval-Augmented Generation)?
RAG é uma arquitetura que estende as capacidades de um Grande Modelo de Linguagem (LLM) sem a necessidade de re-treiná-lo (fine-tuning). Ela funciona em três etapas principais:
1. Recuperação (Retrieval): O sistema busca documentos relevantes a partir de uma base de conhecimento local baseada na pergunta do usuário. 2. Aumentação (Augmentation): A pergunta do usuário e os fragmentos de documentos encontrados são combinados em um "prompt rico". 3. Geração (Generation): O LLM lê o contexto provido e gera uma resposta precisa, baseada unicamente no conteúdo dos documentos fornecidos.
Requisitos e Setup do Ambiente
1. Instalar o Ollama
Acesse ollama.com e instale o software no seu sistema (Linux, macOS ou Windows). Após a instalação, abra o terminal e faça o download do modelo Llama 3.1 (ou Llama 3 de 8B):ollama pull llama3
ollama pull nomic-embed-text
O nomic-embed-text é um modelo de embeddings leve de alta performance para converter textos em vetores matemáticos.
2. Dependências do Python
Crie um ambiente virtual e instale as dependências:python -m venv venv
source venv/bin/activate
pip install langchain langchain-community chromadb sentence-transformers langchain-text-splitters
O Código do Agente RAG Local
Abaixo está o script completo que lê documentos locais (como PDFs ou arquivos de texto), cria o banco vetorial local (ChromaDB) e executa a inferência local usando o Ollama.
import os
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
1. Carregar o documento de conhecimento local
Suponha que temos um arquivo 'manual_sgi.txt' com as normas da empresa
with open("manual_sgi.txt", "w", encoding="utf-8") as f:
f.write("""
MANUAL DO SISTEMA DE GESTÃO INTEGRADO (SGI) - ALEX FERRAZ TECNOLOGIA
Seção 4.2 - Política de Segurança de Redes corporativas:
Todos os servidores na AWS devem usar autenticação via chave SSH pública/privada (RSA 4096).
É proibido o acesso root direto via SSH. Apenas o usuário 'deploy' tem acesso ao ambiente de produção.
As senhas de banco de dados devem ser rotacionadas a cada 30 dias usando o AWS Secrets Manager.
""")
loader = TextLoader("manual_sgi.txt", encoding="utf-8")
documents = loader.load()
2. Particionar o texto em blocos menores (Chunking)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=50)
texts = text_splitter.split_documents(documents)
3. Gerar Embeddings e criar o Banco de Vetores (Chroma DB)
O Chroma persistirá os dados na pasta ./chroma_db de forma local e segura
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vector_store = Chroma.from_documents(
documents=texts,
embedding=embeddings,
persist_directory="./chroma_db"
)
4. Criar o Prompt Customizado para Garantir Limitação de Escopo
template = """Use as seguintes partes do contexto fornecido para responder à pergunta no final.
Se você não souber a resposta, diga apenas que não sabe, não tente inventar uma resposta.
Mantenha a resposta curta, direta e estritamente baseada no contexto.
Contexto:
{context}
Pergunta: {question}
Resposta útil em português:"""
custom_prompt = PromptTemplate(
template=template,
input_variables=["context", "question"]
)
5. Configurar o Modelo Llama3 no Ollama e a Chain de Perguntas & Respostas
llm = Ollama(model="llama3", temperature=0.1)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vector_store.as_retriever(search_kwargs={"k": 2}),
chain_type_kwargs={"prompt": custom_prompt}
)
6. Executar a Pergunta
pergunta = "Qual usuário tem acesso ao ambiente de produção e qual a política de chaves SSH?"
resposta = qa_chain.run(pergunta)
print("--- PERGUNTA ---")
print(pergunta)
print("\n--- RESPOSTA DO AGENTE ---")
print(resposta)
Análise de Desempenho em CPU
Embeddings: O modelo nomic-embed-text gera embeddings de forma quase instantânea na CPU, pois possui poucos parâmetros.
Busca Semântica: O ChromaDB é extremamente leve e recupera os trechos em milissegundos.
* Geração (Llama 3 8B): Em uma CPU moderna (ex: AMD Ryzen 7 ou Intel Core i7), a geração demora cerca de 10 a 20 segundos por resposta. Usando quantização de 4 bits (padrão do Ollama), a memória RAM consumida fica em torno de 4.8 GB.
Conclusão e Governança
Esta arquitetura demonstra que é viável criar assistentes de IA corporativos robustos sem depender da internet ou expor segredos industriais. Para sistemas que necessitam de conformidade com ISO 27001 (Segurança da Informação), o RAG local elimina o risco de vazamento de dados de forma definitiva.
Gostou do tutorial? Se você está planejando implementar IA Generativa local na sua infraestrutura, compartilhe suas dúvidas no meu LinkedIn!