AGO 2026 — Presente

Portfólio

Aplicação em produção com um LLM rodando de verdade: o recrutador cola a descrição da vaga e recebe, via pipeline próprio de RAG híbrido, um relatório de fit gerado a partir do meu histórico profissional real, com citação rastreável em cada afirmação.

Portfólio

O que é

Não é uma página estática com um CV em PDF disfarçado: é uma aplicação em produção com um LLM rodando de verdade por trás. A seção central, "Sou recrutador", recebe a descrição de uma vaga e devolve, em segundos, um relatório de fit gerado por um pipeline próprio de RAG híbrido sobre meu histórico profissional real — projetos e experiências indexados —, com citação rastreável pra cada afirmação factual. Não é um resumo genérico gerado por IA: é retrieval sobre conteúdo real, com prova de origem.

Este texto que você está lendo agora é, ele mesmo, um exemplo do mecanismo: o arquivo MDX que gera esta página é o mesmo que alimenta o índice de busca do relatório de match. Se você chegou aqui a partir de uma citação [[cite:project:portfolio]], é porque o pipeline descrito abaixo funcionou.

Conteúdo como fonte única

Cada projeto e experiência vive em um único arquivo .mdx, com frontmatter estruturado (período, empresa, skills, mídia) e corpo em Markdown. Esse mesmo arquivo alimenta duas coisas ao mesmo tempo: a página renderizada (como esta) e o chunk indexado pro relatório de match. Não existe um CMS separado nem uma segunda cópia do conteúdo pro RAG — evita o problema clássico de "documentação que desalinha do produto", porque aqui documentação e produto são o mesmo arquivo.

Optei por Velite (em vez de um headless CMS externo) justamente por isso: o volume de conteúdo é o de um portfólio pessoal, não o de uma equipe editorial, então versionar tudo como MDX no próprio repositório é mais simples do que operar um serviço externo só pra isso.

Indexação e retrieval híbrido

No build, cada chunk (projeto ou experiência) vira um embedding vetorial via Vertex AI (gemini-embedding-001) e é salvo num knowledge.json estático. Ao receber uma vaga, calculo a similaridade de cosseno entre a descrição e cada chunk, combino com um score léxico (BM25, via minisearch) e seleciono os trechos mais relevantes — retrieval híbrido, sem banco vetorial dedicado.

Essa é uma decisão deliberada, não uma limitação: pro volume de conteúdo de um portfólio pessoal, rodar um banco vetorial dedicado seria complexidade desproporcional ao problema. Se o conteúdo crescesse muito além disso, um banco vetorial próprio entraria na conta — mas hoje não se paga.

Geração com citação obrigatória

A geração usa Gemini via Vertex AI como provedor padrão, acessado pelo Vercel AI SDK. DeepSeek entra como alternativa plugável só pro passo de geração (ele não tem API de embeddings), trocando o baseURL do cliente OpenAI-compatible do SDK — a troca de provedor de geração não exige tocar no pipeline de retrieval.

O modelo recebe só os trechos selecionados pelo retrieval e é instruído a citar [[cite:ID]] em toda afirmação factual. Antes de exibir a resposta, cada ID citado é validado contra o knowledge.json real — citação que não corresponde a um chunk existente é descartada, não corrigida "no chute". É o guarda-corpo que impede o relatório de inventar experiência que não existe.

Anti-abuso

A rota que fala com o Vertex AI roda em runtime Node.js (não Edge), porque a autenticação via service account exige isso. Duas camadas protegem essa rota de uso indevido: rate limiting por IP com janela deslizante (via Upstash Redis) e Cloudflare Turnstile no formulário, pra barrar automação. Não vou detalhar limiares aqui — é justamente o tipo de número que perde valor de proteção quando fica público.

Decisões

  • ▹Home single-page com sidebar, em vez de landing multi-seção convencional: um recrutador apressado precisa colar a vaga e ler o relatório sem sair da home e sem procurar onde fica a ferramenta. /projetos/[slug] e /experiencia/[slug] existem como páginas próprias à parte porque são o alvo das citações — precisam de uma URL estável pra apontar.
  • ▹Retrieval híbrido caseiro, em vez de banco vetorial dedicado: já coberto acima — volume não justifica a complexidade extra.
  • ▹Vertex AI como padrão, DeepSeek como alternativa plugável só pra geração: mantém a porta aberta pra trocar de provedor de LLM sem reescrever o pipeline de embeddings/retrieval, que continua sempre no Vertex AI.
  • ▹Dark-only, sem toggle de tema: paleta e tipografia são tokens fixos — decisão de identidade visual, não uma feature adiada.

Galeria

Voltar para projetos