Guía
Guía de Jev con Python
El SDK oficial de Python de TypeSafe funciona con este sitio sin cambios: instala typesafe-sdk, apunta la base URL a jev-api.org y llama a system_one con una clave de jev-api.org. Esta guía cubre instalación, configuración, los tres tipos de pregunta, lectura de respuestas y el cliente async.
Actualizado
Instalación
El paquete es typesafe-sdk en PyPI y requiere Python 3.10 o superior. El código está en github.com/typesafe-ai/typesafe-sdk-python.
pip install typesafe-sdk
# or: uv add typesafe-sdk
# requires Python 3.10+Configura la clave y la base URL
El SDK lee dos variables de entorno. TYPESAFE_API_KEY toma una clave de tu panel de jev-api.org — las claves de la consola de TypeSafe no funcionan aquí — y TYPESAFE_BASE_URL debe ser https://jev-api.org para que las peticiones lleguen al endpoint compatible /v1/systemone en lugar de api.typesafe.ai.
# .env — a key from your jev-api.org dashboard
TYPESAFE_API_KEY=jeva_...
TYPESAFE_BASE_URL=https://jev-api.orgTambién puedes pasarlas inline: TypeSafeClient(api_key=..., base_url="https://jev-api.org"). El modelo por defecto es jev-latest; cámbialo con TYPESAFE_DEFAULT_MODEL o el argumento model. El timeout por defecto es 10 segundos.
Primera llamada: Noul, Choice y Score
client.system_one toma un state — cadena, objeto o array — y un mapa questions construido con las clases Noul, Choice y Score. La llamada de abajo vuelve dentro de la banda de latencia documentada de 70 a 500 ms y usa 1 crédito en este sitio.
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
with TypeSafeClient() as client: # reads TYPESAFE_API_KEY and TYPESAFE_BASE_URL
response = client.system_one(
state={"document": "I was charged twice. Please fix this ASAP."},
questions={
"billing": Noul(instructions="Is this ticket about billing?"),
"tone": Choice(
instructions="What is the customer's tone?",
criteria={"calm": None, "frustrated": None, "angry": None},
),
"urgency": Score(
instructions="How urgent is this ticket?",
criteria=["can wait", "this week", "today"],
),
},
)
print(response.nouls["billing"].noul) # 0.0 .. 1.0
print(response.choices["tone"].choice) # winning option
print(response.scores["urgency"].score) # fractional levelLeer las respuestas
La respuesta expone vistas tipadas: response.nouls, response.choices y response.scores, indexadas por tus ids de pregunta. Una respuesta Noul lleva .noul, la probabilidad de sí entre 0 y 1. Una Choice lleva .choice, .probabilities y .confidence. Una Score lleva un .score fraccionario más .legend, .probabilities y .confidence.
Usa confidence como señal de derivación. Cuando es baja o dos opciones quedan cerca, manda el caso a una persona o formula una pregunta de seguimiento más estrecha en lugar de bajar el umbral a ciegas. También puedes leer el objeto crudo por pregunta con response.answers["id"].
Cliente async
AsyncTypeSafeClient tiene la misma interfaz con llamadas awaitables — útil dentro de endpoints FastAPI o workers que despliegan varios states a la vez.
from typesafe_sdk import AsyncTypeSafeClient, Noul
async with AsyncTypeSafeClient() as client:
response = await client.system_one(
state="I was charged twice for my subscription.",
questions={"refund": Noul(instructions="Is the customer asking for money back?")},
)
print(response.answers["refund"])Sin el SDK: requests puro
Si no quieres la dependencia, haz tú mismo el POST con el JSON. El endpoint simple de este sitio, /api/v1/decisions, acepta la misma forma state+questions con el modelo jev-1.13 y límites algo más estrictos (de 1 a 6 preguntas, de 2 a 8 opciones de Choice).
import os
import requests
res = requests.post(
"https://jev-api.org/api/v1/decisions",
headers={"Authorization": f"Bearer {os.environ['JEV_API_KEY']}"},
json={
"model": "jev-1.13",
"state": "I was charged twice for my subscription.",
"questions": {
"refund": {"type": "noul", "instructions": "Is the customer asking for money back?"}
},
},
timeout=30,
)
print(res.json()["answers"]["refund"])Errores y timeouts
jev-api.org devuelve errores JSON con un campo detail. Los códigos que verás:
- 401 — clave ausente o rechazada. Revisa la cabecera Authorization: Bearer y que la clave sea de este sitio.
- 402 — la clave es válida pero el saldo no cubre la llamada. Añade créditos en la página de precios.
- 422 — el cuerpo falló la validación o el modelo lo rechazó (por ejemplo, por los límites de 64k/32k tokens). El mensaje nombra el campo.
- 429 — límite de velocidad. Espera y reintenta.
- 502 — el servicio de decisión no devolvió respuestas. No se usa crédito.
Preguntas frecuentes
¿Puedo usar mi clave de la consola de TypeSafe aquí?
No. Las claves no son intercambiables: las de TypeSafe funcionan en api.typesafe.ai y las del panel de jev-api.org funcionan aquí. Pon TYPESAFE_API_KEY a una clave de jev-api.org y TYPESAFE_BASE_URL a https://jev-api.org.
¿Qué endpoint llama el SDK en este sitio?
Con base_url en https://jev-api.org, el SDK envía a /v1/systemone — el endpoint compatible con TypeSafe, que acepta el conjunto completo de preguntas (hasta 256 preguntas, 255 opciones de Choice, instructions estructuradas) y cobra 1 crédito por llamada correcta.
¿El SDK reintenta automáticamente?
El SDK de TypeSafe trae una política de reintentos por defecto para errores transitorios como 429; puedes cambiarla con la opción retry del cliente. Los errores de validación (422) se corrigen en el cuerpo, no con reintentos.
¿Qué versión de Python necesito?
Python 3.10 o superior. El paquete typesafe-sdk incluye los clientes síncrono (TypeSafeClient) y asíncrono (AsyncTypeSafeClient).
¿Cómo sé qué versión del modelo respondió?
El campo model de la respuesta siempre informa el id versionado que sirvió la petición — hoy jev-1.13.0 — aunque hayas enviado un alias como jev-latest.
Envía la primera decisión
Crea una clave, define las dos variables de entorno y ejecuta el snippet de arriba.