Skip to main content
Voltar para Projetos

RAG Engine em Rust

Backend RAG em Rust: recuperação híbrida em dois estágios com pgvector, chat em streaming via WebSocket com atores Actix, inferência local com Ollama.

RustRAGActixpgvectorOllamaWebSocketRecuperação Híbrida

Overview

A maioria das demos de RAG para no busca vetorial pura. Este projeto vai além: um pipeline de recuperação híbrida em dois estágios onde a busca semântica por cosseno no pgvector reduz o conjunto de candidatos, depois um re-ranking por palavras-chave pontua dentro desse conjunto e combina os dois sinais. O resultado lida com consultas de termos exatos que enganam a busca vetorial pura, sem sacrificar o recall em consultas parafraseadas. Tudo em Rust — não por ser na moda, mas porque a arquitetura exige: um modelo de atores Actix por sessão WebSocket, um pipeline Ollama com concorrência limitada e uma integração com pgvector que precisa de async sem overhead. O lado de ingestão busca artigos de uma API REST no estilo HelpScout, converte HTML em Markdown limpo usando html2md e regras customizadas de scraper, armazena artigos canônicos no PostgreSQL via Diesel ORM, e depois distribui para dois pipelines paralelos: um microsserviço Python (Flask + all-MiniLM-L6-v2) gera os embeddings armazenados no pgvector, enquanto um pipeline Ollama com concorrência limitada gera palavras-chave e resumos por artigo. O pipeline de metadados usa um Semaphore do Tokio e buffer_unordered para limitar as chamadas simultâneas ao LLM local, com rastreamento estruturado de sucesso/parcial/falha e persistência dos IDs com falha para reprocessamento. O chat em streaming funciona através de um modelo de atores Actix. Cada conexão WebSocket gera um ator ChatSession; um ator central ChatServer roteia mensagens e gerencia o estado da sessão. A API de streaming do Ollama é consumida token por token e encaminhada em tempo real pela conexão — o cliente vê as palavras aparecerem conforme são geradas, ancoradas em artigos recuperados pelo pipeline híbrido. Um balanceador de carga Ollama round-robin com thread pool do Rayon está incluído no código para distribuição de inferência em múltiplas instâncias — presente e funcional, aguardando hardware. Este é um serviço exclusivamente de backend — o scaffold de frontend incompleto foi removido intencionalmente. O valor está na infraestrutura: um pipeline RAG em Rust de nível produção com recuperação híbrida real, chat em streaming e design centrado em inferência local. Build limpo, zero avisos do clippy, 19 testes, CI configurado. Código público no GitHub sob bredmond1019.

Technical Stack

IA / Recuperação

  • ▸pgvector (similaridade por cosseno)
  • ▸Sentence Transformers (all-MiniLM-L6-v2)
  • ▸Ollama (llama3.1)
  • ▸Recuperação híbrida em dois estágios
  • ▸Re-ranking por palavras-chave

Backend

  • ▸Rust (edição 2021)
  • ▸Actix-web 4
  • ▸Atores Actix
  • ▸Tokio
  • ▸Diesel 2

Dados

  • ▸PostgreSQL
  • ▸pgvector
  • ▸Migrations Diesel
  • ▸Python Flask (microsserviço de embeddings)

Infraestrutura

  • ▸GitHub Actions CI
  • ▸Docker (Postgres + pgvector)

Key Features

✓

Recuperação híbrida em dois estágios: busca semântica por cosseno no pgvector reduz candidatos, re-ranking por palavras-chave combina os sinais para pontuação final

✓

Modelo de atores Actix para chat WebSocket — atores ChatSession por sessão gerenciados por um ChatServer central

✓

Streaming token por token do Ollama encaminhado em tempo real pela conexão WebSocket

✓

Pipeline de metadados com concorrência limitada usando Semaphore e buffer_unordered do Tokio para controlar chamadas simultâneas ao Ollama

✓

Sincronização paginada de artigos de uma API REST no estilo HelpScout com timeout de 30 segundos e conversão completa de HTML para Markdown

✓

Microsserviço de embeddings em Python com sentence-transformers all-MiniLM-L6-v2 na porta 8080

✓

Fila de jobs assíncrona para ingestão em background com rastreamento de status por job

✓

Persistência de artigos com falha e endpoint de re-embedding para recuperação de falhas parciais no pipeline

✓

Balanceador de carga Ollama round-robin (thread pool Rayon) para distribuição de inferência em múltiplas instâncias — incluído, aguardando hardware

Code Examples

Technical Challenges

▪

Projetar a fusão de recuperação em dois estágios para que o re-ranking por palavras-chave melhore a precisão em termos exatos sem regredir o recall semântico

▪

Construir o modelo de atores Actix para que o histórico de chat por sessão fique dentro do ator, sem estado externo compartilhado

▪

Implementar concorrência limitada no pipeline de metadados — Semaphore + buffer_unordered — para que chamadas em lote ao Ollama não saturem o hardware local

▪

Fazer o vendoring e patching do ollama-rs 0.2.0: a versão upstream 0.2.x→0.3.x mudou a API de histórico para exigir Arc<Mutex<MessagesHistory>> externo, incompatível com o modelo de atores por sessão

▪

Escrever regras customizadas de scraper para conversão HTML-Markdown preservando a estrutura de artigos de suporte longos e aninhados

▪

Manter a interface do microsserviço de embeddings estável para que mudanças de dimensão de embedding sejam tratadas via migration, não via código

Project Outcomes

Limpo — zero avisos do clippy, cargo fmt pass
Build
19 passando (api_client, article, conversão HTML)
Testes
Somente backend, autocontido — clone limpo compila
Escopo
Público no GitHub (bredmond1019)
Código