Pular para conteúdo

AI Insights v2 — Rework de Profundidade, UX e Robustez

Status: Planejado (épico #835) · continuação da frente Insights do épico #814 Data: 2026-06-09 Backlog: GitHub Projects #1 (Auraxis) — cards P5 · UX Executor: Claude (cross-repo: auraxis-api + auraxis-web)


1. Problema

Na página de Transações (app.auraxis.com.br/transactions) o card "Insights de IA" exibe "Insight indisponível — Não conseguimos interpretar este insight agora". Insights nunca deveriam ficar indisponíveis.

Causa-raiz

O card headline lê o insight mais recente do histórico. O mais recente é do tipo spending_patterns (gerado por cron via api-v2, formato {"patterns":[...]}, modelo gpt-4o-mini, 0 tokens). O parser do front (app/features/ai-insights/model/ai-insight.tsparseInsightContent) só entende o formato rico daily:

{ "summary": "...", "items": [{ "type": "...", "dimension": "...", "title": "...", "message": "..." }] }

Qualquer outro shape cai no FALLBACK_INSIGHT_ITEM = "Insight indisponível". Pior: mesmo se parseado, items de spending_patterns não têm dimension, mapeiam para general e seriam filtrados fora da página de Transações.

O que já está correto

O fluxo daily/weekly/monthly já é global: FinancialInsightContextBuilder monta um snapshot único com todas as dimensões (general, transactions, credit_cards, goals, budgets, wallet) e o prompt exige um item por dimensão (_ensure_financial_insight_dimension_coverage). Cada página filtra por dimension (AiInsightSurface.vue). O padrão "gerar global + exibir só o recorte da página" já existe — o spending_patterns é o intruso que o quebra, e os relatórios estão curtíssimos (max_tokens=512).


2. Objetivo

  1. Insights nunca indisponíveis (parser robusto a qualquer shape + fallback gracioso).
  2. Relatórios muito mais profundos: diário ~3 min de leitura; semanal/mensal ~15 min.
  3. Geração global com recorte por dimensão por página (transações não mostra metas/orçamentos).
  4. Modal de confirmação quando nada mudou desde o último insight.
  5. UX melhor: seções colapsáveis por dimensão, reading-time, markdown.

3. Decisões do PO (Italo, 2026-06-09)

Tema Decisão
Modelo LLM gpt-4o em diário, semanal e mensal. Custo projetado ~US$0,50/usuário/mês — dentro do teto de ~US$2,72. Downgrade automático p/ gpt-4o-mini quando o orçamento residual é baixo.
Profundidade Diário ~3 min de leitura (~600 palavras / ~900 tokens). Semanal/mensal ~15 min (~3.000 palavras / ~4.500 tokens).
Quota 1/dia não-cumulativa — reseta no dia (timezone do usuário); sobra não acumula nem rola para o mês seguinte. Substitui o pool "2/dia + 30/mês" do ADR. Recap mensal automático segue fora da quota.
spending_patterns Manter e renderizar — front parseia {"patterns":[...]} e marca dimension="transactions"; api-v2 segue gerando o "Radar". Headline passa a ser o insight rico, não o blob de patterns.
Entrega Épico único; PRs grandes domain-scoped.

Nota: a redução para 1/dia já havia sido decidida em 2026-05-30 (ver feature spec). Este épico torna a quota explicitamente não-cumulativa e remove o pool de "30/mês".


4. Estimativa de custo

Período Palavras Tokens saída Custo/geração (gpt-4o, $10/1M out) Frequência Custo/mês
Diário ~600 ~900 ~US$0,009 até 30/mês ~US$0,27
Semanal ~3.000 ~4.500 ~US$0,045 ~4/mês ~US$0,18
Mensal ~3.000 ~4.500 ~US$0,045 1/mês ~US$0,05
Total ~US$0,50 ✅ (teto ~US$2,72)

O teto rígido per-user (AI_INSIGHTS_*_BUDGET) e o downgrade automático para gpt-4o-mini permanecem como rede de segurança.


5. Escopo de implementação (cross-repo)

Backend — auraxis-api

#1481 — Relatórios profundos + max_tokens - ai_advisory_service.py::_build_financial_insight_prompt(): instruções por period_type exigindo profundidade alvo; permitir message em markdown multi-parágrafo e vários items por dimensão (schema atual não-quebrante). - llm_provider.py: max_tokens configurável por período (daily≈1500, weekly/monthly≈6000) via env. - Depth gate soft (métrica ai_insight_truncations_total{reason="below_depth_target"}; sem re-chamada automática).

#1482 — Quota 1/dia + change-status + GraphQL - ai_rate_limit.py: quota 1/dia não-cumulativa (timezone do usuário); teto de custo mantido. - Novo GET /ai/insights/change-status — monta snapshot, calcula context_hash, compara ao último insight, responde {changed, last_generated_at, last_context_hash} sem chamar o LLM. - Query GraphQL aiInsightChangeStatus (paridade REST+GraphQL) + openapi.json.

Frontend — auraxis-web

#1045 — Parser robusto, headline e recorte - model/ai-insight.ts: reconhecer {"patterns":[...]}InsightItem dimensão transactions; substituir fallback de erro por estado neutro gracioso. - Headline prioriza insight rico (daily/weekly/monthly); patterns viram item de transações. - Recorte estrito por dimensão; "Visão geral" sai das páginas contextuais; hub /insights mostra tudo. - Contratos/tipos regenerados.

#1046 — Render longo + modal "nada mudou" - AiInsightSection.vue: render markdown, seções colapsáveis por dimensão com badge de reading-time. - AiInsightButton.vue + useConfirm: antes de gerar, checar change-status; se changed=false, modal "Notamos que não houve movimentação desde o último insight gerado. Deseja gerar mesmo assim?".

Platform — docs/governança

#836 — amenda ao ADR de custo/quota, atualização da feature spec e desta página de wiki.


6. Ordem de build sugerida

  1. api#1482 (quota 1/dia + change-status) → base do modal.
  2. api#1481 (profundidade + max_tokens) → núcleo de valor.
  3. #836 (ADR/spec/docs) + regen de tipos.
  4. web#1045 (parser + headline + recorte) → elimina "Insight indisponível".
  5. web#1046 (render longo + modal).

7. Métricas de sucesso

  • 0 ocorrências de "Insight indisponível" em produção.
  • tokens_used do diário sobe de ~500 → ~900+; semanal/mensal ~4.500.
  • ai_insight_cost_usd_total por usuário ≤ teto.
  • Páginas contextuais exibem apenas a própria dimensão; /insights mostra tudo agrupado.
  • Modal de confirmação dispara corretamente quando changed=false.

8. Riscos

  • LLM não garante contagem exata de palavras — mitigado por alvos no prompt + max_tokens dimensionado + depth gate por métrica.
  • Manter spending_patterns mantém api-v2 no caminho (superfície extra de sincronização); o headline rico não depende dela.
  • Custo — monitorar após subir profundidade; downgrade automático é a rede de segurança.

9. Onda v3 (2026-07-10) — governança de geração, wallet real, snapshot rico e chat com tools

Continuação desta frente, decidida pelo PO em 2026-07-10 (platform #858). Muda o que está documentado acima nos seguintes pontos:

Tema v2 (acima) v3 (vigente)
Teto de custo ≤50% da assinatura (~US$2,72) R$5/usuário/mês (~US$0,91) — env AI_INSIGHTS_USER_BUDGET_PCT=0.167
Modelo gpt-4o em tudo Mix: gpt-4o só em semanal/mensal (cron); gpt-4o-mini no diário manual e no chat
Anti-regeneração cache por context_hash (volátil — furava com preço de mercado) dedupe semântico por (usuário, tipo, período) + hash sobre projeção estável (sem campos de mercado); regeneração só com force_regenerate
Quota contador único compartilhado (chat queimava o 1/dia) escopos independentes: insights 1/dia; chat 20/dia
GET /ai/insights/spending gerava no primeiro GET do dia read-only (generated:false quando não há insight; header Deprecation)
Enforcement decorator REST (GraphQL sem quota/gate) no service (ponto único REST+GraphQL)
Carteira no snapshot somava Wallet.value cru (R$0 p/ tickers) PortfolioValuationService (patrimônio/investido/P&L reais + data_quality.market_data_unavailable)
Chat snapshot diário de HOJE (não achava "salário de julho") month-aware + period detection pt-BR + function-calling (tools read-only, AI_CHAT_TOOLS_ENABLED)

Snapshot v3 (api #1547) adiciona: tags do usuário (agregações top gasto/receita por tag + budgets por tag), pendências rotuladas (overdue_items[], upcoming_7d/30d), month_summary (savings rate, burn rate, projeção de fim de mês) e prompt v3 com seções obrigatórias e proibição de insights genéricos sem número+ação.

Issues da onda: api #1546, #1547, #1548 · web #1113 · platform #858.


Referências