RAG: Conheça técnicas de Chunking com Haystack e LangChain

Conheça as práticas para deixar um pipeline RAG pronto para produção, desde a escolha do framework até estratégias avançadas de chunking e deployment

A Retrieval-Augmented Generation (RAG) representa uma arquitetura de IA revolucionária que combina recuperação clássica de informações com modelos generativos de linguagem (LLMs) em um único pipeline. Em vez de depender apenas do conhecimento estático pré-treinado em um LLM - que pode estar incompleto ou desatualizado - a RAG aumenta dinamicamente o processo de geração ao injetar informações recuperadas de fontes externas. O resultado é uma geração mais precisa e contextualmente relevante.

Embora o conceito por trás de um pipeline RAG seja relativamente simples, torná-lo pronto para produção pode ser complexo. Este guia técnico explora as melhores práticas, desde a escolha do framework até estratégias avançadas de chunking e deployment.

Principais pontos de atenção

  • Pipelines RAG aumentam as respostas dos LLMs com informações recuperadas em tempo real para respostas mais precisas

  • Haystack oferece pipelines modulares prontos para produção, enquanto LangChain se destaca em prototipagem e integrações com outras ferramentas

  • A seleção do vector database correto (FAISS, ChromaDB, Pinecone) determina escalabilidade, velocidade e recursos do sistema

  • O modelo de embedding e a estratégia de chunking afetam diretamente a qualidade da recuperação e da resposta final

  • Operacionalizar um pipeline RAG em ambientes de produção requer abordagens especializadas, avaliação, monitoramento e estratégias de deployment adequadas

Entendendo a arquitetura RAG

Um pipeline RAG geralmente possui vários componentes que interagem entre si. Os blocos de construção mais essenciais são:

  • Data Ingestion & Preprocessing: Fontes de conhecimento em vários formatos (documentos, páginas web, PDFs) são carregadas e preprocessadas

  • Chunking: Cada documento é dividido em pedaços menores semanticamente significativos

  • Embedding Generation: Cada chunk é transformado em um vetor de alta dimensionalidade usando um modelo de linguagem

  • Vector Database: Armazena todos os embeddings de chunks enquanto suporta busca por similaridade

  • Retrieval Engine: Ao receber uma consulta do usuário, busca os top-k chunks mais similares no banco de dados vetorial

  • Generation Pipeline: Um LLM recebe a consulta do usuário e os chunks de contexto recuperados para gerar uma resposta bem informada

Comparação de frameworks: Haystack vs LangChain

Para quem está construindo RAG em aplicações de produção, frameworks de alto nível são frequentemente preferidos. Haystack (da Deepset) e LangChain são as ferramentas mais populares nesta categoria.

Haystack: arquitetura centrada em pipeline

Haystack é um framework open-source focado em RAG e outros casos de uso para LLMs. Sua característica central é a arquitetura modular centrada em pipeline. Haystack adota uma abordagem baseada em grafos, onde cada componente representa um nó em um pipeline de grafo acíclico direcionado (DAG).

Vantagem principal

Descrição

Design de pipeline modular

A modularidade permite trocar componentes facilmente sem reescrever toda a aplicação

Recursos prontos para produção

Suporte integrado para avaliação, monitoramento e escalabilidade com frameworks como RAGAS e DeepEval

Documentação superior

Documentação abrangente e fácil de seguir, melhorando a velocidade de desenvolvimento

Otimizado para RAG

Suporte nativo para técnicas como HyDE e query expansion

Exemplo técnico (Haystack Pipeline)

# Instalação de pacotes necessários
#pip install haystack-ai openai python-dotenv

# Carregamento de variáveis de ambiente
import os
from dotenv import load_dotenv

load_dotenv()

# Imports do Haystack
from haystack import Document
from haystack import Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever

# Criação do DocumentStore
doc_store = InMemoryDocumentStore()

# Adição de documentos
documents = [
    Document(content="A Torre Eiffel está localizada em Paris, França."),
    Document(content="Haystack é um framework para construir aplicações NLP."),
    Document(content="LangChain é frequentemente usado para construir agentes baseados em LLM."),
    Document(content="RAG significa Retrieval-Augmented Generation.")
]
doc_store.write_documents(documents)

# Geração de embeddings
embedder = OpenAITextEmbedder(model="text-embedding-ada-002")
for doc in doc_store.filter_documents():
    embedding = embedder.run({"text": doc.content})["embedding"]
    doc.embedding = embedding
doc_store.update_documents(documents)

# Construção do pipeline
pipeline = Pipeline()
pipeline.add_component("embedder", OpenAITextEmbedder(model="text-embedding-ada-002"))
pipeline.add_component("retriever", InMemoryEmbeddingRetriever(document_store=doc_store))
pipeline.add_component("generator", OpenAIGenerator(model="gpt-3.5-turbo"))

# Conexão dos componentes
pipeline.connect("embedder.embedding", "retriever.query_embedding")
pipeline.connect("retriever.documents", "generator.documents")

# Execução com uma consulta
query = "O que é RAG em NLP?"
result = pipeline.run({"embedder": {"text": query}})

print("\nResposta:", result["generator"]["replies"][0])

LangChain: framework baseado em chains

LangChain é outro framework open-source que ganhou popularidade para prototipagem rápida de aplicações LLM. Em vez de declarar um grafo de pipeline estático, você geralmente encadeia componentes em código.

Vantagem principal

Descrição

Integrações extensivas

Compatível com vários modelos (OpenAI, Anthropic, HuggingFace) e vector databases

Framework de agentes

Permite construir agentes que podem escolher dinamicamente quais ferramentas usar

Prototipagem rápida

Abstrações de alto nível que lidam com casos de uso comuns

Comunidade e ecossistema

Grande comunidade ativa com muitos tutoriais e plugins

Exemplo técnico (LangChain RAG Chain)

# Instalação de pacotes
# pip install -qU langchain_community faiss-cpu openai python-dotenv

from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
from langchain.schema import Document
import os
from dotenv import load_dotenv

load_dotenv()

# Preparação dos documentos
raw_documents = [
    "A Torre Eiffel está localizada em Paris, França.",
    "Haystack é um framework para construir aplicações NLP.",
    "LangChain é frequentemente usado para construir agentes baseados em LLM.",
    "RAG significa Retrieval-Augmented Generation."
]

# Divisão em chunks
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=100
)
chunks = text_splitter.create_documents(raw_documents)

# Inicialização dos embeddings
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

# Criação do vector store
vectorstore = FAISS.from_documents(chunks, embedding=embeddings)

# Inicialização do pipeline RetrievalQA
qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(model_name="gpt-3.5-turbo"),
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
    chain_type="stuff",
    return_source_documents=True
)

# Execução de uma consulta
query = "O que é RAG em NLP?"
result = qa_chain(query)

print("\nResposta:\n", result["result"])

Quando escolher qual?

Recomendamos Haystack se seu objetivo é um sistema mantível, avaliável e pronto para produção. Se você está tentando prototipar algo rapidamente ou precisa de comportamentos complexos de agentes, LangChain pode ajudá-lo a chegar lá mais rápido.

Seleção e otimização de vector database

O vector database é um componente fundamental de qualquer pipeline RAG. Ele armazena os embeddings dos documentos e realiza buscas por similaridade. A escolha do vector store impactará no desempenho, mas também em recursos como filtragem, escalabilidade e facilidade de integração.

Vector DB

Pontos fortes

Trade-offs / Limitações

Casos de uso típicos

FAISS

Biblioteca C++ com bindings Python otimizada para busca de similaridade. Suporta índices avançados e aceleração GPU

Apenas em memória - requer persistência manual e sharding

Cargas de trabalho de recuperação de baixíssima latência

ChromaDB

Open-source com armazenamento persistente e APIs Pythonic. Excelente integração com LangChain

Limitado a uso local/in-process; falta clustering nativo

Prototipagem rápida e aplicações pequenas a médias

Pinecone

Serviço cloud totalmente gerenciado e serverless com auto-scaling. Conjunto rico de recursos

Maior latência devido a overhead de rede. Custos de serviço

Aplicações enterprise de grande escala com mínima carga operacional

Exemplo: desenvolvimento local com ChromaDB

Durante o desenvolvimento, você pode começar com Chroma por conveniência:

# Instalação de pacotes
#pip install langchain langchain-community chromadb pypdf tiktoken python-dotenv

import os
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader

# Configuração
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
PERSIST_DIR = "./chroma_db"
COLLECTION_NAME = "corporate_docs"
EMBEDDING_MODEL = "text-embedding-3-large"

# Processamento de documentos
documents = PyPDFLoader("relatorio_financeiro.pdf").load()

# Chunking com consciência semântica
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    separators=["\n\n", "\n", ". ", " "]
)
chunks = text_splitter.split_documents(documents)

# Inicialização de embeddings
embeddings = OpenAIEmbeddings(
    model=EMBEDDING_MODEL,
    openai_api_key=OPENAI_API_KEY
)

# Criação do vector store
vectorstore = Chroma(
    collection_name=COLLECTION_NAME,
    embedding_function=embeddings,
    persist_directory=PERSIST_DIR,
    client_settings={
        "anonymized_telemetry": False
    }
)

# Injeção de documentos
vectorstore.add_documents(
    documents=chunks,
    ids=[f"doc_{idx}" for idx in range(len(chunks))],
    metadatas=[chunk.metadata for chunk in chunks]
)

# Operação de persistência
vectorstore.persist()

# Verificação de recuperação
query = "Projeções financeiras Q3"
results = vectorstore.similarity_search(
    query=query,
    k=5,
    filter={"department": "finance"}
)

Estratégias de otimização de desempenho

Independentemente do vector DB escolhido, certas melhores práticas se aplicam:

  • Use busca aproximada para escala: A busca exata k-NN é cara e não escala bem para datasets muito grandes. Algoritmos como HNSW ou IVF podem acelerar a busca com alguma perda controlável na precisão

  • Considerações sobre dimensão e modelo: A busca vetorial pode ser mais lenta para embeddings de dimensões muito altas devido à maldição da dimensionalidade

  • Filtragem e sharding: Se seus dados estão organizados em categorias, você pode fazer shard do índice ou usar filtros, reduzindo o espaço de busca

  • Manter metadados: Metadados úteis podem ser armazenados com cada vetor no índice, permitindo filtragem e melhor prompting/debugging downstream

Modelos de embedding e estratégias para pipelines RAG

A escolha dos embeddings certos é uma decisão fundamental na arquitetura de qualquer pipeline RAG. Os embeddings influenciam tanto a qualidade da recuperação quanto a eficiência computacional.

OpenAI text-embedding-ada-002: um padrão confiável

Um dos modelos comerciais mais populares usados em produção tem sido o text-embedding-ada-002 da OpenAI:

  • Vetores de 1536 dimensões que equilibram capacidade representacional e custo computacional

  • Janela de contexto de 8191 tokens, permitindo processar passagens longas

  • Desempenho competitivo no leaderboard MTEB

  • Alto throughput com suporte a batching

Alternativas open-source e especializadas

Para muitas organizações, opções open-source ou self-hosted são preferíveis:

  • Modelos Instructor: Treinados com instruções para especializar embeddings

  • Família Sentence-BERT: Modelos leves e eficientes (all-MiniLM-L6-v2, all-mpnet-base-v2)

  • Modelos multilíngues: LaBSE, distiluse-base-multilingual-cased-v2

  • Modelos específicos de domínio: PubMedBERT para biomedicina, CodeBERT para código

Estratégias de chunking para recuperação otimizada

A escolha da estratégia de chunking apropriada é essencial para otimizar a precisão de recuperação e o desempenho geral do LLM em pipelines RAG.

Estratégia

Como funciona

Vantagens

Limitações

Chunking de tamanho fixo

Dividir texto em chunks de tamanho igual com overlap

Simples de implementar. Contagens previsíveis

Pode quebrar sentenças/conceitos no meio

Chunking semântico

Dividir texto com base em limites semânticos como tópicos ou parágrafos

Chunks semanticamente coerentes. Melhora precisão

Requer ferramentas NLP. Tamanho de chunk variável

Nível de sentença (Fine-grained)

Cada chunk é uma sentença ou pequeno grupo de sentenças

Máxima precisão de recuperação

Perda de contexto mais amplo. Tamanho do índice aumenta

Não há uma abordagem única otimizada para chunking. Sua escolha deve depender da estrutura dos seus dados, objetivos de recuperação e nível de complexidade que você pode gerenciar.

Técnicas avançadas de RAG

Além da configuração básica de "embed -> retrieve -> generate", técnicas adicionais podem ser aplicadas para otimizar um pipeline RAG:

Query Rewriting e Expansion

Query expansion aborda o problema de incompatibilidade de vocabulário query-documento criando múltiplas variações da consulta do usuário:

Workflow típico:

  1. O usuário envia uma consulta inicial

  2. Um LLM gera várias consultas alternativas (paráfrases, expansões)

  3. Cada consulta gerada é roteada para o vectorstore

  4. Os resultados são combinados para maximizar a cobertura

HyDE (Hypothetical Document Embeddings)

Em vez de embedar e buscar diretamente com a consulta do usuário, primeiro crie uma resposta/documento hipotético para a consulta usando um LLM, depois embede isso e faça a busca.

Fluxo de processo:

  1. Gerar uma resposta hipotética usando LLM

  2. Embedar a resposta hipotética

  3. Usar o embedding para busca de similaridade

  4. Recuperar documentos relevantes com base na similaridade da resposta

Avaliação e monitoramento

Métricas tradicionais de QA e busca devem se adaptar para alinhar com o contexto RAG. Nossa avaliação inclui o desempenho da etapa de recuperação e a qualidade geral das respostas.

Métricas específicas de RAG

Métricas de recuperação:

  • Context Recall: Proporção de documentos relevantes que foram recuperados

  • Context Precision: Fração de chunks recuperados que foram realmente relevantes e úteis

  • Contextual Relevancy Ranking: Garantir que os resultados mais relevantes sejam classificados mais alto

Métricas de geração:

  • Answer Relevancy: Mede se a resposta gerada é relevante para a consulta original

  • Faithfulness: Mede quão fiel a resposta gerada está alinhada com o contexto

  • Factual Correctness: Indica quão próxima a resposta está da referência

Frameworks como DeepEval e RAGAS fornecem ferramentas para computar essas métricas.

Monitoramento em produção

Além da avaliação offline, você quer monitorar o pipeline em produção:

  • Logs de recuperação: Registrar quais documentos foram recuperados para uma determinada consulta

  • Loops de feedback: Se sua aplicação suporta feedback do usuário, passe isso de volta para análise

  • Latência e throughput: Monitorar a duração de cada estágio

  • Content Drift: Se sua base de conhecimento está sujeita a mudanças, acompanhe métricas como relevância ao longo do tempo

Estratégias de deployment em produção

Deployar um pipeline RAG em produção envolve considerações de escalabilidade, segurança e confiabilidade operacional:

Área

Estratégia/Técnica

Descrição e exemplos

Considerações principais

Escalabilidade e desempenho

Horizontal Scaling

Executar múltiplas réplicas do serviço RAG atrás de um load balancer

Garantir consistência do índice

Caching

Cache de embeddings de consultas, documentos recuperados e respostas LLM

Invalidação de cache e privacidade

Processamento assíncrono

Usar filas de mensagens e pools de workers

Design para processamento at-least-once

Orquestração Kubernetes

Deploy RAG como conjunto de pods com limites de recursos

Monitorar saúde dos pods

Otimização de latência

Colocar serviços

Hospedar vector DB e servidores de aplicação na mesma região

Evitar hops cross-region

LLM Warmup & Streaming

Fazer warmup de modelos LLM na inicialização

Mitiga penalidades de cold start

Falha e recuperação

Retries & Fallbacks

Implementar lógica de retry com exponential backoff

Garantir confiabilidade

Segurança e privacidade

Criptografia de dados

Criptografar todos os dados em repouso e em trânsito

Compliance com regulamentações

Controle de acesso

Marcar documentos/vetores com roles de usuário

Prevenir vazamento de dados

Isolamento e multi-tenancy

Usar namespaces/collections por cliente

Simplifica compliance

Filtragem de conteúdo

Aplicar filtragem de saída ou moderação

Reduz risco de vazamentos

Perguntas frequentes

O que é Retrieval-Augmented Generation (RAG) e por que devo me importar?

RAG é uma arquitetura de IA poderosa que combina recuperação clássica de informações com large language models para gerar respostas aumentadas com conhecimento externo atualizado. São mais factualmente precisas e contextualmente relevantes do que LLMs isolados.

Como decido entre Haystack e LangChain para construir um pipeline RAG?

Escolha Haystack se você precisa de um pipeline pronto para produção, modular e avaliável com documentação abrangente. Escolha LangChain para prototipagem rápida de novos modelos, construção de workflows baseados em agentes ou integrações mais flexíveis.

Qual é o papel do vector database em um pipeline RAG?

O vector database armazena os embeddings de alta dimensionalidade dos seus documentos e habilita busca eficiente por similaridade para recuperar o contexto mais relevante para informar a resposta do LLM.

Quais são os melhores vector databases para pipelines RAG?

  • FAISS: Open-source, extremamente rápido para recuperação em memória. Ideal para setups locais menores

  • ChromaDB: Open-source, fácil de usar, suporta persistência e metadata. Bom para workloads locais ou pequenas/médias de produção

  • Pinecone/Weaviate/Azure Cognitive Search: Serviços cloud gerenciados com recursos ricos. Adequados para workloads enterprise grandes e distribuídas

Conclusão

Engenheirar um pipeline RAG pronto para produção requer consideração cuidadosa de múltiplas camadas. O sucesso depende de fazer as escolhas certas em cada etapa, desde selecionar o framework apropriado, modelos de embedding, vector databases, estratégias de chunking, práticas de avaliação, deployment e medidas de segurança.

Ao engenheirar meticulosamente cada camada do pipeline e seguir as melhores práticas em escalabilidade, monitoramento e segurança, você pode entregar soluções RAG precisas, confiáveis e seguras. Como o cenário das tecnologias RAG está evoluindo rapidamente, manter flexibilidade e avaliar continuamente os componentes do seu pipeline é essencial para manter uma solução eficaz e preparada para o futuro.