# Motor de decisão

Decisões estruturadas por critérios, em um nível de velocidade e precisão a sua escolha.

URL base: `https://ai.inovacc.dev`

## Visão geral

O Motor de decisão responde a perguntas estruturadas sobre um conteúdo com vereditos estruturados. Você envia um **estado** (a coisa a julgar: um texto, um registro, um objeto JSON) e um conjunto de **perguntas**, cada uma de um tipo conhecido; você recebe de volta uma resposta por pergunta, com o rótulo ou a pontuação escolhidos, as probabilidades por trás deles e uma confiança. O endpoint é `POST /v1/run` em `https://ai.inovacc.dev`, chamado em uma rota de decisão da sua organização.

O problema que ele resolve é transformar um julgamento em dados sobre os quais um programa possa agir. Perguntar a um modelo de chat "isto está bom?" devolve prosa que você depois precisa interpretar e que não pode comparar de uma chamada para outra. O Motor de decisão devolve sempre o mesmo formato, então você pode armazená-lo, aplicar limiares e auditá-lo.

Use-o para classificação, pontuação, triagem e verificações contra critérios: este chamado precisa de uma pessoa, qual das cinco categorias se encaixa, quão bem esta resposta atinge o padrão. Quando precisar de prosa gerada, use o [Chat com IA](/pt-br/products/ai.chat/); quando o veredito precisar se apoiar nos seus próprios documentos, recupere antes os trechos com [Conhecimento e busca vetorial](/pt-br/products/knowledge/) e coloque-os no estado.

## Conceitos

**Rotas de decisão.** Como em todo o Inovacc AI, você chama uma rota, nunca um modelo. `GET /v1/models` lista as suas rotas; uma entrada cujo `endpoint` é `/v1/run` é uma rota de execução, e as que a Inovacc configurou como rotas de decisão respondem no formato abaixo.

**Perguntas e seus tipos.** `questions` é um objeto de 1 a 64 entradas, identificadas pelos seus próprios ids (letras, dígitos, `_`, `.` ou `-`, até 100 caracteres). Cada pergunta tem um `type`, normalmente `instructions`, e `criteria` cujo formato é fixado pelo tipo:

| Tipo | Pede | `criteria` |
|---|---|---|
| `noul` | sim ou não | um objeto `{"true": "...", "false": "..."}` |
| `choice` | um rótulo entre vários | um objeto `{"label": "description", ...}` |
| `score` | um nível em uma escala | um array de níveis, do mais baixo ao mais alto |

Os formatos são estritos: uma string de critérios como `"1-5"` ou `"yes|no"` é recusada.

**Respostas.** Cada resposta traz o que o seu tipo produziu: o `choice` ou o `score` com `probabilities`, uma `legend` e uma `confidence`. Uma resposta `noul` traz a sua probabilidade `p` em vez de uma confiança.

**Níveis.** Uma rota de decisão atende um de três níveis: `fast`, `standard` ou `precise`. Todos respondem em um único formato, e o `engine.tier` da resposta diz qual deles respondeu. **A confiança não é comparável entre níveis**: cada nível informa em sua própria escala, então defina um limiar por nível.

**Escalonamento.** Com `escalate`, as perguntas respondidas abaixo de um limiar de confiança são perguntadas de novo, isoladamente, no nível mais forte seguinte (`fast`, depois `standard`, depois `precise`), e a resposta mais forte substitui a mais fraca. Os padrões são `fast` 0.40, `standard` 0.80 e `precise` 0.55; você pode passar `min_confidence` (um número, ou um por nível) e `max_tier`. A confiança de uma resposta `noul` é a distância de `p` em relação a uma moeda ao ar, `|2p - 1|`.

## Como funciona

Toda chamada leva `Authorization: Bearer <key>` e um `X-Operation-Id`. Sua organização vem da chave. O corpo aceita apenas `model`, `input` e `escalate`. Em uma rota de decisão, `input` é `{"state", "questions", "images"?}`: `state` é qualquer valor JSON não nulo, `images` tem no máximo 16 entradas. Qualquer outro campo dentro de `input` é recusado com `invalid_decision_input`, e a resposta nunca o repete.

A resposta é:

`{"model": "<route id>", "result": {"answers": {...}, "usage": {"input_tokens", "output_tokens"}}, "state": "Completed", "engine": {"tier", "latency_ms"}}`

e seus cabeçalhos trazem `x-route-id`, `x-usage-input-tokens` e `x-usage-output-tokens`.

Com escalonamento, cada resposta também diz qual `tier` a respondeu e, quando foi escalonada, `escalated_from` lista os níveis mais baixos e a confiança que cada um deu. Um objeto `escalation` informa cada tentativa, quantas perguntas foram feitas e quantas voltaram abaixo do limiar, e quantas respostas cada nível deu ao final. Cada tentativa é uma chamada própria, reservada contra as suas cotas e medida no seu próprio nível. Se uma tentativa falha, o escalonamento para, as respostas anteriores são mantidas e a requisição continua sendo `200`.

Não há transmissão nem tempo limite de 60 segundos neste endpoint. Uma resposta bem-sucedida é armazenada por 24 horas sob o seu id de operação: o mesmo id devolve a mesma resposta mesclada com `x-idempotent-replay: true` e não chama nada. O que é medido são tokens, ao preço de cada nível que respondeu.

## Primeiros passos

Você precisa de uma chave de API e de uma rota de decisão habilitada para a sua organização ([Autenticação](/pt-br/guides/authentication/)).

1. **Encontre a sua rota de decisão** com `GET /v1/models`: uma entrada cujo `endpoint` é `/v1/run`.
2. **Faça uma pergunta `noul`.** `POST /v1/run` com a sua rota como `model`, um texto curto como `state` e uma pergunta `{"type":"noul","instructions":"...","criteria":{"true":"...","false":"..."}}` (veja [os exemplos](#example)). A resposta traz o id da sua pergunta em `result.answers`, com a probabilidade `p`.
3. **Adicione uma pergunta `score`** com três níveis à mesma chamada. As duas respostas voltam em uma só resposta; `engine.tier` nomeia o nível.
4. **Escalone.** Envie a chamada de novo com um novo id de operação e `"escalate": true`. A resposta agora traz `tier` por resposta e um objeto `escalation` listando as tentativas.

## Casos de uso

**Triagem de chamados.** Cada chamado de suporte recebido é o `state`; uma pergunta `choice` escolhe a equipe, uma pergunta `noul` pergunta se uma pessoa precisa responder, uma pergunta `score` avalia a urgência. As respostas são armazenadas junto com o chamado, e um chamado cuja confiança está abaixo do seu limiar vai para uma pessoa.

**Verificações de qualidade em texto gerado.** Antes de o rascunho de um assistente ser enviado, uma chamada de decisão o pontua contra o seu padrão ("Abaixo do padrão", "No padrão", "Acima do padrão") e verifica algumas regras `noul`. Com `escalate`, apenas os rascunhos sobre os quais o nível rápido ficou em dúvida pagam pelo nível preciso.

**Moderação de conteúdo com imagens.** O texto de um anúncio e até 16 imagens são julgados contra as suas perguntas de política; a confiança por pergunta decide entre publicar, rejeitar e enviar para revisão.

## Limites e preços

| Limite | Valor |
|---|---|
| Perguntas por chamada | 1 a 64 |
| Id da pergunta | 1 a 100 caracteres: letras, dígitos, `_`, `.`, `-` |
| Imagens por chamada | 16 |
| Corpo da requisição | 1 MiB por padrão; sua organização pode ser configurada entre 1 KiB e 20 MiB |
| Tokens de entrada por requisição | o limite da sua organização |
| Resposta armazenada para repetição | 24 horas |
| Requisições, tokens, custo, simultaneidade, orçamentos diários | conforme definido para a sua organização |

**Preços:** sob consulta. A unidade de preço é **tokens**, ao preço do nível que respondeu.

## Erros

| Status | Código | O que significa e o que fazer |
|---|---|---|
| 400 | `invalid_input` | `input` está ausente ou não é um objeto JSON. |
| 400 | `invalid_decision_input` | `input` não é `{state, questions, images?}` ou uma pergunta está malformada; confira tipos e ids. |
| 400 | `invalid_escalate` | `escalate` tem uma chave ou valor que não aceita, ou a rota não é uma rota de decisão. |
| 400 | `unsupported_field` | Um campo de nível superior diferente de `model`, `input`, `escalate`. |
| 400 | `model_not_allowed`, `input_too_large` | Use um id de rota válido; encurte o estado. |
| 400 | `missing_operation_id`, `invalid_operation_id` | Envie um `X-Operation-Id` válido. |
| 401 | `missing_credentials`, `invalid_credentials` | Envie uma chave válida. |
| 403 | `route_forbidden` | A rota não é sua, ou não é uma rota de execução. |
| 409 | `operation_in_progress` | Esse id de operação ainda está em execução. |
| 413 | `request_too_large` | O corpo excede o seu limite de tamanho. |
| 429 | `rate_limited`, `quota_exceeded`, `concurrency_limited`, `budget_exhausted` | Veja [Erros](/pt-br/guides/errors/); aguarde `Retry-After` quando informado. |
| 502 | `upstream_error` | O nível falhou, ou um formato de critérios foi recusado; confira os critérios e tente novamente. |
| 503 | `service_unavailable` | As decisões não podem ser alcançadas; tente novamente mais tarde. |

## Boas práticas

- **Escreva os critérios nos formatos estritos**: um objeto para `noul` e `choice`, um array para `score`.
- **Mantenha limiares por nível**, nunca um único número para todos os níveis.
- **Use `escalate` com `max_tier`** para limitar o custo: a maioria das perguntas para no nível mais barato.
- **Coloque no `state` tudo de que o julgamento precisa**, incluindo os trechos recuperados; o motor não vê mais nada.
- **Use ids de pergunta estáveis**, para que as respostas possam ser comparadas entre chamadas e armazenadas por id.
- **Derive o id de operação do item julgado** para que um lote repetido reaproveite a resposta em vez de pagar duas vezes.

## Relacionados

- [Chat com IA](/pt-br/products/ai.chat/), [Conhecimento e busca vetorial](/pt-br/products/knowledge/)
- [Autenticação](/pt-br/guides/authentication/), [Erros](/pt-br/guides/errors/), [Limites](/pt-br/guides/limits/)

## Endpoints

- POST /v1/run

## Exemplo

```sh
curl -X POST "https://ai.inovacc.dev/v1/run" -H "Authorization: Bearer $INOVACC_API_KEY" -H "X-Operation-Id: $(uuidgen)" -H "Content-Type: application/json" -d '{}'
```
