Merge pull request #450 from fsolla/plans/plan-issue-1
docs(plans): B173-B174 — Sollinha: consulta por voz + LLM movido para a Deep Infra
This commit is contained in:
commit
5b59e07143
2 changed files with 151 additions and 0 deletions
85
docs/plans/sollinha-consulta-por-voz.md
Normal file
85
docs/plans/sollinha-consulta-por-voz.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Sollinha — consulta por voz no chat
|
||||
|
||||
Status: plano — registrado (blocked até plano em main)
|
||||
Atualizado em: 2026-08-08
|
||||
Issue: #448
|
||||
Priority: P2
|
||||
Model: composer-2.5 (pool) / deepseek-v4-flash-high (local)
|
||||
Impeccable: C — encaixe no input do chat (superfície que o usuário toca)
|
||||
Canvas UI: /home/fsolla/.cursor/projects/home-fsolla-Code-teqo/canvases/plan-b173-ui-draft.canvas.tsx
|
||||
Appetite: ~0,5–1 dia eng; um outcome verificável
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
Hoje a Sollinha (assistente de IA em `/campanha`) só aceita pergunta em texto digitado. O assessor/coordenador trabalha em campo, muitas vezes com uma mão ocupada ou em pé — digitar uma pergunta sobre dados é atrito. Queremos poder **falar a pergunta** e ela virar a mesma mensagem do chat, mantendo o cérebro atual (DeepSeek + tools de dados + RBAC) intacto.
|
||||
|
||||
Decisão de produto coberta aqui (com custo): **converter voz→texto (STT) e reutilizar o fluxo existente**, em vez de mandar o áudio a um modelo multimodal. O modelo atual é texto-only; levar áudio direto a um modelo "que aceita voz" exigiria trocar de provider/modelo, reescrever a camada de tools/RBAC e pagar 20–100× por consulta — tudo por um ganho que o STT bem-feito já entrega. Na prática, até os "voice agents" fazem STT+TTS em volta de um LLM de texto. Custo de STT é desprezível na escala desta equipe (~dezenas–centenas de perguntas/dia × ~10 s de áudio ≈ centavos de dólar/dia).
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** assessor ou coordenador da campanha em `/campanha` (Field Desk/PWA) — no escritório ou em campo, com o celular ou notebook, sem vontade de digitar (ou com a mão ocupada).
|
||||
- **Job principal:** fazer uma pergunta à Sollinha em voz, sem tocar no teclado, e receber a mesma resposta que receberia digitando.
|
||||
- **Fluxo desejado:**
|
||||
1. No input do chat, toca no botão de microfone (painel desktop / drawer mobile — mesmas duas superfícies do chat atual).
|
||||
2. A barra entra em "Ouvindo…" com indicador + timer enquanto a pessoa fala.
|
||||
3. Ao parar (ou confirmar), o áudio vai para transcrição.
|
||||
4. A transcrição aparece como **rascunho editável** no campo de texto — a pessoa confere/corrige e envia.
|
||||
5. A pergunta segue exatamente o fluxo normal do chat (mesma auth, rate limit, tools, streaming). A resposta chega como hoje.
|
||||
6. Sem microfone/permissão negada → mensagem clara; chat por texto segue normal.
|
||||
- **Anti-goals de produto:** não é "voice agent" conversacional; não é TTS (responder em voz); não armazena gravações; não usa voz como login/biometria; não redesenha o chat (muda só o input).
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- Fazer toda uma pergunta à Sollinha por voz: tocar no mic → falar → transcrição vira o conteúdo do input → enviar.
|
||||
- A pergunta por voz passa pelos mesmos guards do chat de texto (autenticação, limite de mensagens, RBAC das tools).
|
||||
- Áudio processado para transcrição e **não armazenado** — nenhuma gravação fica no banco.
|
||||
- Perda de áudio / falha de transcrição → a pessoa pode tentar de novo ou digitar; nada quebra o chat de texto.
|
||||
- Transcrito entra como rascunho editável, nunca enviado automático sem revisão (nomes de municípios/lideranças errados iriam para as tools como se fossem verdade).
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — este item não apresenta métrica nova; é um novo meio de entrada para o mesmo fluxo.
|
||||
- **Decisões desbloqueadas:** ator digita menos em campo; a pergunta exata que o assessor fez (transcrição) chega às tools igual ao texto.
|
||||
- **Forma:** N/A.
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** o input do chat vive em `src/components/campaign/shell/ai/CampaignAIChat.tsx` (a `InputGroup` atual já tem placeholder + botão Enviar); o fluxo de resposta é `src/app/(campaign)/campanha/api/ai-chat/route.ts` (o texto transcrito entra pela mesma via); keys de IA em env do Vercel.
|
||||
- **Precedente a olhar:** `docs/plans/ai-chat-sollinha.md` (entrega original do chat — `in-prod`, imutável; o roadmap dela já previa "botão de microfone → envia para STT → injeta transcrição como sendMessage"); irmãos do mesmo painel: `docs/plans/largura-padrao-chat-sollinha.md` (B166), `docs/plans/migrar-chat-painel-drawer-resize.md` (B167).
|
||||
- **Risco de acoplamento:** o rate limit (`src/utilities/ai/rateLimit.ts`) é por usuário — perguntas por voz devem contar no mesmo balde para não virar bypass. Nada de escrever áudio em `media`/Blob: transiente. O provider do LLM muda no chore B174 (mesmo `route.ts`/env) — em produção a troca precisa de smoke das tools; a voz não depende dela para existir (STT usa a chave Deep Infra de qualquer forma).
|
||||
|
||||
## Dependências
|
||||
|
||||
- Soft: **B174** (chore — mover o LLM da Sollinha para a Deep Infra), que o usuário pediu junto; a voz não depende dele, mas os dois compartilham `route.ts`/env e o B174 é pré-condição da consolidação de uma chave só.
|
||||
- Soft: conviver com os irmãos de painel do chat (B166/B167 já `in-prod`/`in-progress` — a UI do input é compartilhada, cuidado com conflito de edição).
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- **TTS / responder por voz** → item sucessor separado (mesma família Sollinha).
|
||||
- Gravação para reuniões/sumário (o roadmap do chat original pregava isso) → item separado, desbloqueia depois.
|
||||
- Histórico/threads de conversa → já fora do v1 do chat (mantido).
|
||||
- Múltiplos provedores selecionáveis → não agora; um único STT configurado.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Voz direta para a IA multimodal".** Se alguém "só completar", troca o modelo e reescreve tools/RBAC por um ganho marginal. **Corte:** entrada por voz = STT + mesmo chat de texto; voz-direta só se um dia quisermos conversa falada completa (item separado, com orçamento próprio).
|
||||
- **Auto-enviar sem revisão.** Listar como "funciona" sem edição mandaria transcrição errada para as tools. **Corte:** rascunho editável por default; auto-envio no máximo como opção avançada.
|
||||
- **Persistir gravações "por segurança".** Áudio é dado pessoal de staff + custo/risco LGPD. **Corte:** processar e descartar; sem arquivo, sem collection.
|
||||
|
||||
## Decisões de produto (2026-08-08, confirmadas no gate)
|
||||
|
||||
- **A transcrição vira rascunho editável**, e o usuário envia — sem auto-send. STT em pt-BR erra nomes próprios (municípios, lideranças) e a pessoa quer conferir antes de virar "fato" para as tools.
|
||||
- **Não há TTS neste item** — só entrada por voz. Responder em voz fica como item sucessor separado.
|
||||
- **Fornecedor de STT: Deep Infra Whisper large-v3** (US$ 0,00045/min), mesma conta/chave do LLM — sem fornecedor novo. **Roda no browser foi avaliado e rejeitado:** Whisper via transformers.js/WebGPU é viável só até `small` (qualidade inferior ao large-v3 que a Deep Infra serve, ~590 MB de download, 2,5–3 GB inviável no celular); WebGPU é experimental no Safari e ausente no Firefox; no celular (principal superfície do Field Desk) é lento e pesado; e o chat já exige rede (DeepSeek/Payload), então on-device não compra nada — o custo servidor é desprezível (≈ US$ 0,00008/pergunta). Web Speech API nativa rejeitada: inconsistente, sem contrato com o fornecedor de voz e com suporte pt-BR local só experimental no Chrome.
|
||||
- **Prioridade P2** — Sollinha v1 é recém-deployada e sem métricas de uso ainda; validar aderência de texto antes de acelerar voz.
|
||||
- **LLM continua DeepSeek-V4-Flash, servido pela Deep Infra** (2026-08-08): avaliado o catálogo de texto da Deep Infra — Qwen3-32B (US$ 0,08/0,28) só é mais barato no input e perde no output e muito na capacidade (tool calling/pt-BR); Qwen3-235B/30B-A3B empatam ou pagam 2–6× o output; GLM-4.6 é 4–5×. V4-Flash (US$ 0,09/0,18, 1M ctx, MoE 13B ativos) segue imbatível no custo/poder pra ler dados com tools. A mudança é **mover o provider de `@ai-sdk/deepseek` (API oficial) para a Deep Infra** — mesmo endpoint OpenAI-compatível e mesma chave do STT — capturada no chore B174 (item separado; `smoke` das tools antes de prod, pois Sollinha já está em produção e o routing de tools é o músculo dela).
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue: #448 (B173)
|
||||
- Canvas UI (gate): /home/fsolla/.cursor/projects/home-fsolla-Code-teqo/canvases/plan-b173-ui-draft.canvas.tsx
|
||||
- `src/components/campaign/shell/ai/CampaignAIChat.tsx` — input do chat
|
||||
- `src/app/(campaign)/campanha/api/ai-chat/route.ts` — fluxo da resposta
|
||||
- `src/utilities/ai/rateLimit.ts` — balde por usuário
|
||||
- `docs/plans/ai-chat-sollinha.md` — precedente (imutável)
|
||||
66
docs/plans/sollinha-no-deepinfra.md
Normal file
66
docs/plans/sollinha-no-deepinfra.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Sollinha no Deep Infra (LLM) — mesma API e chave dos agentes
|
||||
|
||||
Status: plano — registrado (blocked até plano em main)
|
||||
Atualizado em: 2026-08-08
|
||||
Issue: #449
|
||||
Priority: P2
|
||||
Model: composer-2.5 (pool) / deepseek-v4-flash-high (local)
|
||||
Impeccable: A — sem UI
|
||||
Canvas UI: N/A — sem UI
|
||||
Appetite: ~0,5 dia eng; um outcome verificável
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
A Sollinha hoje fala com a API oficial da DeepSeek (`@ai-sdk/deepseek` → `api.deepseek.com`), enquanto os agentes do time já usam a Deep Infra. O usuário quer consolidar num só provedor/chave. Avaliado o catálogo de texto da Deep Infra: **DeepSeek-V4-Flash permanece o modelo**, servido pela Deep Infra (US$ 0,09/M input, US$ 0,18/M output, 1 M ctx) — nenhum modelo deles é mais barato no total input+output mantendo tool calling/pt-BR/contexto (Qwen3-32B só ganha no input e perde no output e em capacidade; Qwen3-30B/235B A3B empatam ou pagam 2–6× o output; GLM-4.6 é 4–5×). Este item é só o **movimento de provider**, mantendo o modelo e o comportamento.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** dev/equipe Teqo — reduzir superfície operacional (um provedor, uma chave, uma fatura) sem mudar nada para o assessor.
|
||||
- **Job principal:** continuar perguntando à Sollinha e receber as mesmas respostas, agora roteada pela Deep Infra, com as tools funcionando igual.
|
||||
- **Fluxo desejado:** deploy com o `route.ts` apontando para a Deep Infra → smoke das tools com a chave nova → assessor usa o chat sem notar diferença → rollback imediato (reverter baseURL) se qualquer tool falhar.
|
||||
- **Anti-goals de produto:** trocar de modelo (fica V4-Flash); reescrever tools "porque mudou a API"; mexer em UI; migrar dados.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- A Sollinha é servida pela Deep Infra usando o mesmo modelo (DeepSeek-V4-Flash) e as mesmas tools, com respostas equivalentes.
|
||||
- Smoke explícito das tools de dados antes de tocar produção (Sollinha já está em prod; o routing de tools é o músculo dela).
|
||||
- Rollback barato e documentado: uma chave/baseURL antiga faz o chat voltar ao estado atual.
|
||||
- Nenhuma mudança visível para o assessor; env/e2e com o endpoint mockado continua sem chave real no CI.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
- **Vou apresentar dados?** Não — melhoria operacional.
|
||||
- **Decisões desbloqueadas:** uma única credencial para agentes + Sollinha + STT futuro (B173).
|
||||
|
||||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:** `src/app/(campaign)/campanha/api/ai-chat/route.ts` (o `deepSeek('deepseek-v4-flash')` vira o caminho OpenAI-compatível da Deep Infra — p.ex. `@ai-sdk/deepinfra` com `deepseek-ai/DeepSeek-V4-Flash`, ou baseURL `https://api.deepinfra.com/v1/openai`); env `DEEPINFRA_API_KEY` em Vercel produção + `.env.example`.
|
||||
- **Precedente a olhar:** `docs/plans/ai-chat-sollinha.md` (decisão "modelo deepseek-v4-flash" mantida; só o provedor muda).
|
||||
- **Risco de acoplamento:** mesmo arquivo que B173 (voz) toca — fazer antes ou em acordo para não conflitar; verificar no smoke se o tool calling do V4-Flash se comporta igual pela Deep Infra antes de flipar.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Nenhuma dura. Soft: B173 (voz) reaproveita a mesma chave Deep Infra para o STT.
|
||||
|
||||
## Fora de escopo
|
||||
|
||||
- Trocar o modelo (continua DeepSeek-V4-Flash).
|
||||
- Reescrever as tools / sistema da Sollinha.
|
||||
- Qualquer UI.
|
||||
|
||||
## Rabbit holes de produto
|
||||
|
||||
- **"Aproveita e troca o modelo também".** Explosão de risco sem ganho de custo. **Corte:** modelo fixo; reavaliar só com evidência de qualidade nova.
|
||||
- **"Reescrever as tools pro formato novo".** API é OpenAI-compatível; se algo falhar é smoke/downgrade, não refactor. **Corte:** teste, não reescreva.
|
||||
|
||||
## Questões em aberto (produto)
|
||||
|
||||
- Nenhuma bloqueadora. Confirmação de escopo: manter como **chore separado (B174)** — recomendado, pois o swap tem blast radius próprio (Sollinha em produção) independente da feature de voz; ou dobrar dentro do B173.
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue: #449 (B174)
|
||||
- `src/app/(campaign)/campanha/api/ai-chat/route.ts` — ponto do swap
|
||||
- `docs/plans/sollinha-consulta-por-voz.md` (B173) — onde a chave Deep Infra é reaproveitada no STT
|
||||
- `docs/plans/ai-chat-sollinha.md` — precedente (imutável)
|
||||
Loading…
Reference in a new issue