# Chat com IA

Respostas de chat dos modelos de linguagem da plataforma.

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

## Visão geral

O Chat com IA dá à sua aplicação respostas conversacionais dos modelos de linguagem que a Inovacc opera para a sua organização. O endpoint, `POST /v1/chat/completions`, fala o formato de comunicação chat-completions da OpenAI, então uma biblioteca cliente da OpenAI já existente pode chamá-lo trocando a URL base por `https://ai.inovacc.dev/v1` e adicionando dois cabeçalhos. Você envia uma lista de mensagens e recebe a resposta do assistente, seja como um único documento JSON, seja como uma transmissão de eventos enquanto ela é escrita.

O problema que ele resolve é o acesso sem encanamento: sua organização não precisa ter contas, chaves ou contratos com provedores de modelos. A Inovacc decide qual modelo atende cada uma das suas rotas, aplica os limites e orçamentos da sua organização antes de a chamada ser feita e registra o uso de cada chamada para que você veja quanto cada chave e cada rota gastam.

Use o Chat com IA quando a resposta for texto livre: um assistente, um resumo, um rascunho, uma extração para JSON, uma resposta que chama as suas ferramentas. Outro produto serve melhor quando:

- você precisa de um veredito estruturado a partir de critérios (uma pontuação, uma escolha, um sim ou não, com confiança): use o [Motor de decisão](/pt-br/products/decision/);
- a resposta precisa vir dos seus próprios documentos, com citações: consulte uma coleção na nuvem de [Conhecimento e busca vetorial](/pt-br/products/knowledge/);
- você precisa de vetores em vez de texto: use [Embeddings de IA](/pt-br/products/ai.embeddings/).

## Conceitos

**Rotas, não modelos.** Você nunca nomeia um modelo. Sua organização recebe **rotas**: ids opacos como `r00`, configurados pela Inovacc exclusivamente para a sua organização. Uma rota decide qual modelo responde, seu teto de saída e os campos que ela aceita. `GET /v1/models` lista as rotas que a sua organização pode usar, cada uma com o `endpoint` que atende; o `id` é sempre o id da rota, nunca o nome do que está por trás dela. Envie o id no campo `model`; envie `"auto"`, ou omita `model`, e a rota padrão da sua organização responde. Uma rota atende exatamente um endpoint: uma rota de chat chamada a partir de `/v1/embeddings` ou `/v1/run` é recusada como uma rota que você não tem permissão de usar.

**Campos.** Os campos comuns da OpenAI são sempre aceitos: `messages`, `model`, `stream`, `stream_options`, `max_tokens`, `max_completion_tokens`, `temperature`, `top_p`, `stop`, as penalidades, `logit_bias`, `logprobs`, `tools`, `tool_choice`, `response_format`, `seed`, `reasoning_effort` e mais alguns. Sete campos (`n`, `service_tier`, `store`, `metadata`, `modalities`, `audio`, `web_search_options`) são aceitos apenas quando a sua organização recebeu permissão para eles. Qualquer outro campo é recusado pelo nome. Algumas rotas aceitam um conjunto menor (`messages`, `model`, `stream`, `stream_options`, os dois limites de saída, `temperature`, `top_p`); nelas, `tools` e os demais campos são recusados para aquela rota.

**Mensagens e imagens.** `content` é uma string, ou um array de partes de texto e partes `image_url`. Uma imagem é uma URL `data:` (PNG, JPEG, WebP ou GIF, em base64) ou uma URL `https://`; uma rota cujo modelo não consegue buscar uma URL recusa a forma `https://`. Uma requisição carrega no máximo 20 imagens, e cada uma conta como 1.600 tokens de entrada estimados.

**Teto de saída.** `max_tokens` e `max_completion_tokens` só podem reduzir o teto definido pela rota e pela sua organização; um valor maior é limitado ao teto, nunca recusado. Os tokens de raciocínio que um modelo gasta estão dentro de `completion_tokens`.

**Transmissão.** Com `"stream": true`, a resposta é um `text/event-stream` de eventos `chat.completion.chunk` da OpenAI, cada um em uma linha `data:`, terminando com `data: [DONE]`. Defina `stream_options.include_usage` para receber um bloco final com a contagem de tokens.

**Cabeçalhos de uso.** Uma resposta sem transmissão traz `x-route-id`, `x-usage-input-tokens` e `x-usage-output-tokens`, e toda resposta traz `x-operation-id`.

## Como funciona

Toda chamada leva `Authorization: Bearer <key>` e um `X-Operation-Id`. Sua organização vem da chave. O id de operação é a sua chave de idempotência: de 8 a 128 letras, dígitos, `_` ou `-`. O serviço verifica, em ordem: o id de operação, a chave, se aquele id de operação já foi usado, o corpo e seus campos, a rota, as mensagens, o tamanho estimado da entrada (um quarto dos caracteres do corpo inteiro da requisição, mais a estimativa das imagens) e então reserva a chamada contra as cotas da sua organização. Só quando tudo isso passa é que um modelo é chamado.

O `id` da resposta é sempre `chatcmpl-` seguido do seu id de operação, e seu `model` é sempre o id da rota. Uma resposta cujo orçamento de saída inteiro foi gasto em raciocínio continua sendo `200`, com `content` vazio e `finish_reason: "length"`; uma resposta interrompida pelo filtro de segurança do modelo é `200` com `finish_reason: "content_filter"`.

Uma resposta sem transmissão bem-sucedida é armazenada por 24 horas sob o seu id de operação. Envie o mesmo id novamente e você recebe a resposta armazenada, com `x-idempotent-replay: true`, sem uma segunda chamada ao modelo, sem uma segunda cobrança e sem alteração de cota. Um erro nunca é armazenado, então repetir uma chamada que falhou com o mesmo id a executa de novo. Enquanto uma chamada ainda está em execução, uma segunda chamada com o mesmo id retorna `409 operation_in_progress`.

Uma transmissão nunca é armazenada. Se o modelo falhar no meio, a transmissão termina com um evento de erro (`upstream_error`) e `data: [DONE]`; uma transmissão que termina sem `[DONE]` foi cortada e está incompleta. Leia `delta.content` em todos os blocos, incluindo o primeiro e o que carrega `finish_reason`.

O que é medido são tokens: de entrada e de saída, conforme informado pelo modelo, ou a estimativa quando não há contagem disponível. `GET /v1/usage/summary` soma o uso da sua organização por chave, rota, dia ou hora, e `GET /v1/capabilities` informa a um agente o que a sua organização pode chamar; nenhum dos dois é cobrado.

## Primeiros passos

Você precisa de uma chave de API e de pelo menos uma rota de chat habilitada para a sua organização. As chaves são criadas no console da Inovacc; veja [Autenticação](/pt-br/guides/authentication/).

1. **Liste as suas rotas.** Chame `GET /v1/models`. Cada entrada com `"endpoint": "/v1/chat/completions"` é uma rota com a qual você pode conversar; anote o `id` dela.
2. **Envie uma primeira mensagem.** Chame `POST /v1/chat/completions` com esse id como `model`, uma mensagem `user` e um `X-Operation-Id` novo (veja [os exemplos](#example)). O `id` da resposta termina com o seu id de operação e `x-usage-input-tokens` mostra o que foi contado.
3. **Repita.** Envie a mesma requisição com o mesmo id de operação. A resposta é idêntica e traz `x-idempotent-replay: true`: nada foi executado duas vezes.
4. **Use a transmissão.** Adicione `"stream": true` e `"stream_options": {"include_usage": true}` com um novo id de operação. Os blocos chegam conforme a resposta é escrita, com o último antes de `[DONE]` carregando `usage`.
5. **Confira o gasto.** Chame `GET /v1/usage/summary?group_by=route` para ver as chamadas e os tokens que você acabou de usar.

## Casos de uso

**Um assistente de suporte.** O widget de ajuda transmite a resposta para que a pessoa a veja aparecer imediatamente. Cada turno do usuário é uma chamada com um novo id de operação; o seu servidor guarda a conversa e envia as mensagens recentes a cada vez. Se a conexão cair antes de `[DONE]`, o widget mostra a resposta como cortada e oferece perguntar de novo.

**Extração estruturada em lote.** Uma tarefa noturna lê os documentos recebidos e pede um objeto JSON com `response_format`. Cada documento recebe um id de operação derivado do seu próprio id, de modo que, quando a tarefa é reiniciada após uma falha, os documentos já concluídos voltam das respostas armazenadas em segundos e não são cobrados novamente.

**Um agente que chama as suas ferramentas.** Em uma rota que aceita `tools`, o modelo responde com `tool_calls`; o seu código executa a ferramenta e devolve o resultado como uma mensagem `tool`. Cada etapa tem o seu próprio id de operação, então uma etapa repetida nunca executa uma ferramenta duas vezes do lado do modelo.

## Limites e preços

| Limite | Valor |
|---|---|
| Corpo da requisição | 1 MiB por padrão; sua organização pode ser configurada entre 1 KiB e 20 MiB |
| Imagens por requisição | 20 |
| Custo de entrada estimado de uma imagem | 1.600 tokens |
| Tokens de entrada por requisição | o limite da sua organização (`400 input_too_large` acima dele) |
| Tokens de saída por requisição | o menor entre o teto da rota e o da sua organização |
| Tempo até a primeira resposta do modelo | 60 segundos |
| Resposta armazenada para repetição | 24 horas |
| Uma chamada mantida como em andamento | 5 minutos no máximo |
| Requisições por minuto e por dia; tokens e custo por dia e por mês; chamadas simultâneas; orçamentos diários | conforme definido para a sua organização |

**Preços:** sob consulta. A unidade de preço é **tokens**.

## Erros

| Status | Código | O que significa e o que fazer |
|---|---|---|
| 400 | `missing_operation_id`, `invalid_operation_id` | Envie `X-Operation-Id` com 8 a 128 letras, dígitos, `_` ou `-`. |
| 400 | `invalid_body` | O corpo não é um objeto JSON, ou `user` não é uma string. Corrija o corpo. |
| 400 | `invalid_messages` | `messages` está vazio ou uma mensagem está malformada. |
| 400 | `unsupported_field` | Um campo de nível superior que este endpoint não aceita; remova-o. |
| 400 | `unsupported_field_for_route` | A rota aceita um conjunto menor de campos, ou não consegue buscar uma URL de imagem; remova o campo ou envie a imagem como `data:`. |
| 400 | `model_not_allowed` | O valor de `model` não é um id de rota válido. Use um id de `GET /v1/models`. |
| 400 | `input_too_large` | A entrada excede o limite por requisição da sua organização, ou há mais de 20 imagens. Encurte-a. |
| 401 | `missing_credentials`, `invalid_credentials` | Envie uma chave válida. |
| 403 | `key_disabled`, `organization_disabled` | A chave ou a organização foi desativada; fale com o seu administrador. |
| 403 | `field_not_allowed` | Um campo que a sua organização não recebeu permissão para usar. |
| 403 | `route_forbidden` | A rota não é uma que a sua organização possa usar neste endpoint. |
| 409 | `operation_in_progress` | Esse id de operação ainda está em execução; aguarde e tente novamente. |
| 413 | `request_too_large` | O corpo excede o seu limite de tamanho. |
| 429 | `rate_limited` | Requisições demais; aguarde `Retry-After` segundos. |
| 429 | `quota_exceeded`, `concurrency_limited` | Uma cota de tokens, de custo ou de simultaneidade se esgotou; sem `Retry-After`. |
| 429 | `budget_exhausted` | Um orçamento diário foi consumido; ele é reiniciado às 00:00 UTC (`Retry-After`). |
| 502 | `upstream_error` | O modelo não respondeu de forma utilizável; tente novamente com o mesmo id de operação. |
| 503 | `service_unavailable`, `route_unavailable` | Tente novamente mais tarde; `route_unavailable` exige que a Inovacc corrija a sua rota. |
| 504 | `timeout_error` | O modelo não começou a responder em 60 segundos; tente novamente. |

O envelope e todos os tipos estão em [Erros](/pt-br/guides/errors/).

## Boas práticas

- **Um id de operação por requisição lógica**, reutilizado apenas para repetir essa mesma requisição. Um id reutilizado devolve a primeira resposta, qualquer que seja o novo corpo.
- **Repita em `502`, `503`, `504` e em erros de rede com o mesmo id de operação**, com espera crescente. Em `429 rate_limited` e `budget_exhausted`, aguarde os segundos de `Retry-After`.
- **Defina `max_tokens`** com o que você precisa: isso reduz a reserva feita contra as suas cotas e o custo de uma resposta descontrolada.
- **Observe `X-Budget-Warning`**: ele aparece quando a sua organização passa do limiar de alerta de um orçamento, antes de as chamadas serem recusadas.
- **Use `stream` para pessoas, não para tarefas**: uma resposta transmitida não pode ser repetida, uma sem transmissão pode.
- **Envie imagens como URLs `data:`** quando você não souber se o modelo da rota consegue buscar uma URL, e mantenha-as dentro do limite de 20 imagens.
- **Nunca envie uma chave secreta a um navegador**: chame o Chat com IA a partir do seu servidor.

## Relacionados

- [Autenticação](/pt-br/guides/authentication/), [Erros](/pt-br/guides/errors/), [Limites](/pt-br/guides/limits/)
- [Motor de decisão](/pt-br/products/decision/): vereditos estruturados na mesma chave
- [Conhecimento e busca vetorial](/pt-br/products/knowledge/): respostas a partir dos seus documentos, com citações
- [Embeddings de IA](/pt-br/products/ai.embeddings/)

## Endpoints

- POST /v1/chat/completions
- GET /v1/models
- POST /v1/run

## Exemplo

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