Migrar do Jev · checklist de migração de API

Um checklist prático para migrar do Jev

Migre uma integração existente com o Jev da TypeSafe para a API compatível com Jev da Decision Models: revise a configuração, teste as requisições e mude o tráfego de forma deliberada.

O Jev é um produto da TypeSafe AI; a Decision Models não é afiliada à TypeSafe AI.

Obter chave de APIConheça o tier da UE

Antes de mudar o tráfego

  1. Faça o inventário da integração existente

    Salve a configuração atual e casos de teste representativos. Verifique os tipos de pergunta, as opções, as imagens, a análise das respostas e as novas tentativas. Mantenha disponível a configuração do provedor anterior para um rollback deliberado.

  2. Defina a URL base e o caminho

    Use https://api.decisionmodels.io como URL base e POST /v1/systemone para texto. Remova um sufixo /v1 já existente se o seu cliente acrescentar o caminho por conta própria. Confira o caminho que realmente é enviado.

  3. Crie uma chave de API separada

    Crie uma chave da Decision Models no painel e envie-a como Authorization: Bearer. Chaves, saldos e contas da TypeSafe não são transferidos. Guarde a chave em uma variável de ambiente.

  4. Substitua o ID do modelo

    Substitua o ID de modelo da TypeSafe por um ID disponível da Decision Models, como s1-fast. Consulte GET /v1/models em vez de manter um alias da TypeSafe.

  5. Escolha a região de processamento explicitamente

    Por exemplo, defina S1-Region: eu. Os valores são eu ou global, sujeitos às permissões da chave; sem o header, vale o padrão da chave. As requisições da UE permanecem na UE. O processamento Peer-to-Peer fora da UE exige o consentimento de processamento mundial na chave. Revise os termos de processamento e de contrato.

  6. Divida as perguntas para respeitar os limites do modelo

    O s1-pro aceita até 3 perguntas de texto por requisição; o s1-fast aceita 1 e o s1-vision, 1. Divida você mesmo as perguntas adicionais. O serviço não as divide nem as descarta silenciosamente; perguntas em excesso retornam 400 request_limit_exceeded. Confira também os limites de tokens e de opções abaixo.

  7. Revise os tipos de pergunta e as imagens

    Mantenha o state e o objeto questions indexado pelo nome da pergunta. Use os formatos de critérios abaixo. Para imagens, use o s1-vision por meio de POST /v1/multimodal, com exatamente uma imagem no array images. São aceitas data URLs PNG, JPEG e WebP ou URLs HTTPS públicas, limitadas a 4 MiB decodificados e 2,000,000 pixels. Os exemplos de texto abaixo não testam requisições com imagem.

  8. Leia as respostas e a contabilização de uso

    Leia os resultados em answers, pelo nome da pergunta. Registre usage.input_tokens, usage.output_tokens, usage.decisions e o model_version informado. A contagem de tokens vem do modelo, incluindo as posições de imagem nas requisições com imagem. Use os recibos de uso do painel para valores monetários; não converta caracteres em tokens cobráveis.

  9. Teste erros, novas tentativas e rollback

    Teste chaves inválidas, crédito insuficiente, limites do modelo, limites de taxa e timeouts. Use os códigos de erro abaixo. Avalie os resultados com os seus próprios casos e mude o tráfego depois das suas verificações de aceitação. Um teste de contrato local não estabelece qualidade do modelo nem disponibilidade em produção.

Tipos de pergunta e limites de entrada atuais

ModeloTokens de entrada por perguntaPerguntasOpções
s1-fast8,000116
s1-pro8,192364
s1-vision8,000126

Cada pergunta inclui o seu estado, os critérios e o modelo de prompt; o s1-vision também conta as posições de imagem. Confira os limites de entrada completos.

O que muda quando você migra

Verificado em 27 de outubro de 2026. A comparação datada de alternativas ao Jev e as notas de migração definem o limite da compatibilidade: chaves separadas, IDs de modelo, tiers de processamento, cobrança, limites, metadados e erros. Trocar de modelo exige a sua própria avaliação das saídas. Não afirmamos compatibilidade byte a byte.

Nossas rubricas de pontuação exigem pelo menos dois níveis; o esquema publicado pela TypeSafe também aceita um único nível. Perguntas em excesso geram um erro não passível de nova tentativa.

Com Idempotency-Key, uma requisição em andamento retorna 202 in_progress. Após a liquidação, ou enquanto ela está incerta, retorna 409 idempotency_replay_unavailable com um recibo e sem segunda cobrança, mas sem resposta armazenada. Uma falha confirmada, sem resposta e sem cobrança, permite repetir a mesma chave e o mesmo corpo. Um corpo diferente com a mesma chave retorna 409 idempotency_conflict. Use uma chave nova apenas para uma inferência deliberadamente nova.

Exemplos de texto testados

Cada arquivo abaixo foi executado sem alterações contra um mock HTTP local e isolado do nosso contrato publicado. As verificações cobriram método, caminho, autenticação Bearer, S1-Region, corpo JSON e a leitura de uma resposta simulada com usage e model_version. Nenhuma requisição de inferência em produção foi feita.

Defina DECISIONMODELS_API_KEY com a sua chave. O DECISIONMODELS_BASE_URL, opcional, pode apontar para o seu mock local; caso contrário, é usada a base pública da API. Os exemplos em Python exigem Python 3.10 e a versão do pacote indicada. O exemplo com fetch é TypeScript compatível com JavaScript, executado com Node.js 20.19.4.

O LiteLLM remove o prefixo de provedor typesafe/; o mock recebeu s1-fast. Foi testado apenas o cliente Python do Ollama, não a CLI. SDKs tipados podem descartar metadados extras, como o model_version; os exemplos com HTTP direto o preservam.

curl 7.81.0

testado em 27 out. 2026 contra o nosso contrato publicado, com curl 7.81.0

curl.sh
curl --fail-with-body --silent --show-error --max-time 15 \
  "${DECISIONMODELS_BASE_URL:-https://api.decisionmodels.io}/v1/systemone" \
  -H "Authorization: Bearer $DECISIONMODELS_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'S1-Region: eu' \
  --data '{"model":"s1-fast","state":"Mia owns a red bicycle.","questions":{"color":{"type":"choice","instructions":"Which color is the bicycle?","criteria":{"red":null,"blue":null}}}}'

Python requests 2.32.5

testado em 27 out. 2026 contra o nosso contrato publicado, com Python requests 2.32.5

requests.py
import os
import requests

base = os.environ.get("DECISIONMODELS_BASE_URL", "https://api.decisionmodels.io")
response = requests.post(
    base + "/v1/systemone",
    headers={
        "Authorization": "Bearer " + os.environ["DECISIONMODELS_API_KEY"],
        "S1-Region": "eu",
    },
    json={
        "model": "s1-fast",
        "state": "Mia owns a red bicycle.",
        "questions": {"color": {
            "type": "choice",
            "instructions": "Which color is the bicycle?",
            "criteria": {"red": None, "blue": None},
        }},
    },
    timeout=15,
)
response.raise_for_status()
print(response.json())

Node.js fetch 20.19.4

testado em 27 out. 2026 contra o nosso contrato publicado, com Node.js fetch 20.19.4

fetch.ts
// JavaScript-compatible TypeScript; native fetch in Node.js.
const base = process.env.DECISIONMODELS_BASE_URL ?? "https://api.decisionmodels.io";
const response = await fetch(`${base}/v1/systemone`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.DECISIONMODELS_API_KEY}`,
    "Content-Type": "application/json",
    "S1-Region": "eu",
  },
  body: JSON.stringify({
    model: "s1-fast",
    state: "Mia owns a red bicycle.",
    questions: { color: {
      type: "choice",
      instructions: "Which color is the bicycle?",
      criteria: { red: null, blue: null },
    } },
  }),
  signal: AbortSignal.timeout(15000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());

LiteLLM 1.106.4

testado em 27 out. 2026 contra o nosso contrato publicado, com LiteLLM 1.106.4

litellm.py
import os
import litellm

response = litellm.systemone(
    model="typesafe/s1-fast",
    api_base=os.environ.get("DECISIONMODELS_BASE_URL", "https://api.decisionmodels.io"),
    api_key=os.environ["DECISIONMODELS_API_KEY"],
    extra_headers={"S1-Region": "eu"},
    state="Mia owns a red bicycle.",
    questions={"color": {
        "type": "choice",
        "instructions": "Which color is the bicycle?",
        "criteria": {"red": None, "blue": None},
    }},
    timeout=15,
)
print(response.model_dump())

Ollama Python 0.6.3

testado em 27 out. 2026 contra o nosso contrato publicado, com Ollama Python 0.6.3

ollama.py
import os
from ollama import Client

client = Client(
    host=os.environ.get("DECISIONMODELS_BASE_URL", "https://api.decisionmodels.io"),
    headers={
        "Authorization": "Bearer " + os.environ["DECISIONMODELS_API_KEY"],
        "S1-Region": "eu",
    },
    timeout=15,
)
response = client.systemone(
    model="s1-fast",
    state="Mia owns a red bicycle.",
    questions={"color": {
        "type": "choice",
        "instructions": "Which color is the bicycle?",
        "criteria": {"red": None, "blue": None},
    }},
)
print(response.model_dump())

Documentação dos clientes: LiteLLM System One · Ollama Python 0.6.3. Os testes cobrem as versões indicadas e o exemplo de texto exibido.

Trate os erros antes de migrar

Trate estes códigos explicitamente; as regras completas estão em erros e novas tentativas.

Próximo passo

Revise as notas de migração completas e os seus próprios casos de teste antes de mover as requisições de produção.