Como o chat funciona
O assistente deste site é um experimento de engenharia: um chat que roda no navegador, um Worker que fala com os modelos e uma busca sobre o próprio conteúdo do site. Esta página explica as peças e as decisões.
A arquitetura em um diagrama
Diagrama da arquitetura
O caminho da pergunta, do navegador aos providers, e os ramos que respondem sobre o site, geram artefatos e transmitem a resposta em streaming. Toque numa camada para ver os detalhes.
Fluxo principal
Busca, artefatos e streaming
Escolha uma camada para abrir os detalhes.
Worker pvsouza-ai
- POST /chat (conversa em streaming), POST /title (título curto), GET /models (catálogo) e GET /health.
- Valida a origem da requisição (CORS) antes de processar; erros anteriores ao stream viram JSON com código (origin_not_allowed, invalid_request, upstream_error).
- As chaves dos providers ficam só como secrets do Worker.
AI Gateway
- A Cloudflare registra latência, tokens, custo e status de cada chamada.
- Se o gateway falhar com erro de rede ou 5xx, a chamada é repetida uma vez direto na URL do provider.
- Erros 4xx não são repetidos: normalmente indicam chave inválida ou requisição recusada.
- O Gemini segue direto, sem a rota OpenAI-compatível do gateway.
Providers
- Cinco famílias: OpenAI, Workers AI (Cloudflare), Cerebras, OpenRouter e Google Gemini.
- O usuário escolhe o modelo no chat e o Worker roteia para o provider correspondente.
- Os compatíveis com a API da OpenAI usam a URL do gateway; o Workers AI usa o binding nativo.
buscar_site
- Ferramenta que consulta o corpus público quando a pergunta é sobre o Paulo, o site ou o chat.
- Combina BM25 (lexical) com similaridade de cosseno sobre embeddings bge-m3 de 1024 dimensões.
- Os rankings são fundidos por Reciprocal Rank Fusion (RRF, k=60), sem normalizar scores.
- Não há banco vetorial: o corpus cabe em memória no Worker; os trechos voltam numerados e viram chips de fonte.
Artefatos
- O modelo responde com um artefato HTML ou SVG autocontido quando o pedido é visual.
- A prévia roda num iframe com sandbox, sem acesso à origem da página.
- Reemissões do mesmo artefato viram versões, com diff entre elas.
Streaming
- A resposta chega no protocolo de UI message stream do Vercel AI SDK, sobre Server-Sent Events.
- O Worker escreve eventos tipados (text-start, text-delta, text-end, reasoning e finish) e o cliente renderiza cada pedaço.
- O usuário pode parar a geração no meio, e o cancelamento é repassado ao provider.
Site estático, IA fora dele
O site é um Next.js exportado como estático e publicado no Cloudflare Pages. Não existe servidor nem API route no site: a página do chat roda inteiramente no navegador e fala direto com um Worker Cloudflare separado, publicado em ai.pvsouza.com. As chaves dos providers ficam só como secrets do Worker.
Worker, gateway e providers
O Worker expõe as rotas da conversa em streaming, do título da conversa, do catálogo de modelos e de saúde. Antes de processar, valida a origem da requisição.
As chamadas passam por um gateway de IA da Cloudflare, que registra latência, tokens, custo e status por requisição. Se o gateway falhar com erro de rede ou 5xx, a chamada é repetida uma vez direto na URL do provider; erros 4xx não são repetidos. O catálogo reúne modelos de cinco famílias, e o usuário escolhe qual usar no próprio chat.
Streaming
A resposta chega em streaming no protocolo de UI message stream do Vercel AI SDK, sobre Server-Sent Events. O cliente renderiza cada pedaço conforme ele chega, então o texto aparece progressivamente em vez de esperar a resposta inteira. O usuário pode parar a geração no meio, e o cancelamento é repassado ao provider.
Artefatos
Quando o pedido é um componente visual, o modelo pode responder com um artefato HTML ou SVG autocontido. Ele aparece como um card no meio da conversa e abre num painel, com a prévia rodando num iframe isolado. Uma nova versão do mesmo artefato vira um diff, em vez de apagar a anterior.
A busca como ferramenta: buscar_site
O assistente tem uma ferramenta de busca, buscar_site, que consulta o corpus público do site. Quando a pergunta é sobre o Paulo, sobre este site ou sobre o próprio chat, o modelo chama a ferramenta com a pergunta do usuário e o Worker roda o retrieval sobre os chunks do corpus.
O retrieval combina duas buscas em memória: BM25, que é lexical, e similaridade de cosseno sobre embeddings pré-computados com o modelo multilíngue bge-m3. Os dois rankings são fundidos por Reciprocal Rank Fusion, que soma a contribuição de cada posição sem normalizar scores. Não existe banco vetorial gerenciado: o corpus é pequeno e cabe no Worker.
O resultado volta ao modelo como trechos numerados, para ele responder citando as fontes com [N], e à interface como chips de fonte com link. Trechos sem link público não são numerados nem viram chip. Se a busca não encontra nada, o modelo deve dizer que não achou a informação no site em vez de inventar.
O que fica de fora
O corpus é curado e público: nada de dados internos, nomes de clientes ou detalhes que permitam deduzi-los. O conteúdo passa por revisão editorial e entra no manifesto com fonte, licença e checksum antes de virar chunks.