Blog • Artigo
    Fine-TuningRAGArquitetura

    A Evolução das Arquiteturas RAG: do Naive ao Agentic

    Quando comecei a trabalhar com LLMs em produção, a primeira frustração foi sempre a mesma: o modelo sabe muito sobre o mundo, mas nada sobre a empresa do cliente. Ele alucina contratos que não existem, inventa políticas internas e desconhece completamente o contexto do negócio.

    Alexsander
    AlexsanderEngenheiro de Software
    Mar 16, 2026
    15 min de leitura
    A Evolução das Arquiteturas RAG: do Naive ao Agentic

    RAG nasceu para resolver exatamente isso.

    Retrieval-Augmented Generation é o padrão arquitetural que conecta o poder generativo dos LLMs ao conhecimento específico de uma organização. A ideia central é simples: antes de gerar uma resposta, busque informação relevante externamente e injete no contexto do modelo. O que mudou profundamente nos últimos dois anos foi a sofisticação dessa busca.

    Neste artigo, percorro as seis arquiteturas RAG mais relevantes da atualidade, explicando a lógica por trás de cada evolução, os casos de uso onde cada uma brilha e as decisões de engenharia que você precisa tomar ao escolher entre elas.


    O problema que RAG resolve

    LLMs são treinados com um snapshot do mundo até uma data de corte. Eles não sabem o que aconteceu ontem, não conhecem os documentos internos da sua empresa e não têm acesso em tempo real a sistemas transacionais.

    Existem três abordagens para lidar com isso:

    • Fine-tuning: treinar o modelo com seus dados. Caro, lento e difícil de atualizar.
    • Context stuffing: jogar tudo no prompt. Inviável para bases grandes; desperdiça tokens.
    • RAG: recuperar apenas o que é relevante para aquela consulta específica e injetar no prompt.

    RAG venceu na prática porque equilibra custo, velocidade de atualização e qualidade de resposta de forma que as outras abordagens não conseguem.

    A estrutura básica tem três etapas:

    Código
    Query → Recuperação → Geração aumentada
    

    O que diferencia as arquiteturas é exatamente como essa recuperação acontece.


    1.Naive RAG — a fundação

    Como funciona

    A arquitetura mais simples e ponto de partida para qualquer implementação:

    1. Os documentos são divididos em chunks e convertidos em vetores de embedding
    2. Esses vetores são armazenados em um banco vetorial (Qdrant, Pinecone, FAISS)
    3. A query do usuário é convertida em vetor
    4. O sistema busca os chunks com maior similaridade cosseno
    5. Os chunks recuperados são injetados no prompt junto com a query
    Código
    from langchain.vectorstores import Qdrant
    from langchain.embeddings import OpenAIEmbeddings
    from langchain.chains import RetrievalQA
    from langchain.llms import ChatOpenAI
    
    embeddings = OpenAIEmbeddings()
    vectorstore = Qdrant.from_documents(docs, embeddings)
    
    qa_chain = RetrievalQA.from_chain_type(
        llm=ChatOpenAI(model="gpt-4o"),
        retriever=vectorstore.as_retriever(search_kwargs={"k": 5})
    )
    
    response = qa_chain.invoke({"query": "Qual é a política de reembolso?"})
    

    Quando usar

    • Base de conhecimento estável e bem estruturada
    • Perguntas objetivas com vocabulário próximo ao dos documentos
    • MVPs, provas de conceito e validação de produto
    • Equipes com menor maturidade em IA

    Limitações críticas

    O Naive RAG falha em três cenários comuns:

    Vocabulary mismatch: o usuário usa "devolução" mas o documento diz "reembolso". A similaridade semântica ajuda, mas não resolve tudo.

    Chunking sem contexto: um chunk isolado perde a informação de qual documento pertence, qual seção, qual contexto anterior. Um parágrafo retirado do meio de um contrato pode gerar uma resposta completamente errada.

    Queries vagas: "me fala sobre aquele processo de aprovação" não gera um vetor informativo o suficiente para encontrar os documentos certos.


    2.HyDE — Hypothetical Document Embeddings

    A virada conceitual

    HyDE parte de uma observação simples: a distância no espaço vetorial entre uma pergunta e sua resposta é maior do que a distância entre duas respostas similares.

    Em vez de buscar pelo vetor da pergunta, o HyDE instrui o LLM a imaginar como seria um documento que responderia perfeitamente à query. Esse documento hipotético é então usado como vetor de busca.

    Código
    Query → LLM gera documento hipotético → Embedding do documento → Busca vetorial → Resposta real
    

    Implementação

    Código
    from langchain.chains import HypotheticalDocumentEmbedder
    from langchain.prompts import PromptTemplate
    
    hyde_prompt = PromptTemplate(
        input_variables=["question"],
        template="""Escreva um trecho de documentação técnica que responda a seguinte pergunta.
        O trecho deve ter entre 100 e 150 palavras, no estilo de um manual corporativo.
        
        Pergunta: {question}
        
        Trecho:"""
    )
    
    hyde_embedder = HypotheticalDocumentEmbedder.from_llm(
        llm=ChatOpenAI(model="gpt-4o"),
        base_embeddings=OpenAIEmbeddings(),
        custom_prompt=hyde_prompt
    )
    
    vectorstore = Qdrant.from_documents(docs, hyde_embedder)
    

    Quando usar

    • Usuários não-técnicos que formulam queries vagas ou em linguagem cotidiana
    • Domínios onde o jargão técnico dos documentos é muito diferente da linguagem natural dos usuários
    • Sistemas de atendimento ao cliente e help desks corporativos
    • Quando a qualidade da recuperação é mais importante que a latência

    Trade-offs

    O custo é uma chamada extra ao LLM antes de cada busca. Em sistemas de alto volume, isso pode representar 30-50% de aumento no custo por query. A recomendação é combinar HyDE com cache de embeddings para queries frequentes.


    3.Graph RAG — quando relacionamentos importam

    O problema que os grafos resolvem

    Busca por similaridade semântica responde bem à pergunta "quais chunks são parecidos com esta query?". Mas ela falha na pergunta "quais são todas as empresas que têm relação com o Contrato 2024-087, e quais cláusulas se aplicam a cada uma?".

    Esse é um problema de grafo, não de similaridade.

    Graph RAG extrai entidades e relacionamentos dos documentos e os representa como um grafo de conhecimento. A recuperação deixa de ser vetorial e passa a ser uma travessia do grafo.

    Arquitetura

    Código
    Documentos → Extração de entidades (NER) → Construção do grafo → Schema
                                                                            ↓
    Query → Query Generator → Consulta ao grafo → Contexto estruturado → LLM → Resposta
    
    Código
    from langchain_community.graphs import Neo4jGraph
    from langchain_experimental.graph_transformers import LLMGraphTransformer
    
    graph = Neo4jGraph(url="bolt://localhost:7687", username="neo4j", password="senha")
    
    llm_transformer = LLMGraphTransformer(llm=ChatOpenAI(model="gpt-4o"))
    
    # Extrai entidades e relações automaticamente
    graph_documents = llm_transformer.convert_to_graph_documents(documents)
    graph.add_graph_documents(graph_documents)
    
    # Busca por grafo
    query = """
    MATCH (c:Contrato)-[:ENVOLVE]->(e:Empresa)
    WHERE c.numero = '2024-087'
    RETURN e.nome, e.cnpj, c.clausulas
    """
    resultado = graph.query(query)
    

    Quando usar

    • Bases jurídicas e compliance com múltiplas entidades relacionadas
    • Knowledge graphs corporativos (estrutura organizacional, processos, responsabilidades)
    • Análise de risco com cadeias de relacionamento
    • Sistemas financeiros com grafos de transações e contrapartes
    • Qualquer domínio onde "quem se relaciona com quem" é tão importante quanto o conteúdo

    Combinando com RAG tradicional

    Na prática, Graph RAG raramente é usado sozinho. A arquitetura mais robusta combina grafo para navegação estrutural e vetor para conteúdo semântico — o que nos leva à próxima arquitetura.


    4.Hybrid RAG — lexical + semântico

    Por que embeddings sozinhos não bastam

    Busca vetorial é ótima para similaridade semântica, mas tem um ponto cego: ela não é boa com termos exatos, siglas, nomes próprios e jargão técnico muito específico.

    Um modelo de embedding pode entender que "autarquia federal" e "órgão público" são semanticamente próximos. Mas se você buscar por "BACEN" e o documento diz exatamente "BACEN", a busca léxica BM25 vai encontrar isso com precisão cirúrgica enquanto a busca vetorial pode vacilar.

    Hybrid RAG combina as duas abordagens e usa um reranker para unir os resultados.

    Arquitetura

    Código
    Query
      ├── Busca Lexical (BM25/TF-IDF) → Top-K resultados léxicos
      └── Busca Semântica (Embedding)  → Top-K resultados vetoriais
                                             ↓
                                  Reranker (Cross-Encoder)
                                             ↓
                                  Top-N resultados unificados → LLM
    

    Implementação com Qdrant

    Código
    from qdrant_client import QdrantClient
    from qdrant_client.models import SparseVector, NamedSparseVector, NamedVector
    
    client = QdrantClient(url="http://localhost:6333")
    
    # Busca híbrida: vetorial densa + esparsa (BM25)
    results = client.query_points(
        collection_name="documentos",
        prefetch=[
            # Busca densa (semântica)
            models.Prefetch(
                query=dense_embedding,
                using="dense",
                limit=20
            ),
            # Busca esparsa (léxica)
            models.Prefetch(
                query=models.SparseVector(indices=sparse_indices, values=sparse_values),
                using="sparse",
                limit=20
            ),
        ],
        # Reranking com RRF (Reciprocal Rank Fusion)
        query=models.FusionQuery(fusion=models.Fusion.RRF),
        limit=5
    )
    

    Quando usar

    • Bases com muito jargão técnico, siglas e nomes próprios
    • Sistemas regulatórios onde termos exatos têm peso legal
    • Documentação de APIs, contratos e especificações técnicas
    • Qualquer contexto onde falsos negativos (não encontrar o documento certo) têm alto custo

    O papel do reranker

    O reranker é um Cross-Encoder que avalia a relevância de cada resultado em relação à query de forma mais precisa do que os bi-encoders usados para gerar embeddings. Modelos como cross-encoder/ms-marco-MiniLM-L-6-v2 ou o Cohere Rerank são escolhas comuns.

    O trade-off é latência: o reranker adiciona 50-200ms dependendo do número de candidatos e do hardware.


    5.Contextual RAG — chunks com memória

    O problema do chunking cego

    Imagine um contrato de 50 páginas dividido em chunks de 512 tokens. O chunk que contém a cláusula de rescisão provavelmente não menciona as partes contratantes, o objeto do contrato ou a data de assinatura — porque essa informação está em chunks anteriores.

    Quando esse chunk é recuperado isoladamente, o LLM não tem contexto para interpretar corretamente a cláusula. Ele não sabe a quem aquela rescisão se aplica.

    Contextual RAG resolve isso fazendo o LLM enriquecer cada chunk com seu contexto antes da indexação.

    Como funciona

    Durante o pipeline de ingestão (não em tempo de query), o LLM processa cada chunk junto com o documento completo (ou uma janela de contexto) e gera uma descrição contextual que é concatenada ao chunk antes de ser indexada.

    Código
    from anthropic import Anthropic
    
    client = Anthropic()
    
    def gerar_contexto_chunk(documento_completo: str, chunk: str) -> str:
        prompt = f"""<documento>
    {documento_completo}
    </documento>
    
    Aqui está o trecho específico que precisa ser contextualizado:
    <trecho>
    {chunk}
    </trecho>
    
    Forneça um contexto conciso (2-3 frases) que situe este trecho dentro do documento completo.
    Inclua: qual documento é, qual seção pertence, quais entidades estão envolvidas.
    Responda apenas com o contexto, sem prefácio."""
    
        response = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=200,
            messages=[{"role": "user", "content": prompt}]
        )
        return response.content[0].text
    
    # Pipeline de ingestão
    for chunk in chunks:
        contexto = gerar_contexto_chunk(documento_completo, chunk.text)
        chunk_contextualizado = f"{contexto}\n\n{chunk.text}"
        # indexar chunk_contextualizado no vector store
    

    Quando usar

    • Documentos longos e densos (contratos, relatórios, manuais técnicos)
    • Bases onde a relação entre partes do documento é crucial para a resposta
    • Sistemas jurídicos, de compliance e auditoria
    • Qualquer contexto onde "quem, quando, sobre o quê" precisa estar presente em todo chunk

    Custo de ingestão vs qualidade

    O trade-off aqui é no pipeline de ingestão: você paga uma chamada ao LLM por chunk durante o processamento dos documentos. Para uma base com 10.000 chunks, isso representa 10.000 chamadas extras. O custo unitário é baixo (chunks são pequenos), mas precisa estar no planejamento.

    A Anthropic reportou melhorias de 49% no precision@20 e redução de 67% em falhas ao combinar Contextual RAG com BM25.


    6.Adaptive RAG — roteamento inteligente

    O problema do one-size-fits-all

    As arquiteturas anteriores tratam todas as queries da mesma forma. Mas perguntas têm complexidades muito diferentes:

    • "Qual o CEP da filial de São Paulo?" — resposta direta, não precisa de RAG
    • "Quais são os riscos do projeto X?" — busca simples, resposta objetiva
    • "Compare a performance dos produtos A, B e C nos últimos 3 trimestres e identifique os fatores que explicam as diferenças" — análise multi-step com múltiplas fontes

    Jogar a terceira query num Naive RAG vai produzir uma resposta superficial. Jogar a primeira num sistema de raciocínio multi-step vai desperdiçar tokens e latência.

    Adaptive RAG resolve isso com um Query Analyzer que classifica a complexidade da pergunta e roteia para o pipeline adequado.

    Arquitetura de roteamento

    Código
    Query
      ↓
    Query Analyzer (classificador)
      ├── Simples (factual, direto) → Resposta direta sem RAG
      ├── Médio (busca + síntese)  → RAG padrão + chain of thought
      └── Complexo (multi-step)   → Reasoning chain + múltiplas buscas iterativas
    

    Implementação com LangGraph

    Código
    from langgraph.graph import StateGraph, END
    from typing import TypedDict, Literal
    
    class State(TypedDict):
        query: str
        complexity: Literal["direct", "single_step", "multi_step"]
        context: list[str]
        response: str
    
    def classify_query(state: State) -> State:
        prompt = f"""Classifique a complexidade desta query:
        
    Query: {state['query']}
    
    Responda com exatamente uma das opções:
    - "direct": pergunta factual simples, sem necessidade de busca
    - "single_step": requer busca em documentos, resposta única
    - "multi_step": requer múltiplas buscas, análise comparativa ou raciocínio encadeado
    
    Resposta:"""
        
        classification = llm.invoke(prompt).content.strip()
        return {**state, "complexity": classification}
    
    def route(state: State) -> str:
        return state["complexity"]
    
    workflow = StateGraph(State)
    workflow.add_node("classify", classify_query)
    workflow.add_node("direct_answer", direct_answer_node)
    workflow.add_node("single_step_rag", single_step_rag_node)
    workflow.add_node("multi_step_rag", multi_step_rag_node)
    
    workflow.set_entry_point("classify")
    workflow.add_conditional_edges("classify", route, {
        "direct": "direct_answer",
        "single_step": "single_step_rag",
        "multi_step": "multi_step_rag"
    })
    
    app = workflow.compile()
    

    Quando usar

    • Sistemas com alta variabilidade nas queries dos usuários
    • Ambientes onde custo por query precisa ser otimizado
    • Assistentes corporativos que atendem desde perguntas simples a análises complexas
    • Qualquer sistema onde latência e custo são KPIs explícitos

    7.Agentic RAG — o estado da arte

    A mudança de paradigma

    Nas arquiteturas anteriores, o LLM é passivo: recebe contexto, gera resposta. No Agentic RAG, o LLM é um ator autônomo que decide como resolver o problema.

    A diferença é fundamental:

    RAG tradicionalAgentic RAG
    Pipeline fixoFluxo dinâmico decidido pelo agente
    Uma busca por queryMúltiplas buscas iterativas
    Sem memória entre interaçõesMemória de curto e longo prazo
    Ferramentas predefinidasSeleção dinâmica de ferramentas
    Resposta únicaPlanejamento + execução + validação

    Componentes da arquitetura

    Memória

    • Curto prazo: contexto da conversa atual (janela de contexto)
    • Longo prazo: memória persistente em banco de dados (Redis, PostgreSQL)

    Planejamento

    • ReAct (Reasoning + Acting): raciocina sobre o problema antes de agir
    • Chain of Thought: encadeia passos de raciocínio explicitamente

    Agentes especializados

    • Agent 1: dados locais (vector store, SQL, APIs internas)
    • Agent 2: busca web (Kagi, Bing, Google)
    • Agent 3: cloud engines (AWS, Azure, GCP)

    MCP Servers O Model Context Protocol padroniza a interface entre agentes e ferramentas externas, permitindo que qualquer agente acesse qualquer ferramenta de forma intercambiável.

    Implementação com LangGraph

    Código
    from langgraph.graph import StateGraph, END
    from langgraph.prebuilt import ToolNode
    from langchain_core.tools import tool
    
    @tool
    def buscar_documentos_internos(query: str) -> str:
        """Busca em documentos internos da empresa."""
        return vectorstore.similarity_search(query, k=5)
    
    @tool
    def buscar_web(query: str) -> str:
        """Busca informações atualizadas na web."""
        return web_search_tool.run(query)
    
    @tool
    def consultar_banco_dados(sql: str) -> str:
        """Executa consulta SQL no banco de dados transacional."""
        return db.run(sql)
    
    tools = [buscar_documentos_internos, buscar_web, consultar_banco_dados]
    tool_node = ToolNode(tools)
    
    # Agente com ReAct
    agent = create_react_agent(
        model=ChatOpenAI(model="gpt-4o"),
        tools=tools,
        system_prompt="""Você é um assistente especializado em análise financeira.
        
        Para cada query:
        1. Avalie quais ferramentas são necessárias
        2. Execute as buscas em ordem de relevância
        3. Sintetize as informações obtidas
        4. Valide a resposta antes de retornar
        
        Seja preciso, cite as fontes e indique quando a informação é incerta."""
    )
    
    # Grafo com memória persistente
    from langgraph.checkpoint.redis import RedisSaver
    
    checkpointer = RedisSaver.from_conn_string("redis://localhost:6379")
    
    workflow = StateGraph(MessagesState)
    workflow.add_node("agent", agent)
    workflow.add_node("tools", tool_node)
    workflow.set_entry_point("agent")
    workflow.add_conditional_edges("agent", should_continue)
    workflow.add_edge("tools", "agent")
    
    app = workflow.compile(checkpointer=checkpointer)
    
    # Execução com sessão persistente
    config = {"configurable": {"thread_id": "usuario-123-sessao-456"}}
    response = app.invoke({"messages": [HumanMessage(content=query)]}, config=config)
    

    Quando usar

    • Assistentes que precisam resolver problemas complexos de forma autônoma
    • Sistemas que integram múltiplas fontes de dados heterogêneas
    • Workflows de análise que requerem raciocínio multi-step
    • Automação de processos que envolvem decisões intermediárias

    Desafios de produção

    Agentic RAG traz complexidade operacional significativa:

    Observabilidade: é essencial rastrear cada passo do agente — qual ferramenta foi chamada, com quais parâmetros, qual foi o resultado. LangSmith é a solução mais madura para isso.

    Controle de custos: loops de agente sem limite podem gerar centenas de chamadas ao LLM. Implemente max_iterations e alertas de custo.

    Timeouts: agentes complexos podem demorar 30-60 segundos. Defina SLAs claros e implemente respostas parciais quando necessário.

    Guardrails: em ambientes regulados (financeiro, saúde, jurídico), é indispensável validar o que o agente faz antes de executar ações irreversíveis.


    Comparativo arquitetural

    ArquiteturaComplexidadeCusto relativoLatênciaMelhor caso de uso
    Naive RAGBaixa$< 500msMVP, bases simples
    HyDEBaixa$$1-2sQueries vagas, usuários leigos
    Graph RAGAlta$$$1-3sDados relacionais, ontologias
    Hybrid RAGMédia$$500ms-1.5sJargão técnico, termos exatos
    Contextual RAGMédia$$ (ingestão)< 500msDocumentos longos e densos
    Adaptive RAGAlta$-$$$variávelAlto volume, queries diversas
    Agentic RAGMuito alta$$$$5-60sProblemas complexos, multi-fonte

    Como escolher a arquitetura certa

    A escolha da arquitetura RAG não é sobre usar a mais sofisticada — é sobre usar a mais adequada para o contexto. Algumas perguntas que uso no processo de decisão:

    Qual é a natureza das queries? Se são sempre simples e factuais → Naive ou Hybrid. Se variam muito → Adaptive. Se requerem raciocínio → Agentic.

    Qual é a estrutura dos documentos? Textos longos com contexto entre seções → Contextual. Dados com entidades relacionadas → Graph. Bases com jargão técnico → Hybrid.

    Quais são os SLAs de latência? Abaixo de 1 segundo → Naive, Hybrid ou Contextual. Até 3 segundos → a maioria. Sem restrição → Agentic.

    Qual é o ambiente regulatório? Em financial services e saúde, priorize rastreabilidade, explainability e guardrails sobre sofisticação arquitetural.

    Qual é a maturidade da equipe? Uma equipe que ainda está aprendendo RAG vai entregar mais valor com um Hybrid RAG bem implementado do que com um Agentic RAG mal implementado.


    Conclusão

    A progressão do Naive ao Agentic RAG conta uma história sobre como a indústria aprendeu que recuperação de informação é um problema multidimensional. Não existe uma solução universal.

    O Naive RAG continua sendo a escolha certa para dezenas de casos de uso. O Agentic RAG é transformador para os problemas certos, mas traz consigo uma carga operacional que não pode ser ignorada.

    A minha recomendação prática: comece simples, meça, e evolua a arquitetura conforme os dados indicarem onde estão os gargalos. Um Hybrid RAG com bom reranker resolve 80% dos problemas que as equipes tentam resolver com Agentic RAG. Guarde a complexidade para quando ela for realmente necessária.

    E quando for necessária — o Agentic RAG com LangGraph, MCP e observabilidade via LangSmith é uma das combinações mais poderosas que já trabalhei.


    Referências e leitura complementar


    Alexsander Valente é Engenheiro de Dados e IA Architect na Threeger 360, com mais de 10 anos de experiência em instituições financeiras. Publica conteúdo técnico sobre IA Generativa, RAG e arquiteturas de dados no LinkedIn e no curso IA Generativa na Prática.

    Este conteúdo foi útil?
    Compartilhar artigo

    Quer aplicar isso no seu contexto?

    Vamos conversar sobre seus desafios e encontrar o melhor caminho para sua operação.

    Agendar conversa