1
resposta

[Projeto] 06 Faça como eu fiz: integração RAG

IMPLEMENTAÇÃO
1️ Instalações Necessárias
pip install langchain
pip install langchain-community
pip install langchain-openai
pip install langchain-huggingface
pip install faiss-cpu
pip install pypdf
pip install tiktoken
pip install python-dotenv

Ollama:

https://ollama.com

Baixar modelos:

ollama pull bge-m3
ollama pull gemma:4b

2️ Criar Caderno do Zero

Abra Jupyter:

jupyter notebook

Chorar:RAG_Local_Integrado.ipynb

3️ Carregar PDFs do Diretório
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader

loader = DirectoryLoader(
"./pdfs",
glob="**/*.pdf",
loader_cls=PyPDFLoader
)

documents = loader.load()

print(len(documents))

Agora você tem apenas PDFs.

4️ Chunking com Token Splitter (Hugging Face)
from langchain_text_splitters import TokenTextSplitter

splitter = TokenTextSplitter(
chunk_size=512,
chunk_overlap=100
)

chunks = splitter.split_documents(documents)

print(len(chunks))

chunk_size 512 → equilíbrio
overlap 100 → mantém contexto

5️ Incorporações locais (BGE-M3 via Ollama)
from langchain_community.embeddings import OllamaEmbeddings

embeddings = OllamaEmbeddings(
model="bge-m3"
)

Sem API externa. 100% local.

6️ Vector Store Local (FAISS)
from langchain.vectorstores import FAISS

vectorstore = FAISS.from_documents(
chunks,
embeddings
)

vectorstore.save_local("faiss_index")

Agora persistido em arquivo.

7️ Criar Retriever
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

8️ Testar LLM Local (Gemma)
from langchain_community.chat_models import ChatOllama

llm = ChatOllama(
model="gemma:4b",
temperature=0
)

response = llm.invoke("Explique o princípio da legalidade.")
print(response.content)

9️ Criar Corrente RAG Básica
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template("""
Responda com base apenas no contexto:

{context}

Pergunta:
{question}
""")

rag_chain = (
{
"context": retriever,
"question": RunnablePassthrough()
}
| prompt
| llm
| StrOutputParser()
)

Teste:

rag_chain.invoke("Qual o prazo de vigência do contrato?")

10 Reescrita de consulta (Modelo Menor)

Objetivo: melhorar consultas mal formuladas.

rewrite_prompt = ChatPromptTemplate.from_template("""
Reescreva a pergunta de forma mais clara e específica:

Pergunta: {question}
""")

rewriter_chain = rewrite_prompt | llm | StrOutputParser()

query = "prazo contrato?"

new_query = rewriter_chain.invoke({"question": query})
print(new_query)

Agora usamos uma consulta refinada no retriever.

Recuperador de consultas múltiplas
from langchain.retrievers.multi_query import MultiQueryRetriever

multi_retriever = MultiQueryRetriever.from_llm(
retriever=retriever,
llm=llm
)

docs = multi_retriever.get_relevant_documents(
"Qual a responsabilidade da contratada?"
)

print(len(docs))

Ele gera diversas variações automaticamente.

Técnica HyDE (Ocultar)

HyDE cria um documento hipotético antes de pesquisar.

hyde_prompt = ChatPromptTemplate.from_template("""
Escreva um parágrafo hipotético que responderia:

{question}
""")

hyde_chain = hyde_prompt | llm | StrOutputParser()

hypothetical_doc = hyde_chain.invoke(
{"question": "Qual a penalidade por inadimplemento?"}
)

docs = vectorstore.similarity_search(hypothetical_doc, k=4)

1 resposta

Ei! Tudo bem, Moacir?

Sensacional o seu projeto! Você não apenas seguiu o roteiro, mas construiu um guia completo de RAG Local extremamente bem estruturado. Utilizar o Ollama com o modelo bge-m3 para embeddings e o gemma:4b para inferência é uma escolha muito inteligente para quem busca privacidade e baixo custo sem depender de APIs externas.

Parabéns pela dedicação e por compartilhar o passo a passo com a comunidade! Isso ajuda muito outros colegas que estão tentando configurar o ambiente local.

Qualquer dúvida, compartilhe no fórum pois estaremos por aqui.

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!