typestrict.aidocs

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.

EndpointO que faz
POST /v1/systemoneResponde perguntas sobre um texto, no formato de requisição e resposta do Jev.
GET /v1/modelsO modelo que está dentro, pelo nome.
GET /healthzok quando está pronto, para health checks.
VariávelPadrãoO que faz
PORT8080A porta em que escuta (o Cloud Run e o Lambda definem).
TYPESTRICT_TOKENnenhumQuando 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_IAM

No 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).

Nesta página