Ejecútalo donde quieras
Tu modelo como un contenedor que responde como Jev, en Docker, Cloud Run, AWS Lambda, Firebase y Kubernetes.
Próximamente
El contenedor está en construcción; hoy un modelo se descarga como ONNX, pesos y paquete. Esta página es su especificación. El runtime de servicio es open source (Apache-2.0).
Cada modelo también se entrega como imagen de contenedor: el modelo, un runtime de CPU (ONNX Runtime) y un servidor HTTP, sin nada que configurar. Habla la misma API de decisión que Jev, así que pasar de Jev a tu propio modelo es cambiar una URL base.
| Endpoint | Qué hace |
|---|---|
POST /v1/systemone | Responde preguntas sobre un texto, en el formato de solicitud y respuesta de Jev. |
GET /v1/models | El modelo que contiene, por nombre. |
GET /healthz | ok cuando está listo, para health checks. |
| Variable | Por defecto | Qué hace |
|---|---|---|
PORT | 8080 | El puerto en el que escucha (Cloud Run y Lambda lo definen). |
TYPESTRICT_TOKEN | ninguno | Si está definida, cada solicitud debe llevar Authorization: Bearer <token>. Prefiere la autenticación propia de tu plataforma (Cloud Run IAM, Lambda IAM) cuando la tengas. |
Sin GPU, sin acceso a internet y sin llamadas a nosotros: las solicitudes y los datos se quedan en tu infraestructura.
Docker
typestrict pull <model> --container # o: docker load -i <model>.tar (enlace de descarga en la página del modelo)
docker run -p 8080:8080 typestrict/<model>curl http://localhost:8080/v1/systemone -H "Content-Type: application/json" -d '{
"model": "ticket-router",
"state": "Me cobraron dos veces. Por favor, ayúdenme.",
"questions": {
"team": {
"type": "choice",
"instructions": "¿Qué equipo atiende el ticket?",
"criteria": { "billing": "Pagos y facturas", "support": "Todo lo demás" }
}
}
}'
# una respuesta se ve así:
# { "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
Cloud Run ejecuta imágenes de Artifact Registry. Copia la imagen allí y luego despliega:
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 lo mantiene privado: quienes llaman necesitan un token de identidad de una cuenta de servicio
con el rol roles/run.invoker. Define --min-instances 1 si la primera solicitud después de un periodo sin tráfico debe
ser rápida.
AWS Lambda
La imagen incluye el AWS Lambda Web Adapter, así que la misma imagen corre en Lambda sin cambios. Lambda ejecuta imágenes de ECR en la misma cuenta y región:
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_IAMEn Lambda, la CPU crece con la memoria: 2 GB es un buen punto de partida. La primera solicitud después de un arranque en frío carga el modelo.
Firebase
Firebase Functions no ejecuta imágenes propias, así que el modelo corre en Cloud Run (arriba) y Firebase llega hasta él:
-
Hosting: dirige una ruta directo al servicio de Cloud Run con un rewrite en
firebase.json:{ "hosting": { "rewrites": [{ "source": "/api/decide", "run": { "serviceId": "ticket-router", "region": "us-central1" } }] } } -
Functions: llama al servicio de Cloud Run desde tu función con un token de identidad, como a cualquier otra 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 }]El modelo no guarda estado, así que escala horizontalmente con réplicas (o con un HorizontalPodAutoscaler por CPU).