mirror of
https://github.com/mcloh/decision-models-benchmark.git
synced 2026-11-05 22:04:12 +00:00
setup environment
This commit is contained in:
74
docs/01-contexto-arquitetural.md
Normal file
74
docs/01-contexto-arquitetural.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# 01 — Contexto arquitetural
|
||||
|
||||
Este documento descreve a arquitetura de referência em termos genéricos e só com os conceitos necessários ao experimento. O objetivo é deixar claro **onde** o modelo de decisão atua e **quais informações de contexto** ele recebe.
|
||||
|
||||
## Componentes da arquitetura de referência
|
||||
|
||||
| Componente | Papel | Relevância para o benchmark |
|
||||
|------------|-------|-----------------------------|
|
||||
| **Adaptador de canal** | Integra canais de interação (chat, mensageria, voz) e normaliza a entrada | Define o formato do enunciado que chega ao orquestrador |
|
||||
| **Agente Orquestrador** | Supervisiona cada turno: identifica a intenção, aplica políticas, controla sessões e seleciona o agente | **Hospeda o modelo de decisão avaliado** |
|
||||
| **A2A Gateway** | Registra agentes (cards) e faz autenticação, mediação de tarefas A2A, ciclo de vida de tarefas (IDs, estado, retomada, cancelamento), além de erros e timeouts | Fonte do catálogo de agentes, que vira o conjunto de opções de destino |
|
||||
| **A2A Adapter** | Permite que agentes sem A2A nativo conversem com o orquestrador de forma padronizada | Fora de escopo, exceto como opção de destino |
|
||||
| **Agentes especializados** | Agentes de domínio, um agente de propósito geral (por exemplo, com busca web) e outros | São as **classes de destino** do roteamento |
|
||||
| **MCP Gateway / Server** | Expõe ferramentas e fontes de dados com contrato padronizado, *discovery*, autenticação e limites | Fonte de dados para pré-requisitos e para o **serviço de elegibilidade de intenções** |
|
||||
| **Serviço de elegibilidade de intenções** | A partir das intenções mapeadas, identifica as que são elegíveis para um dado usuário | **Restringe as opções** apresentadas ao modelo de decisão |
|
||||
| **LLM Gateway** | Centraliza o acesso a modelos (LLM, busca e modelos System 1), além de políticas, limites e telemetria | Ponto de integração natural do modelo de decisão em produção |
|
||||
| **Memória curta** | Estado operacional da conversa e de cada sessão de agente (`conversation_id`, `session_id`/`task_id`, `agent_id`) | Fornece o **estado** (`state`) da requisição de decisão |
|
||||
| **Memória longa** | Fatos e preferências duradouros entre sessões | Contexto opcional; avaliado só se fizer parte do `state` |
|
||||
| **Base de personalização** | Atributos declarados e inferidos do usuário, com acesso governado | Fora de escopo no primeiro ciclo |
|
||||
| **Observabilidade** | OpenTelemetry Collector, Pub/Sub, armazenamento de traces e logs, dashboards, avaliação de LLM e data lake | Modelo de telemetria usado pelo harness (latência, `run_id`, `model_id`) |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
U[Usuário] --> CA[Adaptador de canal]
|
||||
CA --> ORQ
|
||||
subgraph ORQ[Agente Orquestrador]
|
||||
DM[[Modelo de decisão<br/>POST /v1/systemone]]
|
||||
end
|
||||
MC[(Memória curta)] --> ORQ
|
||||
ML[(Memória longa)] --> ORQ
|
||||
ORQ <--> MCP[MCP Gateway] --> EL[Serviço de elegibilidade]
|
||||
ORQ <--> LLMG[LLM Gateway]
|
||||
ORQ <--> A2A[A2A Gateway]
|
||||
A2A <--> AG1[Agente especializado A]
|
||||
A2A <--> AG2[Agente especializado B]
|
||||
A2A <--> AGG[Agente de propósito geral]
|
||||
ORQ -.-> OT[OTel Collector]
|
||||
```
|
||||
|
||||
## Fluxo de um turno no orquestrador
|
||||
|
||||
1. Registrar a mensagem recebida, carregar o estado da conversa e carregar os atributos de contexto.
|
||||
2. Aplicar os **guardrails de entrada**.
|
||||
3. **Classificar e analisar a intenção.**
|
||||
4. Seguir um destes ramos:
|
||||
- **rotear para o agente ativo** via A2A;
|
||||
- **executar os pré-requisitos** e **iniciar uma sessão com um novo agente** via A2A;
|
||||
- **preparar perguntas de pré-requisito**;
|
||||
- **preparar uma pergunta de desambiguação de intenção**.
|
||||
5. Validar o retorno do agente.
|
||||
6. Preparar a resposta e aplicar os **guardrails de saída**.
|
||||
7. Registrar a mensagem e os estados.
|
||||
|
||||
## Pontos de decisão avaliados
|
||||
|
||||
O benchmark avalia os pontos de decisão em que um modelo System 1 substitui ou antecede uma chamada a um LLM generalista. Cada ponto vira uma **tarefa de decisão** com pergunta, opções e regra de decisão próprias. A definição completa está em [02-desenho-experimental.md](02-desenho-experimental.md).
|
||||
|
||||
| ID | Ponto de decisão | Etapa do fluxo | Tipo JEV previsto |
|
||||
|----|------------------|----------------|-------------------|
|
||||
| D1 | Classificação de intenção entre as intenções **elegíveis** | Passo 3 | `choice` |
|
||||
| D2 | Continuidade de sessão: manter o agente ativo, retomar uma sessão suspensa, iniciar um novo agente ou desambiguar | Passo 4 | `choice` |
|
||||
| D3 | Necessidade de desambiguação: a intenção está clara o suficiente para rotear? | Passos 3–4 | `noul` ou `score`, a confirmar (ver questões em aberto) |
|
||||
| D4 | Várias intenções no mesmo enunciado: quais intenções estão presentes | Passo 3 | várias decisões sobre o mesmo texto (tarefa 65) |
|
||||
| D5 | *(opcional)* Guardrail de entrada: dentro do escopo, fora do escopo ou bloqueado | Passo 2 | `choice` |
|
||||
|
||||
Ficam **fora de escopo**: geração de resposta, validação do retorno dos agentes, guardrails de saída, extração de atributos de personalização e o próprio protocolo A2A/MCP. A elegibilidade de intenções é **simulada**: o conjunto de opções elegíveis já vem pronto em cada exemplo.
|
||||
|
||||
## Requisitos não funcionais que derivam da arquitetura
|
||||
|
||||
- **Latência por turno.** O modelo roda em todos os turnos, no caminho síncrono do usuário. Por isso, p95 e p99 com lote 1 são a métrica operacional principal.
|
||||
- **Contexto curto.** A decisão usa o enunciado e um resumo do estado (agente ativo, sessões abertas, últimos turnos), não o histórico completo.
|
||||
- **Opções dinâmicas.** O conjunto de opções muda a cada usuário e a cada turno, por causa da elegibilidade e das sessões abertas. Os modelos precisam aceitar opções descritas em tempo de inferência, sem retreino.
|
||||
- **Abstenção útil.** Quando a confiança é baixa, o melhor caminho é desambiguar, não errar a rota. A calibração e a acurácia seletiva são métricas de primeira classe.
|
||||
- **Telemetria.** Cada decisão gera um registro compatível com OpenTelemetry (`run_id`, `model_id`, `latency_ms`, versão do adaptador).
|
||||
131
docs/02-desenho-experimental.md
Normal file
131
docs/02-desenho-experimental.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 02 — Desenho experimental
|
||||
|
||||
## 1. Hipóteses
|
||||
|
||||
- **H1 (acurácia).** Pelo menos um candidato atinge, em PT-BR, uma acurácia de roteamento (D1/D2) compatível com o uso no orquestrador. O critério é a não inferioridade em relação ao baseline LLM (margem de 3 p.p.); ver [04, Q5](04-questoes-em-aberto.md#q5--critérios-de-sucesso-pré-registrados).
|
||||
- **H2 (calibração).** As probabilidades e a confiança devolvidas permitem uma política de abstenção (encaminhar para desambiguação) que melhora a acurácia seletiva sem derrubar demais a cobertura.
|
||||
- **H3 (desempenho).** O candidato cabe no orçamento de latência por turno (p95 com lote 1) com um custo por mil decisões menor que o de uma chamada a um LLM generalista.
|
||||
|
||||
## 2. Tarefas de decisão
|
||||
|
||||
Cada tarefa tem **pergunta**, **opções com descrição** e **regra de decisão** (tarefa 21). No primeiro ciclo, cada questão tem **no máximo 20 opções**, incluindo `sem_correspondencia` (tarefas 22–23).
|
||||
|
||||
### D1 — Classificação de intenção
|
||||
|
||||
- **Pergunta:** "Qual intenção do usuário este enunciado expressa?"
|
||||
- **Opções:** as intenções elegíveis do exemplo, de 2 a 19, mais `sem_correspondencia`. Cada opção tem uma descrição curta, do mesmo jeito que viria do catálogo de agentes ou intenções.
|
||||
- **Regra:** escolher a intenção principal que o próximo agente precisa atender. Se nenhuma se aplica, escolher `sem_correspondencia`.
|
||||
|
||||
### D2 — Continuidade de sessão
|
||||
|
||||
- **Pergunta:** "Como o orquestrador deve tratar este turno, considerando o estado da conversa?"
|
||||
- **Opções:** `continuar_agente_ativo`, `retomar_sessao:<agent_id>` (uma opção para cada sessão suspensa), `iniciar_novo_agente`, `desambiguar`.
|
||||
- **Regra:** `continuar_agente_ativo` quando o enunciado dá sequência à tarefa em curso, mesmo que seja curto ("sim", "o segundo", "pode ser"). `retomar_sessao` quando o usuário volta a um assunto anterior. `iniciar_novo_agente` quando aparece uma intenção nova. `desambiguar` quando não dá para decidir com segurança.
|
||||
|
||||
### D3 — Necessidade de desambiguação
|
||||
|
||||
- **Pergunta:** "O enunciado tem informação suficiente para rotear sem perguntar ao usuário?"
|
||||
- **Tipo:** `noul` (P(sim) = "dá para rotear sem perguntar").
|
||||
- **Uso:** comparar a abstenção explícita (D3) com a abstenção derivada da confiança de D1 (tarefa 60).
|
||||
|
||||
### D4 — Várias intenções
|
||||
|
||||
- Aplica-se só a enunciados anotados com mais de uma intenção.
|
||||
- Executa várias perguntas `noul` sobre o mesmo texto, uma por intenção candidata ("O enunciado pede X?"), na mesma requisição JEV (tarefa 65).
|
||||
- Métrica: F1 por conjunto de intenções e custo total, que soma as latências.
|
||||
|
||||
### D5 — Guardrail de entrada *(opcional)*
|
||||
|
||||
- Opções: `no_escopo`, `fora_do_escopo`, `requer_bloqueio`. Só entra se houver dados anotados suficientes.
|
||||
|
||||
## 3. Formato canônico de entrada (tarefa 36)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "conv-000123-t04-D2",
|
||||
"group_id": "conv-000123",
|
||||
"task": "D2",
|
||||
"state": {
|
||||
"active_agent": "agente_a",
|
||||
"suspended_sessions": ["agente_b"],
|
||||
"recent_turns": [
|
||||
{"role": "user", "text": "..."},
|
||||
{"role": "agent", "agent_id": "agente_a", "text": "..."}
|
||||
],
|
||||
"eligible_intents": ["intencao_1", "intencao_2"]
|
||||
},
|
||||
"utterance": "...",
|
||||
"question": "Como o orquestrador deve tratar este turno?",
|
||||
"question_type": "choice",
|
||||
"options": {
|
||||
"continuar_agente_ativo": "...",
|
||||
"retomar_sessao:agente_b": "...",
|
||||
"iniciar_novo_agente": "...",
|
||||
"desambiguar": "..."
|
||||
},
|
||||
"gold_label": "retomar_sessao:agente_b",
|
||||
"metadata": {
|
||||
"taxonomy_version": "v0.1",
|
||||
"domain": "...",
|
||||
"length_bucket": "curto",
|
||||
"ambiguity": "media",
|
||||
"turn_index": 4,
|
||||
"adversarial": ["abreviacao"],
|
||||
"n_options": 4,
|
||||
"n_tokens": {"laya": 0, "semif": 0, "gliner": 0, "rizzo_flow": 0}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Conversão para JEV.** `question` vira `questions.<task>.instructions` e `options` vira `criteria` (contrato `jev-compat-v1`, em [contracts/jev/schemas/](../contracts/jev/schemas/)). O `state` enviado é sempre o **texto serializado** descrito abaixo, nunca o objeto estruturado.
|
||||
|
||||
**Serialização do estado.** Alguns candidatos aceitam só texto, e não `state` estruturado. Por isso, uma **única regra de serialização** de `state` + `utterance` em texto vale para todos os adaptadores (um bloco "Contexto:" com o agente ativo, as sessões suspensas e os N últimos turnos, seguido de "Mensagem:"; N calculado como em [04, Q8](04-questoes-em-aberto.md#q8--turnos-no-state-e-orçamento-de-tokens)). A regra é versionada junto com a política de truncamento (tarefa 53). Um adaptador não pode usar informação de `state` que não esteja nessa serialização.
|
||||
|
||||
## 4. Dados
|
||||
|
||||
- **Unidade de amostragem:** conversa (`group_id`). Cada turno anotado gera um ou mais exemplos (um por tarefa de decisão).
|
||||
- **Fontes:** enunciados representativos do domínio de destino, anonimizados (tarefas 24–25). Se houver dados sintéticos, eles ficam identificados em `metadata` e são reportados em separado.
|
||||
- **Estratificação (tarefa 26):** domínio, comprimento, ambiguidade, classe esperada, posição do turno e presença de agente ativo ou de sessões suspensas.
|
||||
- **Adversariais (tarefa 27):** abreviações, erros de ortografia, regionalismos, enunciados muito curtos e dependentes de contexto ("sim", "o outro"), várias intenções, troca de assunto no meio da conversa, retorno a um assunto anterior e pedidos fora de escopo.
|
||||
- **Anotação (tarefas 29–32):** dois anotadores independentes e um terceiro para adjudicação. Para cada exemplo se registram o rótulo, a justificativa e a versão da taxonomia. A concordância (kappa de Cohen ou alfa de Krippendorff) vai para o relatório.
|
||||
- **Partições (tarefas 33–35):** desenvolvimento, calibração e teste final, separadas por `group_id`. O teste final é congelado (hash registrado) antes de qualquer ajuste.
|
||||
|
||||
## 5. Protocolo de execução
|
||||
|
||||
| Etapa | Partição | O que pode mudar | Tarefas |
|
||||
|-------|----------|------------------|---------|
|
||||
| Conformidade e sanidade | fixtures | adaptadores | 41, 49–51 |
|
||||
| Piloto CPU/GPU (50 ex.) | dev | só parâmetros operacionais | 55–58 |
|
||||
| Desenvolvimento | dev | nada além do operacional; sem calibração | 59 |
|
||||
| Calibração | calibração | limiares de confiança, regra de abstenção, calibradores por candidato | 60–61 |
|
||||
| **Congelamento** | — | **nada** daqui em diante | 62 |
|
||||
| Teste final | teste | — | 63–66 |
|
||||
|
||||
- Seeds, ordem dos exemplos, lote, precisão numérica (fp32, bf16 ou fp16 por candidato, registrada) e limite de tokens fixos por execução (tarefa 52).
|
||||
- As medições de desempenho são feitas depois do aquecimento, com no mínimo três execuções independentes (tarefa 66).
|
||||
- Cenários de execução: CPU com lote 1, GPU com lote 1 e GPU com lote de produção (escolhido automaticamente, ver Q6). O lote 1 representa o caminho síncrono do orquestrador; o lote maior mede a vazão.
|
||||
|
||||
## 6. Métricas
|
||||
|
||||
**Qualidade (tarefas 67–68)**
|
||||
- Accuracy, macro F1, precision e recall por classe, matriz de confusão.
|
||||
- Taxa de **rota errada com confiança alta** (erro que não seria desambiguado): é a métrica de maior impacto operacional.
|
||||
- Brier score, ECE, curva cobertura × acurácia seletiva e AURC, calculados sobre `max(probabilities)` calibrado. A `confidence` nativa do JEV não é calibrada e só é registrada.
|
||||
- D4: F1 por conjunto de intenções.
|
||||
|
||||
**Desempenho (tarefas 69–70)**
|
||||
- Latência p50, p95 e p99 por decisão e por turno (soma das decisões do turno).
|
||||
- Vazão, uso de GPU, RAM, VRAM, tempo de carga, tempo de aquecimento e armazenamento dos artefatos.
|
||||
- Custo estimado por mil decisões em cada cenário, a partir do preço do *shape* OCI e da vazão medida.
|
||||
|
||||
**Cortes (tarefa 71):** tarefa de decisão, número de opções, comprimento, ambiguidade, posição do turno, com ou sem agente ativo e categoria adversarial.
|
||||
|
||||
**Análise de erros (tarefas 72–73):** taxonomia, contexto insuficiente, ambiguidade, linguagem, truncamento, instrução ou desempenho do modelo.
|
||||
|
||||
## 7. Ameaças à validade
|
||||
|
||||
- **Vantagem de formato.** Cada modelo pode ter sido treinado com um estilo de prompt diferente. Por isso há um contrato único e uma serialização única, e os desvios ficam documentados por adaptador.
|
||||
- **Vazamento entre partições.** É controlado pela partição por `group_id` e pelo congelamento com hash.
|
||||
- **Truncamento desigual.** Todos usam a mesma política, baseada no menor contexto efetivo, e a contagem de tokens de cada entrada é registrada.
|
||||
- **Representatividade.** Dados sintéticos e reais são reportados em separado.
|
||||
- **Elegibilidade simulada.** Em produção, o conjunto de opções vem de um serviço. Aqui ele é fixado por exemplo.
|
||||
175
docs/03-plano-de-tarefas.md
Normal file
175
docs/03-plano-de-tarefas.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# 03 — Plano de tarefas
|
||||
|
||||
As 78 microtarefas mantêm a numeração original. As linhas **↳** registram a adaptação de cada tarefa ao contexto de roteamento e orquestração ou uma dependência importante. As referências *Qn* apontam para as decisões de projeto em [04-questoes-em-aberto.md](04-questoes-em-aberto.md).
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
F0[F0 Infra OCI] --> F1[F1 Ambiente e artefatos]
|
||||
F2[F2 Tarefas de decisão] --> F3[F3 Dados e anotação]
|
||||
F2 --> F4[F4 Contrato e adaptadores]
|
||||
F1 --> F4
|
||||
F3 --> F5[F5 Controle de execução]
|
||||
F4 --> F5
|
||||
F5 --> F6[F6 Piloto]
|
||||
F6 --> F7[F7 Dev e calibração]
|
||||
F7 --> F8[F8 Teste final]
|
||||
F8 --> F9[F9 Métricas e análise]
|
||||
F9 --> F10[F10 Relatório e encerramento]
|
||||
```
|
||||
|
||||
As fases F0–F1 (infra) e F2–F3 (dados) podem andar em paralelo.
|
||||
|
||||
---
|
||||
|
||||
## F0 — Infraestrutura OCI
|
||||
|
||||
- [x] **1.** Criar um compartment OCI dedicado ao benchmark.
|
||||
- ↳ `root/<compartimento-pai>/decision-models`. Recursos em `us-chicago-1`. OCIDs em `.secrets/artefatos-OCI.md` (fora do Git).
|
||||
- [ ] **2.** Aplicar as tags `projeto=benchmark-decisoes-ptbr`, `ambiente=benchmark` e `centro_custo=<definir>` aos recursos do projeto. *(Q13)*
|
||||
- ↳ Parcial: `projeto` e `ambiente` aplicadas como tags livres por `infra/oci/provision.py`. Falta `centro_custo`.
|
||||
- [ ] **3.** Criar um orçamento para o compartment.
|
||||
- ↳ **Em aberto por decisão (2026-10-07):** o uso está coberto por cota interna de engenharia. Não será criado no primeiro ciclo.
|
||||
- [ ] **4.** Configurar alertas de orçamento em 50%, 80% e 100% do valor aprovado.
|
||||
- ↳ Em aberto, porque depende da tarefa 3.
|
||||
- [x] **5.** Criar um projeto no OCI Data Science.
|
||||
- ↳ `benchmark-decisoes-ptbr`.
|
||||
- [ ] **6.** Criar buckets no Object Storage para `entrada`, `artefatos`, `resultados` e `logs-imutaveis`.
|
||||
- ↳ Criados com o prefixo `dmb-` (nomes de bucket são únicos no namespace), privados e com versionamento.
|
||||
- ↳ Pendente: a regra de retenção (WORM) de `dmb-logs-imutaveis`, que depende do prazo de retenção (tarefa 77).
|
||||
- [x] **7.** Definir políticas IAM de menor privilégio para leitura dos dados, escrita dos resultados e execução dos jobs.
|
||||
- ↳ Sem acesso de administrador à tenancy, as políticas ficam no próprio compartment e não usam grupos nem dynamic groups.
|
||||
- ↳ `dmb-usuario-manager`: o usuário (filtrado por `request.user.id`) é *manager* das famílias data-science, object, virtual-network, logging, repos e generative-ai.
|
||||
- ↳ `dmb-jobs-menor-privilegio`: os jobs (`request.principal.type='datasciencejob'`) leem `dmb-entrada`/`dmb-artefatos`, escrevem em `dmb-resultados`/`dmb-logs-imutaveis`, usam logs e repos. Inclui a política de serviço do Data Science para a VCN.
|
||||
- [x] **8.** Definir uma VCN privada para os jobs, com acesso ao Object Storage por Service Gateway.
|
||||
- ↳ `dmb-vcn` 10.20.0.0/16, sub-rede privada `dmb-subnet-jobs`. A rota e a security list só permitem tráfego para serviços OCI pelo Service Gateway.
|
||||
- [ ] **9.** Criar uma rota temporária de saída por NAT Gateway, só para a aquisição inicial de dependências e pesos.
|
||||
- ↳ Remover a rota logo após a tarefa 16 e passar pelo gate de egresso antes de qualquer execução. *(Q3)*
|
||||
- ↳ Criar e ativar **só quando necessário**, com `infra/oci/nat.py on`. Para desligar: `nat.py off`, que fecha a rota e bloqueia o NAT. Na tarefa 78: `nat.py off --delete`.
|
||||
- [ ] **10.** Validar que os jobs acessam os buckets sem internet pública.
|
||||
- ↳ Adiado para quando o primeiro job existir (depois da tarefa 11).
|
||||
|
||||
## F1 — Ambiente e artefatos
|
||||
|
||||
- [ ] **11.** Criar uma imagem de contêiner base com Python, CUDA, PyTorch, Transformers, Hugging Face Hub e ferramentas de medição.
|
||||
- ↳ Incluir um exportador OpenTelemetry, para que a telemetria do harness tenha o mesmo formato da observabilidade do orquestrador.
|
||||
- [ ] **12.** Fixar num manifesto as versões do sistema, dos drivers CUDA, do Python, das bibliotecas e da imagem de contêiner.
|
||||
- [ ] **13.** Baixar os pesos, tokenizadores, revisões e licenças aprovados de cada candidato. *(Q4)*
|
||||
- ↳ A aquisição falha se a licença estiver fora da allowlist de `config/benchmark.yaml`. O contexto efetivo de cada candidato é medido e registrado.
|
||||
- ↳ Incluir as dependências específicas de cada candidato (pacote GLiNER, runtime SemIf, interface Rizzo Flow) e a revisão fixada de `Qwen/Qwen3.5-4B`.
|
||||
- [ ] **14.** Calcular o SHA-256 de cada artefato baixado.
|
||||
- [ ] **15.** Copiar os pesos e dependências aprovados para o bucket `artefatos`.
|
||||
- [ ] **16.** Registrar no manifesto a origem, a revisão, a licença, o hash, a data de aquisição e o tamanho de cada artefato.
|
||||
- [ ] **17.** Desabilitar a saída pública dos jobs de benchmark.
|
||||
- [ ] **18.** Carregar cada candidato só a partir dos artefatos locais.
|
||||
- ↳ Usar `HF_HUB_OFFLINE=1`, `TRANSFORMERS_OFFLINE=1` e um cache apontado para os artefatos verificados.
|
||||
- [ ] **19.** Fazer o job falhar se algum candidato tentar baixar arquivos durante a inferência.
|
||||
- ↳ Duas camadas: as variáveis de ambiente offline e o bloqueio de rede da VCN. Um teste negativo prova que a falha ocorre.
|
||||
|
||||
## F2 — Tarefas de decisão e taxonomia
|
||||
|
||||
- [ ] **20.** Definir a taxonomia de decisões a avaliar em PT-BR.
|
||||
- ↳ Taxonomia de **intenções** (D1), ligadas aos **agentes de destino** do catálogo A2A, mais as decisões de **continuidade de sessão** (D2), **desambiguação** (D3) e **várias intenções** (D4). D5 é opcional. Ver [02 §2](02-desenho-experimental.md#2-tarefas-de-decisão).
|
||||
- [ ] **21.** Escrever a pergunta, as opções, as descrições das opções e a regra de decisão de cada tarefa.
|
||||
- ↳ As descrições das opções seguem o estilo de um *agent card*: curtas e orientadas à capacidade do agente.
|
||||
- [ ] **22.** Limitar o primeiro ciclo a no máximo 20 opções por questão, para garantir compatibilidade com o Laya. *(Q2)*
|
||||
- ↳ Os subconjuntos de opções por exemplo simulam o serviço de elegibilidade de intenções.
|
||||
- [ ] **23.** Incluir uma opção explícita de `outro` ou `sem correspondência` quando a taxonomia não for exaustiva.
|
||||
|
||||
## F3 — Dados e anotação
|
||||
|
||||
- [ ] **24.** Coletar textos PT-BR representativos do domínio de destino. *(Q7)*
|
||||
- ↳ A unidade é a **conversa com vários turnos**, não o enunciado isolado. Cada turno guarda o estado (agente ativo e sessões suspensas).
|
||||
- [ ] **25.** Remover ou mascarar dados pessoais, segredos e identificadores que o benchmark não precisa.
|
||||
- [ ] **26.** Separar os textos por domínio, comprimento, grau de ambiguidade e classe esperada.
|
||||
- ↳ Acrescentar a posição do turno e a presença de agente ativo ou de sessões suspensas.
|
||||
- [ ] **27.** Criar exemplos adversariais com abreviações, erros de ortografia, regionalismos, textos curtos e várias intenções.
|
||||
- ↳ Acrescentar respostas curtas que dependem do contexto ("sim", "o segundo"), troca de assunto, retorno a um assunto anterior e pedidos fora de escopo.
|
||||
- [ ] **28.** Definir os critérios de inclusão e exclusão dos exemplos.
|
||||
- [ ] **29.** Produzir o guia de anotação humana.
|
||||
- ↳ O guia cobre D1–D4 com exemplos-limite (por exemplo, quando um enunciado curto continua a tarefa do agente ativo e quando inicia um novo agente).
|
||||
- [ ] **30.** Anotar cada exemplo com dois avaliadores independentes.
|
||||
- [ ] **31.** Resolver as discordâncias com a revisão de um terceiro avaliador.
|
||||
- [ ] **32.** Registrar, para cada exemplo, a resposta de referência, a justificativa e a versão da taxonomia.
|
||||
- ↳ Reportar também a concordância entre anotadores.
|
||||
- [ ] **33.** Separar os dados em desenvolvimento, calibração e teste final por grupo de origem. *(Q12)*
|
||||
- ↳ O grupo é `group_id`, ou seja, a conversa.
|
||||
- [ ] **34.** Impedir que textos derivados do mesmo caso apareçam em mais de uma partição.
|
||||
- [ ] **35.** Congelar o conjunto de teste final antes de qualquer ajuste de parâmetros.
|
||||
- ↳ Registrar o hash do arquivo congelado e guardar uma cópia em `logs-imutaveis`.
|
||||
|
||||
## F4 — Contrato JEV e adaptadores
|
||||
|
||||
- [ ] **36.** Criar um formato canônico de entrada com `id`, `state`, `question`, `options`, `gold_label` e metadados.
|
||||
- ↳ Ver [02 §3](02-desenho-experimental.md#3-formato-canônico-de-entrada-tarefa-36), que inclui a **regra única de serialização** de `state`.
|
||||
- [ ] **37.** Definir a versão do contrato JEV compatível a usar no benchmark: `POST /v1/systemone`, esquema de requisição, esquema de resposta e códigos de erro. *(Q1)*
|
||||
- ↳ Versão `jev-compat-v1`. Os esquemas já estão em `contracts/jev/schemas/`; falta revisar os códigos de erro no código dos adaptadores.
|
||||
- [ ] **38.** Definir o mapeamento obrigatório entre o contrato JEV e os tipos internos `choice`, `noul` e `score`.
|
||||
- [ ] **39.** Definir a regra de conversão de probabilidades, confiança, níveis ordinais, opções descritas e campos de uso.
|
||||
- [ ] **40.** Definir o comportamento padronizado para entradas inválidas, limite de contexto, timeout, opção desconhecida e indisponibilidade do modelo.
|
||||
- ↳ Na prática, uma falha do modelo de decisão vira desambiguação ou fallback no orquestrador. No benchmark, essas falhas contam como erro e são reportadas à parte.
|
||||
- [ ] **41.** Criar testes de conformidade com requisições e respostas JEV congeladas.
|
||||
- [ ] **42.** Criar um adaptador JEV local para o Laya com o checkpoint multilíngue fixado.
|
||||
- [ ] **43.** Criar um adaptador JEV local para o SemIf em modo `direct`, com a revisão do Qwen fixada.
|
||||
- [ ] **44.** Criar um adaptador JEV local para o GLiNER Decide usando `classify_text`.
|
||||
- [ ] **45.** Criar um adaptador JEV local para o Rizzo Flow usando sua interface de decisões. *(Q4)*
|
||||
- [ ] **46.** Expor cada adaptador no mesmo caminho local `POST /v1/systemone`, sem dependência de rede externa.
|
||||
- [ ] **47.** Garantir que cada adaptador devolva a resposta JEV completa, incluindo escolha, distribuição de probabilidades, confiança e metadados de uso, quando disponíveis.
|
||||
- [ ] **48.** Normalizar as saídas adicionais de execução num registro interno com `latency_ms`, `model_id`, `run_id` e versão do adaptador.
|
||||
- ↳ O registro é emitido como span OpenTelemetry e também gravado em arquivo de resultados.
|
||||
- [ ] **49.** Validar que os adaptadores preservam a mesma ordem e a mesma descrição das opções.
|
||||
- [ ] **50.** Validar que trocar de candidato não altera a requisição JEV nem o formato da resposta JEV.
|
||||
- [ ] **51.** Implementar testes de sanidade com decisões triviais, opções permutadas e os três tipos de pergunta.
|
||||
- ↳ Incluir um teste de invariância à permutação das opções em D1 e D2 (a mesma escolha com outra ordem).
|
||||
|
||||
## F5 — Controle de execução
|
||||
|
||||
- [ ] **52.** Fixar seeds, ordem dos exemplos, tamanho de lote, precisão numérica e limites de tokens de cada execução.
|
||||
- [ ] **53.** Definir uma política de truncamento comum para textos maiores que o menor contexto efetivamente suportado. *(Q8)*
|
||||
- ↳ Truncar primeiro os turnos mais antigos do `state`. O enunciado atual nunca é truncado.
|
||||
- [ ] **54.** Registrar o número de tokens de cada entrada antes de executar os modelos.
|
||||
|
||||
## F6 — Piloto
|
||||
|
||||
- [ ] **55.** Executar um piloto de 50 exemplos por candidato em CPU. *(Q11)*
|
||||
- [ ] **56.** Executar um piloto de 50 exemplos por candidato em GPU.
|
||||
- [ ] **57.** Medir memória de GPU, memória RAM, tempo de carga, tempo de aquecimento e falhas do piloto.
|
||||
- [ ] **58.** Ajustar apenas os parâmetros operacionais necessários para eliminar falhas de execução.
|
||||
|
||||
## F7 — Desenvolvimento e calibração
|
||||
|
||||
- [ ] **59.** Executar os candidatos no conjunto de desenvolvimento, sem calibração adicional.
|
||||
- [ ] **60.** Escolher os limites de confiança e as regras de abstenção só com a partição de calibração.
|
||||
- ↳ Abster-se significa encaminhar para desambiguação. A regra é escolhida por meta de cobertura ou de risco, definida antes. *(Q5)*
|
||||
- [ ] **61.** Calibrar as probabilidades separadamente por candidato, quando aplicável. *(Q10)*
|
||||
- [ ] **62.** Não alterar prompts, opções, pesos ou limiares depois da abertura do conjunto de teste final.
|
||||
- ↳ Marco de congelamento: registrar os hashes da configuração, dos calibradores e dos adaptadores.
|
||||
|
||||
## F8 — Teste final
|
||||
|
||||
- [ ] **63.** Executar uma rodada de acurácia no teste final com lote 1.
|
||||
- [ ] **64.** Executar uma rodada de acurácia no teste final com o lote de produção definido. *(Q6)*
|
||||
- [ ] **65.** Executar uma rodada de várias decisões sobre o mesmo texto, quando esse padrão existir no caso de uso.
|
||||
- ↳ Corresponde a D4 e a combinações por turno (por exemplo, D2 + D1). Medir a latência somada por turno.
|
||||
- [ ] **66.** Repetir cada medição de desempenho depois do aquecimento, em pelo menos três execuções independentes.
|
||||
|
||||
## F9 — Métricas e análise
|
||||
|
||||
- [ ] **67.** Coletar accuracy, macro F1, precision, recall e matriz de confusão.
|
||||
- ↳ Acrescentar a taxa de rota errada com confiança alta.
|
||||
- [ ] **68.** Coletar Brier score, ECE, cobertura e acurácia seletiva quando houver probabilidades ou abstenção.
|
||||
- [ ] **69.** Coletar latência p50, p95 e p99, vazão, uso de GPU, uso de RAM e consumo de armazenamento.
|
||||
- ↳ Reportar a latência por decisão e por turno.
|
||||
- [ ] **70.** Calcular o custo estimado por mil decisões em cada cenário de execução.
|
||||
- [ ] **71.** Criar cortes dos resultados por domínio, número de opções, comprimento e dificuldade do texto.
|
||||
- ↳ Acrescentar os cortes por tarefa de decisão, posição do turno, com ou sem agente ativo e categoria adversarial.
|
||||
- [ ] **72.** Inspecionar manualmente os erros de alto impacto e as discordâncias entre os modelos.
|
||||
- [ ] **73.** Classificar os erros em: taxonomia, contexto insuficiente, ambiguidade, linguagem, truncamento, instrução ou desempenho do modelo.
|
||||
- [ ] **74.** Gerar tabelas comparativas e gráficos a partir dos arquivos de resultados versionados. *(Q9)*
|
||||
- ↳ Incluir intervalos de confiança (bootstrap) e testes pareados entre candidatos.
|
||||
|
||||
## F10 — Relatório e encerramento
|
||||
|
||||
- [ ] **75.** Elaborar o relatório técnico com configuração, limitações, resultados e recomendação.
|
||||
- [ ] **76.** Anexar ao relatório os manifestos de artefatos, hashes, configurações, logs, testes de conformidade e comandos de reprodução.
|
||||
- [ ] **77.** Arquivar os conjuntos congelados e os resultados no Object Storage com retenção definida.
|
||||
- [ ] **78.** Desligar notebooks, jobs, endpoints temporários e o NAT Gateway que não sejam mais necessários.
|
||||
167
docs/04-questoes-em-aberto.md
Normal file
167
docs/04-questoes-em-aberto.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# 04 — Decisões de projeto (ex-questões em aberto)
|
||||
|
||||
Todas as questões foram resolvidas em 2026-10-07. O critério foi preferir a **abordagem automatizada e verificável**: regras determinísticas em código, gates que fazem o pipeline falhar, valores calculados a partir de medições e parâmetros pré-registrados em [config/benchmark.yaml](../config/benchmark.yaml). Ninguém precisa decidir nada caso a caso durante a execução. Os valores numéricos pré-registrados ficam congelados com hash no marco da tarefa 62.
|
||||
|
||||
## Resumo
|
||||
|
||||
| # | Questão | Decisão | Mecanismo automatizado |
|
||||
|---|---------|---------|------------------------|
|
||||
| Q1 | Contrato JEV | Esquema público do `POST /v1/systemone` (`state` + `questions` tipadas → `answers` + `usage`), congelado como `jev-compat-v1` | JSON Schema em `contracts/jev/schemas/` e testes de conformidade |
|
||||
| Q2 | 20 opções incluem o fallback? | Sim: no máximo 19 opções de domínio + `sem_correspondencia` | Validação de esquema (`maxProperties: 20`) e lint do dataset |
|
||||
| Q3 | NAT × isolamento | Desassociar a rota NAT logo após a tarefa 16 | Gate de egresso: o pipeline só segue se a sonda de saída **falhar** |
|
||||
| Q4 | Interfaces e licenças | Interfaces mapeadas por candidato (abaixo). Só licenças da allowlist | O script de aquisição lê a licença nos metadados do Hub e falha fora da allowlist |
|
||||
| Q5 | Critérios de sucesso | SLO de latência fixo + não inferioridade relativa ao baseline | Avaliação automática dos critérios em `config/benchmark.yaml` |
|
||||
| Q6 | Lote de produção | Escolhido por candidato: o maior lote com p95 dentro do SLO | Varredura de lotes no piloto |
|
||||
| Q7 | Fonte dos dados | Reais anonimizados + sintéticos, com origem marcada | Geração sintética por template e LLM, anonimização automática, deduplicação |
|
||||
| Q8 | Turnos no `state` | O maior N ∈ {0,1,2,4} que cabe no orçamento comum de tokens | Cálculo sobre a partição de desenvolvimento |
|
||||
| Q9 | Baseline LLM | Incluído, fora do ranking principal | Adaptador JEV sobre o LLM Gateway |
|
||||
| Q10 | Calibração | Temperature scaling por candidato × tarefa, só na partição de calibração | Ajuste por NLL e congelamento com hash |
|
||||
| Q11 | Piloto em CPU | Mantido, com timeout. Inviabilidade declarada automaticamente | Regra p95 > timeout → "inviável em CPU" |
|
||||
| Q12 | Tamanho do teste | ≥ 1.300 decisões D1 no teste final (análise de poder) | `analysis/sample_size.py`, com recálculo do MDE |
|
||||
| Q13 | Centro de custo e orçamento | **Orçamento em aberto**: o uso está coberto por cota interna de engenharia. A estimativa de custo continua no relatório | A estimativa é calculada por script (tarefa 70) |
|
||||
|
||||
---
|
||||
|
||||
## Q1 — Contrato JEV `jev-compat-v1`
|
||||
|
||||
Base: a forma pública do `POST /v1/systemone`, a mesma reproduzida pelas implementações abertas (OpenJev/SemIf).
|
||||
|
||||
**Requisição**
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "<model_id>",
|
||||
"state": "<texto> | <objeto JSON>",
|
||||
"questions": {
|
||||
"<nome>": {"type": "choice", "instructions": "...", "criteria": {"<opcao>": "<descrição>"}},
|
||||
"<nome>": {"type": "noul", "instructions": "...", "criteria": {"true": "...", "false": "..."}},
|
||||
"<nome>": {"type": "score", "instructions": "...", "criteria": ["<nível 0>", "<nível 1>", "..."]}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Resposta**
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "<model_id>",
|
||||
"answers": {
|
||||
"<nome>": {"type": "choice", "choice": "<opcao>", "confidence": 0.0, "probabilities": {"<opcao>": 0.0}},
|
||||
"<nome>": {"type": "noul", "noul": 0.0},
|
||||
"<nome>": {"type": "score", "score": 0.0, "confidence": 0.0,
|
||||
"probabilities": {"0": 0.0}, "legend": {"0": "<nível 0>"}}
|
||||
},
|
||||
"usage": {"input_tokens": 0, "output_tokens": 0}
|
||||
}
|
||||
```
|
||||
|
||||
**Erros:** `422` para requisição malformada, modelo desconhecido ou estado acima do contexto. `401` para autenticação, que não se aplica aos adaptadores locais. Comportamentos padronizados do benchmark (tarefa 40):
|
||||
|
||||
| Situação | Código | Contabilização |
|
||||
|----------|--------|----------------|
|
||||
| Requisição inválida | `422` | Erro do harness: falha o job |
|
||||
| Estado acima do contexto, depois do truncamento comum | `422` | Erro de decisão (`error_type=context`) |
|
||||
| Timeout (`timeout_ms` do cenário) | `504` | Erro de decisão (`error_type=timeout`) |
|
||||
| Opção devolvida fora de `criteria` | `502` | Erro de decisão (`error_type=unknown_option`) |
|
||||
| Modelo indisponível | `503` | Erro de execução: refaz até 3 vezes e depois falha o job |
|
||||
|
||||
**Mapeamento para os tipos internos (tarefas 38–39)**
|
||||
|
||||
- `choice` → D1, D2 e D5. A predição é `choice`; a distribuição é `probabilities`.
|
||||
- `noul` → D3 e as perguntas por intenção de D4. P(sim) = `noul`.
|
||||
- `score` → reservado. Não é usado no primeiro ciclo.
|
||||
- **`confidence` não é calibrada** em nenhuma implementação. Por isso, todas as métricas de calibração e abstenção usam `max(probabilities)` (ou `max(noul, 1−noul)`) **depois** da calibração da tarefa 61. A `confidence` nativa é só registrada.
|
||||
- Quando um candidato não expõe uma distribuição normalizada, o adaptador aplica softmax sobre os escores das opções e marca `metadata.probabilities_source = "normalized_scores"`.
|
||||
- `output_tokens` deve ser sempre 0, porque não há geração. Um valor diferente de 0 reprova o teste de conformidade.
|
||||
|
||||
## Q2 — Limite de opções
|
||||
|
||||
O limite de 20 opções inclui `sem_correspondencia`: no máximo 19 opções de domínio + 1. O dataset é validado por esquema. Um exemplo com mais de 20 opções reprova o lint e impede o congelamento (tarefa 35).
|
||||
|
||||
## Q3 — NAT e isolamento de rede
|
||||
|
||||
Sequência automatizada, em que cada passo falha o pipeline se não for cumprido:
|
||||
|
||||
1. **9 → 16:** a rota NAT existe só durante a aquisição.
|
||||
2. **Fim da tarefa 16:** `infra/oci/nat.py off` remove a rota e o egresso `0.0.0.0/0` e bloqueia o NAT. O NAT só é criado ou ativado com `nat.py on`, quando for necessário.
|
||||
3. **Gate de egresso (tarefas 17 e 19):** um job de sonda tenta resolver e abrir conexão com hosts públicos (Hugging Face Hub, PyPI). O gate passa só se **todas** as tentativas falharem e se o acesso ao Object Storage pelo Service Gateway funcionar.
|
||||
4. **Toda execução de benchmark** roda o gate antes da inferência e grava o resultado no manifesto da execução.
|
||||
5. **Tarefa 78:** o NAT Gateway é destruído, e o gate confirma que nenhum recurso do compartment tem rota de saída.
|
||||
|
||||
## Q4 — Interfaces e licenças dos candidatos
|
||||
|
||||
| Candidato | Licença | Interface usada pelo adaptador | Contexto declarado | Observação |
|
||||
|-----------|---------|--------------------------------|--------------------|------------|
|
||||
| Laya multilingual | Apache-2.0 | `laya.load(...).predict(state, questions)`, nativamente no formato JEV | 1.024 tokens (default), até 8.192 | Recomenda até ~20 opções. Vem descalibrado: a calibração da tarefa 61 é obrigatória |
|
||||
| SemIf + Qwen3.5-4B | MIT (SemIf); Qwen: verificar no Hub | Modo `direct`: um forward pass lê os logits das opções declaradas | ~8k tokens | Revisão do Qwen fixada no manifesto |
|
||||
| GLiNER2.5-multi-Decide | Apache-2.0 | `classify_text(text, {"<q>": {"labels": {opcao: descrição}}})` | Não declarado: medir | Não tem `noul`/`score` nativos. `noul` vira o rótulo binário `{true,false}`. As probabilidades são normalizadas a partir dos escores |
|
||||
| Rizzo Flow 4B | Apache-2.0 (base); dados de treino com componentes CC-BY-SA/CC-BY | Prompt `spark-decisions-v3`, com leitura dos logits das letras de resposta | 2.048 tokens | **O formato de prompt é obrigatório**: o adaptador monta `spark-decisions-v3` a partir da serialização comum. Documentação só em inglês: o risco de idioma vai para o relatório |
|
||||
|
||||
Regras automatizadas:
|
||||
- A **allowlist de licenças** (`Apache-2.0`, `MIT`) fica em `config/benchmark.yaml`. O script da tarefa 13 lê `cardData.license` de cada repositório no Hub. Licença ausente ou fora da lista falha a aquisição, até haver aprovação explícita registrada no manifesto.
|
||||
- O **contexto efetivo** de cada candidato é medido por código: o mínimo entre `tokenizer.model_max_length`, `config.max_position_embeddings` e o limite declarado no adaptador. O resultado vai para o manifesto. Esse valor alimenta Q8.
|
||||
|
||||
## Q5 — Critérios de sucesso pré-registrados
|
||||
|
||||
Avaliados automaticamente pelo `analysis/` a partir de `config/benchmark.yaml`:
|
||||
|
||||
- **Desempenho (H3):** em GPU com lote 1, p95 ≤ **150 ms por decisão** e ≤ **300 ms por turno**. Em CPU os valores são só reportados.
|
||||
- **Acurácia (H1):** em D1 e D2, **não inferioridade em relação ao baseline LLM** com margem de **3 p.p.**: o limite inferior do IC 95% (bootstrap pareado por conversa) da diferença precisa ser > −3 p.p. Sem baseline disponível, vale o critério absoluto: macro F1 ≥ 0,80.
|
||||
- **Risco (H2):** no limiar escolhido na calibração, a taxa de **rota errada com confiança alta** precisa ser ≤ **2%**, com cobertura ≥ **80%**.
|
||||
|
||||
O critério relativo ao baseline dispensa um limiar absoluto arbitrário de acurácia, que dependeria da dificuldade do dataset.
|
||||
|
||||
## Q6 — Lote de produção
|
||||
|
||||
O piloto em GPU (tarefa 56) varre os lotes {1, 2, 4, 8, 16, 32}. O lote de produção de cada candidato é **o maior lote com p95 por decisão ≤ SLO**. O valor escolhido entra no manifesto e é congelado na tarefa 62. Lote 1 continua sendo o cenário principal. O lote de produção serve para reportar vazão e custo.
|
||||
|
||||
## Q7 — Fonte e preparação dos dados
|
||||
|
||||
- **Reais:** enunciados de conversas anonimizadas, se houver. **Sintéticos:** gerados a partir da taxonomia e dos templates adversariais (tarefa 27), com um LLM via gateway que **não** seja nenhum dos candidatos nem o baseline.
|
||||
- **Anonimização automática (tarefa 25):** regras para CPF, CNPJ, telefone, e-mail, CEP, números de cartão e protocolo, além de NER de pessoas e lugares, substituindo os achados por marcadores tipados (`<CPF>`, `<NOME>`). Uma amostra aleatória de 5% passa por verificação humana. Qualquer vazamento encontrado obriga a reprocessar o lote inteiro.
|
||||
- **Deduplicação:** MinHash/LSH para quase-duplicatas, dentro de cada fonte e entre fontes. Antes da partição, duplicatas recebem o mesmo `group_id`.
|
||||
- O campo `metadata.source` ∈ {`real`, `synthetic`} existe em todos os exemplos. As métricas saem por fonte e no agregado.
|
||||
- A anotação humana (tarefas 30–31) se mantém para todos os exemplos, inclusive os sintéticos. O rótulo de geração serve só como sugestão e é escondido dos anotadores.
|
||||
|
||||
## Q8 — Turnos no `state` e orçamento de tokens
|
||||
|
||||
1. **Orçamento comum** = o menor contexto efetivo medido entre os candidatos (Q4) − a reserva para a pergunta e as opções do maior exemplo.
|
||||
2. **N** = o maior valor em {0, 1, 2, 4} em que ≥ 95% dos exemplos de desenvolvimento cabem no orçamento sem truncar o enunciado atual. A contagem usa o tokenizador **mais verboso** entre os candidatos.
|
||||
3. A regra de truncamento (tarefa 53) remove primeiro os turnos mais antigos e nunca o enunciado atual. Se o enunciado sozinho estoura o orçamento, ele é truncado no fim e o exemplo recebe `truncated=true`.
|
||||
4. Uma ablação com N ∈ {0, 1, 2, 4} roda **só no desenvolvimento** e serve só para o relatório. Ela não altera a configuração congelada.
|
||||
|
||||
## Q9 — Baseline LLM
|
||||
|
||||
- Um LLM generalista disponível via LLM Gateway ou serviço gerenciado na OCI, com a versão fixada no manifesto.
|
||||
- Adaptador JEV próprio com saída restrita às opções. Quando houver logprobs, as probabilidades vêm deles. Quando não houver, a distribuição é one-hot com `probabilities_source="none"`, e o baseline fica fora das métricas de calibração.
|
||||
- Tem a mesma serialização, o mesmo truncamento e os mesmos dados. Fica **fora do ranking principal** e serve de referência para H1 e para o custo.
|
||||
- Por usar rede, é a **única exceção** ao isolamento. Roda num job separado, com egresso só para o endpoint do gateway, sem acesso aos artefatos dos candidatos.
|
||||
|
||||
## Q10 — Calibração
|
||||
|
||||
- **Temperature scaling** por candidato × tarefa de decisão: um único parâmetro, ajustado por minimização de NLL na partição de calibração. Para `noul`, o mesmo método é aplicado ao logit de P(sim).
|
||||
- O calibrador só é aceito se reduzir o ECE na própria partição de calibração (validação cruzada em 5 dobras por `group_id`). Se não reduzir, fica a identidade (T = 1).
|
||||
- Em seguida, os limiares de abstenção (tarefa 60) são escolhidos sobre as probabilidades calibradas, pelo critério de Q5: maximizar a cobertura com taxa de rota errada com confiança alta ≤ 2%.
|
||||
- Os parâmetros T e os limiares são versionados e congelados com hash na tarefa 62.
|
||||
|
||||
## Q11 — Piloto em CPU
|
||||
|
||||
- Timeout de **10 s por decisão** em CPU.
|
||||
- Regra automática: candidato com p95 > timeout ou com taxa de timeout > 5% no piloto recebe o status `inviavel_cpu` no manifesto e é excluído das rodadas finais em CPU. Os resultados em CPU dos demais são reportados como viabilidade, não como ranking.
|
||||
|
||||
## Q12 — Tamanho do conjunto de teste final
|
||||
|
||||
Análise de poder para a comparação pareada (teste de McNemar) entre dois candidatos em D1:
|
||||
|
||||
- Diferença mínima detectável d = 3 p.p., α = 0,05 (bilateral), poder = 0,80, proporção de discordância esperada p_d = 0,15:
|
||||
n ≈ (z₀.₉₇₅·√p_d + z₀.₈·√(p_d − d²))² / d² ≈ **1.300 decisões**.
|
||||
- Correção de agrupamento: n_final = n × (1 + (m − 1)·ICC), em que m é o número médio de turnos por conversa e o ICC é estimado na partição de desenvolvimento. Antes de medir, usar ICC = 0,05.
|
||||
- `analysis/sample_size.py` (a implementar) recalcula n com os valores observados. Se o teste congelado ficar abaixo do n necessário, o relatório troca a afirmação de significância pelo **MDE efetivo** do conjunto disponível.
|
||||
- D2–D4 usam o que estiver disponível, com IC por bootstrap por conversa.
|
||||
|
||||
## Q13 — Centro de custo e orçamento
|
||||
|
||||
> **Revisão (2026-10-07):** o orçamento e os alertas (tarefas 3–4) ficam **em aberto**, porque o uso está coberto por cota interna de engenharia. A tag `centro_custo` não é aplicada por enquanto. O texto abaixo vale só se for necessário criar um orçamento depois.
|
||||
|
||||
- `centro_custo` é variável Terraform **obrigatória e sem default**. O `terraform plan` falha enquanto ela não for informada, o que impede criar recursos sem a tag.
|
||||
- O valor do orçamento é calculado pelo script de estimativa, que multiplica as horas previstas por *shape* (piloto, dev, calibração, teste e repetições) pelo preço público da OCI e aplica um fator de contingência de 1,3. O resultado vai para `infra/oci/` como `budget_amount`. Os alertas de 50%, 80% e 100% (tarefa 4) são derivados desse valor.
|
||||
Reference in New Issue
Block a user