Pular para o conteúdo principal
A geração aumentada por recuperação, ou RAG, é um dos padrões mais úteis para construir aplicações de IA que precisam responder a partir dos seus próprios documentos. Em vez de pedir a um modelo para confiar apenas na memória, você recupera material-fonte relevante primeiro, envia esse contexto ao modelo e pede para ele responder com citações. Neste tutorial, construiremos um bot RAG privado usando Python, Venice para embeddings e chat completions, Qdrant para busca vetorial e FastEmbed para re-ranking local. Ao final, você terá as peças principais para um assistente local de documentos que pode ingerir seus arquivos, recuperar chunks relevantes, re-rankeá-los e responder com citações. O bot RAG em ação Antes de continuarmos: se você quiser executar o código deste artigo, precisará de uma chave de API Venice. Exporte-a como variável de ambiente:
Interessado na implementação completa do código? Confira o repositório no GitHub.

Como funciona um bot RAG moderno

Um bom pipeline RAG é mais do que “colocar documentos em uma base de dados vetorial”. O fluxo básico é assim: A etapa de re-ranking é o upgrade que torna isso muito mais útil que uma demo RAG básica. A busca vetorial é rápida e boa em encontrar chunks semanticamente similares, mas ainda pode retornar passagens adjacentes ao tópico em vez de diretamente úteis. Um cross-encoder lê a pergunta e cada chunk candidato juntos, e depois pontua o quão bem aquele chunk de fato responde à pergunta.

Instalando as dependências

Usaremos o SDK Python da OpenAI porque a Venice expõe uma API compatível com OpenAI. Também usaremos o cliente Python do Qdrant com suporte a FastEmbed:
Se preferir manter as dependências em um arquivo, crie requirements.txt com os mesmos pacotes:

Escolhendo os modelos

Crie um arquivo chamado rag_bot.py e comece adicionando os imports, estruturas de dados, URL da API e nomes dos modelos:
O nome do modelo de embedding é intencionalmente compatível com OpenAI. A Venice mapeia nomes de modelos de embedding compatíveis para modelos de embedding hospedados na Venice, então o código existente do SDK da OpenAI geralmente pode ser migrado mudando o base_url e a chave de API. Você pode listar os modelos Venice disponíveis com:
Para modelos de chat:

Criando os clientes Venice e Qdrant

Crie um cliente Venice compatível com OpenAI para embeddings e chat completions:
Para o Qdrant, você tem três modos úteis: Para um bot local privado, comece com um caminho Qdrant local em disco:
Existem algumas maneiras diferentes de lidar com a implantação em produção. No entanto, se você usar uma implantação Qdrant remota, lembre-se de que seus chunks de documentos e metadados serão armazenados lá. A Venice pode manter a camada de inferência privada, mas você ainda deve escolher a implantação Qdrant certa para seus dados.

Carregando e dividindo documentos em chunks

Para este tutorial, deixaremos o bot ingerir arquivos ou pastas locais. Comece com arquivos .md, .rst e .txt:
Quando os arquivos são carregados, precisamos dividir o texto fazendo “chunking” — separando-o em pedaços de dados. Uma estratégia ingênua poderia dividir os chunks uniformemente. No entanto, na maioria dos casos, isso pode perder informação em limites semânticos, o que pode reduzir a eficácia do seu sistema RAG. A estratégia de chunking que usaremos prefere limites de parágrafo ou sentença para que o modelo receba contexto coerente:
Um tamanho inicial de chunk de 1000 caracteres com 150 caracteres de overlap é um bom padrão para documentos mistos de Markdown e texto. Chunks menores podem melhorar a precisão. Chunks maiores podem preservar mais contexto. A configuração certa frequentemente depende dos tipos de documentos que você está armazenando.

Fazendo embedding de documentos com a Venice

Quando temos os chunks, fazemos o embedding em lotes:
Batching importa. Fazer embedding de um chunk por vez é simples, mas adiciona latência evitável. Mantenha o tamanho do batch configurável para que possa ajustar o throughput com base na sua carga de trabalho.

Armazenando vetores no Qdrant

Antes de inserir pontos, crie uma coleção Qdrant com o tamanho de vetor correto. A maneira mais fácil de saber o tamanho do vetor é fazer o embedding do primeiro batch e depois usar len(embeddings[0]).
Cada ponto armazena o vetor mais metadados de payload. O payload inclui o texto original e um caminho de origem para que a resposta possa citar de onde o contexto veio:
Use UUIDs determinísticos derivados de source, chunk_index e conteúdo. Isso torna a ingestão repetida idempotente para chunks inalterados.

Recuperando chunks candidatos

No momento da pergunta, o bot faz embedding da pergunta do usuário e pede ao Qdrant as melhores correspondências vetoriais:
O limit aqui é o número de candidatos. Geralmente deve ser maior que o número de chunks que você planeja enviar ao modelo, porque o próximo passo vai re-rankeá-los. Um bom padrão é recuperar 8 candidatos e enviar os 4 melhores ao modelo de chat.

Re-ranking com FastEmbed

Agora adicionamos a parte que faz a recuperação parecer muito mais inteligente.
A diferença importante entre busca de embedding e re-ranking por cross-encoder é como a pontuação acontece. A busca por embedding compara um vetor da pergunta com um vetor de cada chunk. É rápida e escalável. Um cross-encoder avalia a pergunta e o chunk juntos. É mais lento, mas pode julgar a relevância mais diretamente. É por isso que o padrão usual é:
  1. Recuperar um conjunto maior de candidatos com busca vetorial.
  2. Re-rankear apenas esses candidatos localmente.
  3. Enviar os poucos chunks de topo ao modelo de linguagem.
Um bom ponto de partida é candidate_k=8 e top_k=4. Aumente candidate_k se a fonte certa frequentemente está próxima mas não está chegando ao contexto final.

Respondendo com chat completions da Venice

Quando o contexto é selecionado, formate-o com números de origem:
Depois envie o contexto a um modelo de chat Venice:
Note o system prompt: o bot é instruído a responder apenas a partir do contexto fornecido. Isso é um guardrail simples, mas importante. Um assistente RAG não deve responder com confiança a partir do conhecimento geral do modelo quando os documentos recuperados não suportam a resposta.

Executando o bot

Quando você montar as peças em um script, salve como rag_bot.py. Uma primeira execução simples pode usar alguns documentos de amostra integrados para que você verifique o pipeline antes de ingerir seus próprios arquivos:
Para ingerir seus próprios documentos:
Para manter uma coleção Qdrant local em disco e iniciar um chat interativo:
O script imprime a resposta e depois imprime as fontes com as pontuações de vetor e de re-ranking:
Se quiser inspecionar o texto real passado ao modelo, adicione:

Opções úteis de CLI

Exponha os principais knobs de recuperação como opções de CLI para poder ajustar o bot sem editar código: Para desenvolvimento local repetido, um fluxo comum é:
Depois faça perguntas subsequentes sem ingerir novamente:

Notas de privacidade

Para uma configuração RAG privada, pense em cada camada separadamente: O padrão mais privado para este tutorial é Venice para inferência, Qdrant local em disco e re-ranking FastEmbed local. Isso te dá um bot RAG prático sem enviar os payloads da sua base vetorial a um vector store de terceiros.

Erros comuns para tratar de imediato

Se você mudar os modelos de embedding, recrie a coleção Qdrant. Diferentes modelos de embedding podem produzir vetores com dimensões diferentes, e coleções Qdrant esperam um tamanho de vetor fixo.

Para onde ir a seguir

Quando você tiver a baseline rodando, as melhorias de maior impacto geralmente são:
  • Adicionar loaders específicos para PDFs, HTML, tickets ou páginas internas de wiki.
  • Armazenar metadados mais ricos como títulos, headings, datas, donos e URLs.
  • Ajustar candidate_k, top_k, tamanho de chunk e overlap em perguntas reais.
  • Adicionar perguntas de avaliação para medir a qualidade da recuperação antes e depois das mudanças.
  • Fazer streaming do chat completion final da Venice para uma experiência interativa melhor.
Sistemas RAG são fáceis de demonstrar e surpreendentemente fáceis de tornar medianos. O padrão de busca vetorial mais re-ranking é uma base sólida porque mantém a recuperação rápida ao mesmo tempo que dá ao bot uma chance melhor de enviar o contexto certo ao modelo de linguagem.