Problema
Chat que envia histórico infinito ao modelo, não persiste threads e mistura “RAG” sem métricas de qualidade. UX quebra sob latência variável.
Solução
Modelar sessão (thread), mensagens com papel user/assistant/tool e política de contexto (última N mensagens + sumário). Backend expõe POST /chat/stream e opcionalmente GET /threads. Ferramentas (buscar pedido, criar ticket) como endpoints tipados retornando JSON ao modelo.
Arquitetura
React (UI + streaming UI) ↔ Node (orquestrador)
↘ vector store (opcional)
↘ tools HTTP internos
- Idempotência em ações side-effect (tool calls).
- Moderation antes de persistir mensagem pública.
Código
// pseudo-orquestrador
async function* streamReply(threadId: string, userText: string) {
const history = await repo.loadWindow(threadId, { maxTokens: 6000 });
const stream = llm.streamChat([...history, { role: "user", content: userText }]);
for await (const chunk of stream) {
yield chunk;
}
await repo.appendAssistant(threadId, accumulated);
}Performance
Streaming reduz percepção de latência; paralelizar tool calls independentes; truncar com sumário offline (job) para threads longas.
Melhorias futuras
Feedback explícito (👍/👎) para fine-tuning/RAG; evals de resposta; anexos com pipeline de OCR.
Conclusão
Chatbot vendável é estado + política de contexto + ferramentas. Esse desenho mostra visão full stack e de produto.