Rode em qualquer lugar
O seu modelo como um container que responde como o Jev, no Docker, Cloud Run, AWS Lambda, Firebase e Kubernetes.
Em breve
O container está sendo construído; hoje um modelo é baixado como ONNX, pesos e pacote. Esta página é a especificação dele. O runtime de serving é open source (Apache-2.0).
Cada modelo também sai como uma imagem de container: o modelo, um runtime de CPU (ONNX Runtime) e um servidor HTTP, nada para configurar. Ele fala a mesma API de decisão do Jev, então trocar o Jev pelo seu próprio modelo é trocar uma URL base.
| Endpoint | O que faz |
|---|---|
POST /v1/systemone | Responde perguntas sobre um texto, no formato de requisição e resposta do Jev. |
GET /v1/models | O modelo que está dentro, pelo nome. |
GET /healthz | ok quando está pronto, para health checks. |
| Variável | Padrão | O que faz |
|---|---|---|
PORT | 8080 | A porta em que escuta (o Cloud Run e o Lambda definem). |
TYPESTRICT_TOKEN | nenhum | Quando definida, toda requisição precisa levar Authorization: Bearer <token>. Prefira a autenticação da sua própria plataforma (Cloud Run IAM, Lambda IAM) quando tiver. |
Sem GPU, sem acesso à internet e sem chamadas para nós: requisições e dados ficam na sua infraestrutura.
Docker
typestrict pull <model> --container # ou: docker load -i <model>.tar (link de download na página do modelo)
docker run -p 8080:8080 typestrict/<model>curl http://localhost:8080/v1/systemone -H "Content-Type: application/json" -d '{
"model": "ticket-router",
"state": "Fui cobrado duas vezes. Por favor, me ajudem.",
"questions": {
"team": {
"type": "choice",
"instructions": "Qual time atende o ticket?",
"criteria": { "billing": "Pagamentos e faturas", "support": "Todo o resto" }
}
}
}'
# uma resposta tem esta cara:
# { "model": "ticket-router", "answers": { "team": { "type": "choice", "choice": "billing", "confidence": 0.97,
# "probabilities": { "billing": 0.97, "support": 0.03 } } }, "usage": { "input_tokens": 41, "output_tokens": 0 } }Google Cloud Run
O Cloud Run roda imagens do Artifact Registry. Copie a imagem para lá e depois faça o deploy:
typestrict pull <model> --to us-docker.pkg.dev/<project>/<repo>/ticket-router
gcloud run deploy ticket-router \
--image us-docker.pkg.dev/<project>/<repo>/ticket-router \
--region us-central1 --cpu 1 --memory 1Gi \
--no-allow-unauthenticated--no-allow-unauthenticated mantém o serviço privado: quem chama precisa de um identity token de uma service account com o
papel roles/run.invoker. Defina --min-instances 1 se a primeira requisição depois de um período parado precisar ser rápida.
AWS Lambda
A imagem traz o AWS Lambda Web Adapter, então a mesma imagem roda no Lambda sem mudanças. O Lambda roda imagens do ECR na mesma conta e região:
typestrict pull <model> --to <account>.dkr.ecr.us-east-1.amazonaws.com/ticket-router
aws lambda create-function --function-name ticket-router \
--package-type Image \
--code ImageUri=<account>.dkr.ecr.us-east-1.amazonaws.com/ticket-router:latest \
--role arn:aws:iam::<account>:role/<lambda-role> \
--memory-size 2048 --timeout 30
aws lambda create-function-url-config --function-name ticket-router --auth-type AWS_IAMNo Lambda, a CPU cresce com a memória: 2 GB é um bom começo. A primeira requisição depois de um cold start carrega o modelo.
Firebase
As Firebase Functions não rodam imagens próprias, então o modelo roda no Cloud Run (acima) e o Firebase chega até ele:
-
Hosting: direcione um caminho direto para o serviço do Cloud Run com um rewrite no
firebase.json:{ "hosting": { "rewrites": [{ "source": "/api/decide", "run": { "serviceId": "ticket-router", "region": "us-central1" } }] } } -
Functions: chame o serviço do Cloud Run a partir da sua função com um identity token, como qualquer outra API HTTP.
Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata: { name: ticket-router }
spec:
replicas: 2
selector: { matchLabels: { app: ticket-router } }
template:
metadata: { labels: { app: ticket-router } }
spec:
containers:
- name: model
image: <your-registry>/ticket-router
ports: [{ containerPort: 8080 }]
resources: { requests: { cpu: "1", memory: 1Gi }, limits: { memory: 2Gi } }
readinessProbe: { httpGet: { path: /healthz, port: 8080 } }
livenessProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 30 }
---
apiVersion: v1
kind: Service
metadata: { name: ticket-router }
spec:
selector: { app: ticket-router }
ports: [{ port: 80, targetPort: 8080 }]O modelo não guarda estado, então escala horizontalmente com réplicas (ou um HorizontalPodAutoscaler por CPU).