Piloto: sumário executivo, gráficos, metodologia e conclusão

- analysis/charts.py: gráficos SVG (acurácia, qualidade × latência, GPU × CPU)
  com paleta validada para daltonismo.
- collect.py regenera só a tabela entre marcadores e preserva o README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Marcos Lohmann
2026-10-07 18:21:53 -03:00
parent 0ec89cd40f
commit 48159adf56
6 changed files with 1469 additions and 10 deletions

View File

@@ -1,7 +1,37 @@
# Resultados — partição `dev`, 50 exemplos
# Piloto — 50 exemplos de desenvolvimento por candidato
Gerado por `infra/ds/collect.py` a partir dos buckets de resultados. CPU: us-chicago-1 (`VM.Standard.E4.Flex`, 8 OCPU, sub-rede privada). GPU: sa-saopaulo-1 (`VM.GPU.A10.1`). Lote 1; latências excluem os exemplos de aquecimento. Probabilidades ainda sem calibração.
## Sumário executivo
O piloto validou, de ponta a ponta, a execução dos quatro candidatos sobre a mesma amostra de 50 enunciados de atendimento de telefonia móvel, em CPU e em GPU. Não houve erros de execução nem truncamento de entrada, e nenhum parâmetro operacional precisou de ajuste.
- **Qualidade:** os dois modelos de 4B parâmetros lideram. O **SemIf** acertou **92%** e o **Rizzo Flow** **82–86%**. Os encoders compactos ficaram abaixo: **Laya** com 66% e **GLiNER** com 48%.
- **Abstenção:** o SemIf reconheceu 10 de 12 pedidos sem intenção correspondente; o Laya, 4 de 12. Esse é o comportamento que evita rotas erradas no orquestrador.
- **Latência em GPU A10:** Laya e GLiNER respondem em cerca de **20 ms**; SemIf e Rizzo, em cerca de **110 ms** de mediana. Mas o **p95 dos modelos de 4B (175–181 ms) fica acima do limite pré-registrado de 150 ms**.
- **CPU:** só Laya e GLiNER são viáveis (p95 de 0,2 a 0,5 s). SemIf e Rizzo levam de 13 a 31 s por decisão e ficam fora das rodadas em CPU.
- **Leitura preliminar:** há um *trade-off* claro entre qualidade e latência, que a rodada completa de desenvolvimento, a calibração e o teste final (1.744 exemplos) vão quantificar com intervalos de confiança.
## Resultados gerais
![Acurácia por candidato](chart-acuracia.svg)
![Qualidade × latência em GPU](chart-qualidade-latencia.svg)
![Latência por decisão: GPU × CPU](chart-latencia.svg)
| Candidato | Acertos dentro do escopo (38) | `sem_correspondencia` reconhecido (12) | Escopo marcado como `sem_correspondencia` |
|---|---|---|---|
| SemIf | 36 | 10 | 2 |
| Rizzo Flow | 34 | 7 | 2 |
| Laya | 29 | 4 | 0 |
| GLiNER | 19 | 5 | 11 |
*(GPU A10. Em CPU os números coincidem, exceto o Rizzo Flow, que acerta 2 casos a mais: os backends CPU e CUDA do llama.cpp não são numericamente idênticos.)*
## Resultados detalhados
Lote 1. As latências excluem os 5 primeiros exemplos (aquecimento). ECE calculado sobre as probabilidades brutas, ainda sem calibração.
<!-- TABELA:INICIO -->
| Candidato | Disp. | Precisão | n | Acurácia | Macro F1 | ECE (bruto) | p50 ms | p95 ms | p99 ms | Carga s | RAM pico MiB | GPU pico MiB | Erros | Truncados |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| gliner | cpu | float32 | 50 | 48.0% | 43.9% | 0.198 | 244.0 | 481.0 | 511.6 | 21.0 | 3257 | — | 0 | 0 |
@@ -12,3 +42,33 @@ Gerado por `infra/ds/collect.py` a partir dos buckets de resultados. CPU: us-chi
| rizzo_flow | cuda | gguf-q8_0 | 50 | 82.0% | 84.3% | 0.103 | 108.1 | 174.7 | 182.5 | 5.3 | 4527 | 5107 | 0 | 0 |
| semif | cpu | bfloat16 | 50 | 92.0% | 93.9% | 0.079 | 30633.4 | 47585.7 | 49344.0 | 6.3 | 9137 | — | 0 | 0 |
| semif | cuda | bfloat16 | 50 | 92.0% | 93.9% | 0.114 | 113.8 | 181.3 | 183.7 | 6.7 | 9020 | 8513 | 0 | 0 |
<!-- TABELA:FIM -->
Arquivos: `summary-<candidato>-<dispositivo>.json` (resumo da execução, com cenário, precisão e diagnósticos) e `predictions-<candidato>-<dispositivo>.jsonl` (uma linha por exemplo, com a distribuição de probabilidades completa).
## Metodologia
**Amostra.** São 50 exemplos sorteados com seed fixa (20261007) da partição de desenvolvimento do conjunto congelado `d1-v1`. Os candidatos recebem os mesmos exemplos, na mesma ordem.
| Característica | Composição da amostra |
|---|---|
| Intenções distintas | 29 das 42 da taxonomia |
| Rótulo `sem_correspondencia` | 12: 8 pedidos fora de escopo e 4 com a intenção correta fora das opções |
| Opções por pergunta | 4 (15 exemplos) · 8 (14) · 12 (9) · 16 (12) |
| Perfis de escrita | informal/abreviado (12), erros de digitação (11), curto/neutro (8), regionalismo (8), emocional (5), indireto/várias intenções (5), longo (1) |
**Tarefa.** Classificação de intenção (D1): para cada enunciado, o candidato escolhe uma opção entre as intenções elegíveis do exemplo mais `sem_correspondencia`, pelo contrato `POST /v1/systemone` (`jev-compat-v1`).
**Execução.** Lote 1 e sem paralelismo; cada candidato na sua precisão nativa (fp32 para Laya e GLiNER, bf16 para SemIf, GGUF Q8_0 para Rizzo Flow). Inferência isolada de fontes externas, com artefatos verificados por SHA-256.
**Cenário.** CPU em us-chicago-1 (`VM.Standard.E4.Flex`, 8 OCPU, 64 GB). GPU em sa-saopaulo-1 (`VM.GPU.A10.1`). Mais detalhes em [docs/05](../../docs/05-cenario-de-execucao.md).
**Limites desta etapa.** Com 50 exemplos, cada ponto percentual de acurácia corresponde a meio exemplo, e os intervalos de confiança são largos (cerca de ±13 p.p. a 95%). O piloto serve para validar a execução e dar a ordem de grandeza, não para ranquear.
## Conclusão
1. **Execução validada.** Os quatro candidatos rodam isolados, sem erros e sem truncamento, com a mesma entrada e o mesmo contrato, em CPU e em GPU. O piloto não exigiu ajuste operacional; o orçamento interno de opções do Laya foi verificado e mantido no padrão.
2. **CPU restrita aos encoders.** Pela regra pré-registrada (p95 ≤ 10 s), SemIf e Rizzo Flow ficam fora das rodadas em CPU.
3. **Sinal de qualidade.** Os modelos de 4B lideram em acurácia e em abstenção correta. Entre os compactos, o Laya acerta mais dentro do escopo, mas quase não abstém; o GLiNER marca muitos pedidos válidos como `sem_correspondencia`.
4. **Sinal de latência.** Em GPU, só Laya e GLiNER cumprem o p95 ≤ 150 ms. SemIf e Rizzo ficam perto do limite (cerca de 110 ms de mediana), mas acima dele no p95.
5. **Próximos passos.** Rodada completa de desenvolvimento (1.183 exemplos), calibração das probabilidades e escolha de limiares de abstenção (1.127 exemplos), congelamento da configuração e teste final (1.744 exemplos), com intervalos de confiança e cortes por perfil e número de opções.