EN

Nº 05de 22Destaque

Project Wraeclast

Assistente com RAG: coleta diária em GitHub Actions, busca vetorial em Postgres com pgvector e resposta ancorada no contexto recuperado

Ano
2026
Status
EM CURSO
Papel
Projeto pessoal · solo
Stack
Python · FastAPI · PostgreSQL · pgvector +4
wraeclast
PW

Python

Sem captura pública — capa gerada

01O projeto

Assistente pessoal para um jogo cuja meta muda a cada patch. Uma rotina diária coleta economia, o personagem do dono e conteúdo da comunidade, resume cada documento em JSON estruturado com um LLM e grava o embedding num Postgres com pgvector. Na pergunta, a API FastAPI embeda o texto, recupera os trechos mais próximos por distância de cosseno e monta um bloco de contexto com preços, ranking de farms e perfil do personagem — o LLM responde só sobre esse bloco. Não há modelo treinado nem fine-tuning: a inteligência é o corpus curado que cresce todo dia. O site em Next.js tem as telas de hoje, de farms e de bancada de craft, mais um grafo do conhecimento coletado.

02O que foi feito

  1. Busca vetorial em Postgres com pgvector: embeddings de 1024 dimensões (truncagem Matryoshka para caber no índice HNSW) recuperados por distância de cosseno e filtráveis por tópico

  2. Sem fine-tuning e sem modelo próprio: o contexto do chat é montado dos trechos recuperados mais preços, farms e perfil do personagem, e o prompt manda responder só com esse contexto e avisar quando o dado faltar

  3. Coleta pesada separada da API: o cron diário roda no GitHub Actions, sem limite de tempo de execução; só as leituras e o /chat rodam como função serverless na Vercel

  4. 350 testes passando localmente com pytest e CI de ruff + pytest a cada push; a meta de 80% de cobertura por módulo está registrada e datada no ROADMAP

  5. O /chat é fechado por token comparado em tempo constante com hmac.compare_digest, e falha fechado quando o token não está configurado

03Decisões

Decisão 01

Pergunta: Por que RAG e não fine-tuning?

Resposta: O conteúdo muda a cada patch do jogo. Re-treinar modelo a cada mudança custa caro e envelhece rápido; um corpus curado que ganha documentos novos todo dia fica atualizado por construção, e o LLM entra só para curar texto em JSON e responder ancorado no que foi recuperado.

Decisão 02

Pergunta: Por que a coleta roda no GitHub Actions e não na própria API?

Resposta: Função serverless tem teto de tempo de execução, e a coleta diária (scraping, embeddings e curadoria via LLM) não cabe nesse teto. O job de cron roda no Actions e só grava no banco; a API fica com leitura e chat, que são rápidos o bastante.

Decisão 03

Pergunta: Por que truncar o embedding para 1024 dimensões?

Resposta: O provedor devolve 3072 dimensões por padrão e o índice HNSW do pgvector tem limite prático abaixo disso. A truncagem Matryoshka (parâmetro dimensions na própria chamada) faz o vetor caber no índice sem trocar de provedor nem perder a busca por similaridade.

04Stack

  • Python
  • FastAPI
  • PostgreSQL
  • pgvector
  • Next.js
  • TypeScript
  • GitHub Actions
  • Vercel
Próximo projeto →Nº 06

E-commerce transacional em Spring Boot: outbox com retry exponencial, idempotência de webhook e rate limit em Redis com circuit breaker