Groundline: um serviço RAG que calcula quanto dinheiro economiza

Um projeto pessoal em FastAPI e LangGraph: busca híbrida, reordenação, autoverificação e um cache semântico que cobre de 60 a 65 por cento das perguntas repetidas. A economia aparece na própria interface.

·
Groundline: busca sobre documentos que mede o próprio custo e a economia
Um RAG que mostra o preço de cada resposta

Nos últimos dias montei um projeto pessoal chamado Groundline e quero contar por que o fiz assim e quais problemas ele resolve.

Por que mais um RAG

Montar uma busca básica sobre documentos hoje não é problema, existem milhares de tutoriais. Mas a maioria dos projetos de estudo e de demonstração para no estágio de «ótimo, ele responde alguma coisa». Num negócio real a pergunta principal é outra: quanto custa operar isso.

Cada chamada a um modelo de linguagem custa dinheiro real e segundos de espera. Se os usuários perguntam a mesma coisa com palavras diferentes e o sistema refaz a busca vetorial completa e gera a resposta do zero toda vez, o orçamento vai embora repetindo trabalho já feito.

Resolvi construir um serviço que não apenas resolve a busca sobre documentos, mas também mostra a economia de forma visível, em números honestos.

Como funciona para o usuário

Você envia documentos em PDF, TXT ou Markdown e faz perguntas. Na saída recebe uma resposta clara com referências precisas à fonte: o arquivo, o trecho exato e a página. O modelo está estritamente proibido de inventar, ele trabalha apenas com o que foi realmente encontrado no texto.

A tela de documentos do Groundline com a área de upload
Envio de documentos: PDF, TXT e Markdown

Por dentro: sete passos de uma resposta

Quando chega uma pergunta, o sistema não corre direto para o modelo, ele percorre honestamente toda a cadeia.

  1. Cache semântico. Verificamos se já respondemos algo parecido. Se sim, devolvemos a resposta na hora sem gastar um único token.
  2. Reformulação. Se o cache errou, o modelo limpa a pergunta e expande as abreviações em uma consulta de busca decente.
  3. Busca híbrida. Rodamos em paralelo a busca vetorial por significado e a busca de texto completo por palavras exatas. A primeira capta sinônimos muito bem, a segunda não perde códigos, termos e referências específicas.
  4. Reordenação. Um modelo dedicado avalia os trechos recuperados e os reordena não pela semelhança formal, mas por quanto o fragmento realmente responde à pergunta.
  5. Autoverificação. O modelo avalia se o contexto é suficiente. Se não for, outra busca é disparada indicando exatamente o que falta, com no máximo duas tentativas adicionais.
  6. Geração. A resposta é transmitida ao usuário palavra por palavra.
  7. Gravação e cache. A resposta vai para o histórico e para o cache, para futuras perguntas parecidas.

O cache pelo qual tudo começou

O limiar de similaridade do cache não saiu do nada. Cada consulta registra a proximidade com a pergunta armazenada mais próxima, mesmo quando o cache não dispara. Com essas métricas ajustei o limiar para capturar reformulações reais sem jogar perguntas diferentes no mesmo balde.

No meu conjunto de teste com perguntas repetidas o cache cobre de 60 a 65 por cento das consultas. Em cenários de usuário realmente únicos esse número será menor, claro, mas o ganho econômico continua perceptível.

E a economia aparece enquanto o serviço trabalha:

  • qual passo do pipeline está rodando agora e quantos milissegundos ou tokens ele consumiu;
  • um gráfico ao vivo do gasto com o modelo contra o dinheiro economizado pelo cache.
O chat do Groundline com uma resposta, as fontes abertas e o painel do pipeline
O painel do pipeline mostra a duração de cada passo

Contra o que foi preciso lutar

  1. Disputa pelo processador. Os modelos locais de embeddings e de reordenação disputavam a CPU com a indexação em segundo plano dos arquivos novos. No pico, uma consulta comum levava 83 segundos em vez de algumas centenas de milissegundos. Resolvi com serialização rígida: a indexação de fundo e o processamento de perguntas agora esperam sua vez de acessar os modelos.
  2. Vazamento de conexões com o banco de dados. Se o usuário fechava a aba bem no meio da geração, a conexão ficava presa no pool. Numa hospedagem gratuita com limite microscópico de conexões isso derrubava o serviço rapidamente. Corrigi protegendo a gravação final no banco contra o cancelamento.

Pilha técnica

  • Backend: FastAPI, LangGraph, Python.
  • Banco de dados: Postgres com a extensão pgvector para busca vetorial, SQLAlchemy e Alembic para migrações.
  • Segurança: o isolamento de dados entre usuários não depende só do código, mas de Row-Level Security dentro do próprio banco. Um filtro esquecido numa consulta não vaza arquivos alheios.
  • Modelos e monitoramento: Groq para respostas rápidas, LangFuse para rastrear cada passo e a biblioteca ragas para avaliar qualidade, incluindo precisão, cobertura do contexto e ausência de alucinações.
O painel de limites do Groundline aberto com várias cotas visíveis
As cotas ficam à vista em vez de esconder dentro de um erro

Como essa cadeia se parece

Esses mesmos sete passos ficam mais claros vendo uma vez do que lendo. Um esquema interativo leva uma consulta por toda a cadeia e mostra o que muda em cada etapa:

Como um modelo responde a partir dos seus documentos

Leia mais