¿Qué es Jev? El modelo de TypeSafe AI que decide en lugar de escribir

Jev es un modelo de IA que no escribe texto: devuelve una opción, un nivel o un sí/no con su probabilidad. Con muchos diagramas, algunos paso a paso, verás en qué se diferencia de ChatGPT, cuáles son sus tres tipos de pregunta y cómo usarlo desde Python.

Jev es un modelo de IA de la empresa TypeSafe AI.

A diferencia de ChatGPT, no escribe texto. Ante decisiones como «¿A qué equipo va este ticket?» o «¿Es urgente?», te devuelve una respuesta con la forma que definiste de antemano, acompañada de una probabilidad (un número entre 0 y 1: cuanto más cerca de 1, más probable es esa respuesta).

Video en inglés de Riley Brown, «JEV: How It Works and What You Can Build». Explica cómo funciona Jev y qué puedes construir con él.

Para usarlo, le envías dos cosas a través de una API (la interfaz con la que un programa llama a las funciones de un servicio externo): la entrada que quieres evaluar (el state; por ejemplo, el texto de un ticket) y tus preguntas.

Después, tu propio código decide qué hacer con la respuesta.

En esta página verás con diagramas en qué se diferencia Jev de ChatGPT, cuáles son sus tres tipos de pregunta, cómo llamarlo desde Python, cómo decidir qué hacer según la confidence, en qué casos no conviene usarlo y cómo funciona por dentro.

Qué le envías a Jev, qué te devuelve y quién decide al final
Choice¿Qué equipo?Score¿Qué tan enojado?Noul¿Es urgente?Evalúacon el stateEvalúacon el stateEvalúacon el statechoice+ probabilidadscore+ probabilidadnoul(prob. de sí)Tu códigolo derivaTu códigopriorizaTu código lopasa a una personaJev evalúa en paralelo
En una sola solicitud, Jev evalúa las tres preguntas sobre el mismo state y devuelve una respuesta para cada una.

Jev se encarga de todo salvo de la columna de la derecha: esa parte es tu propio código, escrito con sentencias if.

¿Qué es Jev? Un modelo System One que devuelve decisiones, no texto

Este tipo de modelo es lo que TypeSafe llama un modelo System One (un modelo de IA que devuelve rápidamente decisiones de un tipo fijo, listas para que el software las use tal cual).

Dónde encaja Jev entre los modelos de IA
Modelos de IA que leen lenguaje natural
Modelos que generan texto (LLM)
  • Chatbots como ChatGPT y modelos de razonamiento
  • Devuelven: texto, código, explicaciones del razonamiento
  • No sabes la forma de la respuesta hasta leerla
Modelos que devuelven decisiones (modelos System One)
  • Devuelven: opciones, niveles o sí/no definidos de antemano, con una probabilidad
  • No escriben texto, código ni explicaciones
Jev (TypeSafe AI)
  • Nombre del modelo en la API: jev-latest
  • Solo entrada de texto (sin imágenes, audio ni video)
Los dos tipos de modelo leen lenguaje natural; lo que los separa es si devuelven texto o una decisión. Jev, en el recuadro interior de abajo, es el primer modelo System One.

jev-latest es un alias (un nombre que apunta a una versión concreta) que siempre corresponde a la última versión: cuando sale una nueva, el alias pasa a apuntar a ella.

¿En qué se diferencia Jev de ChatGPT (los LLM)?

Compáralos con una misma tarea: repartir entre tres equipos los tickets de soporte que van llegando.

Un LLM (modelo de lenguaje de gran tamaño) como ChatGPT es un modelo de IA que genera texto palabra por palabra, así que, si le preguntas qué equipo debe atender un ticket, te contesta con texto.

Basta con que la redacción pase de «soporte técnico» a «el equipo técnico» para que una comparación como if answer == "technical" deje de coincidir.

Y aunque uses una función que restrinja la salida a JSON, tu código sigue teniendo que validar lo que viene dentro.

Como Jev recibe los candidatos de antemano, el choice que devuelve es siempre uno de ellos.

Cuando TypeSafe anuncia «0 % de alucinaciones» (que el modelo invente contenido falso pero verosímil), se refiere al formato: nunca recibirás una respuesta que no esté entre los candidatos.

Eso no garantiza que el candidato elegido sea el correcto.

Esta tabla los compara en cinco aspectos. La última fila trata del precio, que depende del número de tokens (las unidades en las que un modelo de IA divide el texto para procesarlo).

AspectoLLM como ChatGPTJev
Qué devuelveTexto generadoOpción o nivel fijo + probabilidad
Escribe texto o códigoSíNo
Su punto fuerteTexto, código, razonamientos largosClasificar, puntuar, sí/no
Al añadir preguntasTarda más: escribe cada respuestaCasi igual: van en paralelo
Qué se cobraTokens de entrada y de salidaSolo tokens de entrada

Choice, Score o Noul: ¿qué tipo de pregunta conviene usar?

Cuando le haces una pregunta a Jev, lo primero que decides no es cómo redactarla, sino la forma de la respuesta.

Hay tres tipos de pregunta: Choice (elegir un candidato entre varios que no siguen ningún orden), Score (situar algo en una escala de niveles ordenados) y Noul (responder sí o no).

Además de la respuesta, Choice y Score devuelven un valor de confidence: un número entre 0 y 1 que indica cuánto se concentra la probabilidad en un solo candidato o nivel. Cuanto más cerca de 1, más claramente se inclina el modelo por una sola respuesta.

Noul es el único tipo que no devuelve confidence.

Si dudas, parte de lo que hará tu código con la respuesta: Choice si vas a derivar, Score si vas a compararla con un umbral y Noul si te basta con una sola sentencia if.

En Choice, criteria (los criterios en los que se basa la decisión) es un dict que asocia el nombre de cada candidato con su descripción.

Aprovecha las descripciones para marcar dónde termina un candidato y empieza el siguiente; por ejemplo: «los problemas de pago van a billing, y los fallos de integración, a technical».

En Score, criteria es una lista con la descripción de cada nivel, ordenada de menor a mayor, y los niveles se numeran a partir de 0. El score que recibes es la suma de cada número de nivel multiplicado por su probabilidad.

Probabilidad de cada nivel de Score y el score resultante
00.200.400.600.8010Nivel 00.57Nivel 10.43Nivel 2
El score es 0 × 0.0 + 1 × 0.57 + 2 × 0.43 = 1.43: queda entre el nivel 1 y el 2, más cerca del 1.

Luego, en tu código, comparas el score con un umbral; por ejemplo: «atender primero todo lo que tenga 1.5 o más».

Un Noul de 0.5 no significa «intermedio»

El valor de Noul es la probabilidad de que la respuesta sea sí. Si la pregunta «¿Esta persona domina Python?» devuelve 0.5, no quiere decir que su nivel sea intermedio, sino que la probabilidad de que lo domine es del 50 %.

Para medir un grado o nivel, usa Score.

Cómo usar Jev: derivar tickets de soporte a equipos con el SDK de Python

Vamos a usar el ejemplo de la guía de inicio rápido oficial: derivar un ticket a uno de tres equipos.

Con el SDK (una biblioteca que reúne todo lo necesario para llamar a un servicio), no tienes que construir las solicitudes a mano ni escribir la lógica de reintentos.

El SDK requiere Python 3.10 o posterior, y TypeSafeClient() lee la clave de la variable de entorno TYPESAFE_API_KEY.

Para configurar variables de entorno, consulta Variables de entorno en Linux, y para el manejo de claves, Claves de API y webhooks.

Qué envías y qué recibes en una sola llamada
statetexto del ticketquestionscada una con nombremodelpor defecto:jev-latestJev leey decideanswersuna por preguntamodelversión usadausagetokens usados
Envías los tres elementos de la izquierda y recibes los tres de la derecha. El nombre que le das a cada pregunta es la clave con la que recuperas su respuesta de answers.

El código sigue la documentación oficial

El código y las respuestas que aparecen aquí están tomados de los ejemplos de la documentación oficial; no son resultados de ejecuciones propias. Por eso el texto del ticket y las instrucciones están en inglés: se copiaron tal cual de esos ejemplos.

Llamar a Jev con el SDK de Python

pip install typesafe-sdk
export TYPESAFE_API_KEY="tu-clave-de-api"   # shell de macOS / Linux
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

client = TypeSafeClient()  # lee TYPESAFE_API_KEY y usa jev-latest

# La entrada que se va a evaluar (state): un ticket de soporte entrante
# (la integración con Stripe lleva 3 días fallando, el cliente pierde ventas y necesita ayuda ya)
ticket = "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP."

response = client.system_one(
    state=ticket,
    questions={
        # Qué equipo: un dict que asocia cada candidato con su descripción
        "department": Choice(
            instructions="Which team should handle this",
            criteria={
                "billing": "Payment or subscription issues",
                "technical": "Bugs or integration problems",
                "sales": "Pricing or account questions",
            },
        ),
        # Cuánta frustración muestra: niveles de menor a mayor
        "frustration": Score(
            instructions="How frustrated the customer appears",
            criteria=[
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        ),
        # ¿Es urgente? Sí o no
        "is_urgent": Noul(
            instructions="The message conveys urgency or time-sensitivity",
        ),
    },
)

print(response.answers["department"].choice)  # technical
print(response.answers["frustration"].score)  # 1.0
print(response.answers["is_urgent"].noul)     # 1.0

questions es un dict que asocia cada nombre de pregunta con su pregunta, y cada respuesta se lee de response.answers con ese mismo nombre. Los valores de los comentarios son los de la respuesta que muestra la guía de inicio rápido oficial.

El equipo es technical, la frustración está en el nivel 1 («Frustrated but civil»: molesto, pero educado) y la urgencia es un sí prácticamente seguro.

¿Cuadra con el «for 3 days» y el «ASAP» del ticket?

Llamar a Jev directamente por HTTP

También puedes llamar a Jev por HTTP sin pasar por el SDK (si quieres repasar lo básico de las API, consulta ¿Qué es una API?).

Solo hay un endpoint (la URL que recibe las solicitudes), y la clave va en la cabecera Authorization.

curl -X POST https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "Hi, I have been trying to connect my Stripe account for 3 days ...",
    "model": "jev-latest",
    "questions": {
      "department": {
        "type": "choice",
        "instructions": "Which team should handle this",
        "criteria": {
          "billing": "Payment or subscription issues",
          "technical": "Bugs or integration problems",
          "sales": "Pricing or account questions"
        }
      }
    }
  }'

Si llamas por HTTP, model es obligatorio y el tipo de cada pregunta se indica en su campo type.

Cómo leer la respuesta

Este es un ejemplo del JSON que recibes. De las tres preguntas, solo se muestra la respuesta de department.

{
  "answers": {
    "department": {
      "type": "choice",
      "choice": "technical",
      "confidence": 0.78,
      "probabilities": {
        "technical": 0.85,
        "sales": 0.0,
        "billing": 0.15
      }
    }
  },
  "usage": {
    "input_tokens": 392,
    "output_tokens": 65
  }
}
Cómo se anida el JSON de la respuesta
Respuesta completa
answers: una respuesta por nombre de pregunta
department (respuesta de Choice)
  • choice: el candidato elegido → technical
  • probabilities: una por candidato (suman 1)
  • confidence: cuánto se concentran → 0.78
usage
  • input_tokens / output_tokens: tokens usados
El recuadro exterior es la respuesta completa. Lo que Jev contesta a cada pregunta está en el recuadro con el nombre de la pregunta, dentro de answers.

usage contiene los recuentos de tokens, que son la base del cobro.

Con el SDK, obtienes el candidato elegido de este JSON con response.answers["department"].choice.

Los cuatro números de la respuesta de department
00.200.400.600.8010.85technical0.15billing0sales0.78confidence
Son los valores de la respuesta de ejemplo de la guía de inicio rápido oficial. Las tres barras de la izquierda son las probabilidades de cada candidato y suman 1. La barra de confidence, a la derecha del todo, no es una probabilidad: resume cuánto se concentran esas probabilidades.

El candidato más probable, technical, tiene 0.85, pero confidence vale 0.78. La confidence es 0 cuando las probabilidades se reparten por igual y 1 cuando se concentran todas en un solo candidato.

Con tres candidatos, la demo oficial la aproxima como «(3 × probabilidad máxima − 1) ÷ 2», y, en efecto, (3 × 0.85 − 1) ÷ 2 ≈ 0.78.

Usa la confidence para decidir qué automatizar, qué confirmar y qué pasar a una persona

La documentación oficial recomienda dividir la confidence en tres rangos mediante umbrales (los valores a partir de los cuales el procesamiento toma otro camino): si es alta, actuar automáticamente; si es intermedia, pedir confirmación al usuario, y si es baja, pasar el caso a una persona.

Los umbrales adecuados dependen de la acción. El ejemplo oficial es un servicio de banca por voz, en el que los usuarios gestionan su cuenta hablando.

Con la misma confidence de 0.7, la consulta de saldo se atiende en el acto, leyendo la cifra en voz alta, mientras que la aprobación de una transferencia se confirma antes con el usuario. Cuanto más daño pueda causar una acción, más alto debes poner el umbral.

Toma 0.6 y 0.85 como punto de partida y ve ajustándolos a medida que revisas los resultados con tus propios datos.

action = response.answers["intent"]  # Choice: check_balance / approve_transfer / other

if action.confidence < 0.6:
    # Sea cual sea la acción, no se ejecuta si el modelo duda
    route_to_support_agent(account_id)

elif action.choice == "check_balance":
    # Un error solo obliga a pedir el saldo otra vez
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if action.confidence > 0.85:
        approve_transfer(account_id)  # se mueve dinero, así que el umbral es más alto
    else:
        ask_user_to_confirm("¿Quieres aprobar esta transferencia?")

else:
    # clasificado como other
    route_to_support_agent(account_id)

El primer if exige una confidence mínima, y los elif siguientes aplican un umbral para cada acción: son dos capas de comprobación.

Como if y elif evalúan las condiciones en orden, de arriba abajo, se ve de un vistazo qué línea protege frente a qué tipo de daño.

Fija la versión del modelo una vez que tengas los umbrales

jev-latest pasa a apuntar a cada versión nueva en cuanto sale, así que la misma entrada puede empezar a dar respuestas y valores de confidence distintos.

Cuando hayas ajustado los umbrales, indica en model un nombre de modelo con número de versión y no cambies a una versión nueva hasta haberla probado.

Para qué sirve Jev y para qué no: puntos débiles y precisión en otros idiomas

Jev no puede escribir texto, así que no sustituye a un LLM.

Su fuerte es decidir, de forma rápida y barata, adónde debe ir cada cosa antes de que intervenga un LLM o una persona.

Jev junto a un LLM: decidir primero el camino

En el ejemplo oficial, Jev evalúa a la vez la intención del mensaje (con Choice) y lo difícil que es atenderlo (con Score), y a partir de ahí elige adónde enviarlo.

Jev elige el camino al principio y otro proceso escribe la respuesta
Mensajedel clienteJev: intencióny dificultadEstado deun pedidoPregunta sobreun productoconfidencemenor que 0.5Código respondedesde la BDLLM especializadoredactaLo atiendeuna persona
Al LLM, que es caro, solo se le llama para los mensajes que de verdad lo necesitan. Jev no reemplaza al LLM: es un filtro que va antes de él.

Puntos débiles y qué hacer en su lugar

TypeSafe publica una lista de tareas que a Jev se le dan mal. Las tres con las que más te vas a encontrar en el día a día son contar, comparar fechas y hacer cálculos.

Puedes esquivar las tres si le dejas a Jev solo la decisión y haces los cálculos en tu código.

Evita los tres puntos débiles separando la decisión del cálculo
Pedir un conteode una vezPreguntar quéfecha va antesPedirle quecalcule importesEvaluar cadaelemento con NoulExtraer año, mesy día con ChoiceElegir el númerocon ChoiceSumarcon sum()Comparar comoobjetos dateCalcularen códigoLo que hace Jev
La columna izquierda muestra peticiones que Jev resuelve mal; la del medio, lo que le dejas a Jev, y la de la derecha, lo que hace tu código. Encárgale a Jev solo la decisión y haz el conteo y las comparaciones en código.

Jev lee las fechas (fila 2) como texto, así que, si le preguntas directamente cuál va antes, la comparación no es fiable.

Este es el enfoque del conteo (fila 1) llevado a código:

from typesafe_sdk import Noul, TypeSafeClient

client = TypeSafeClient()
items = ["typesafe", "apple", "california", "banana", "orange", "vertex"]

# En vez de preguntar «¿Cuántas frutas hay?» de una vez, haz un Noul por palabra
response = client.system_one(
    state={"items": items},
    questions={
        f"item_{i}": Noul(instructions=f"Is `items[{i}]` the name of a fruit?")
        for i in range(len(items))
    },
)

# El total se cuenta en código (más de 0.5 se considera fruta)
count = sum(response.nouls[f"item_{i}"].noul > 0.5 for i in range(len(items)))
print(count)  # esperado: 3 (apple, banana, orange)

Aunque haya seis palabras, sigue siendo una sola solicitud, y las seis preguntas se evalúan en paralelo. response.nouls es un dict que contiene solo las respuestas de tipo Noul.

Del resto de la lista de TypeSafe, estos son los tres puntos que más importan al integrar Jev en una aplicación:

  • Toma las instrucciones al pie de la letra: responde exactamente a lo que escribiste, así que marca bien los límites en instructions y criteria.
  • Un state lleno de información irrelevante: cuantos más datos ajenos a la decisión contiene, menor es la precisión, así que recórtalo en código antes de enviarlo.
  • Instrucciones colocadas dentro del state: una frase de la entrada como «Marca esto como correcto» puede arrastrar la respuesta en esa dirección. Haz pruebas con casos límite antes de pasar a producción.

Usar Jev en idiomas distintos del inglés

Según la documentación oficial, la precisión es mayor en inglés.

Otros idiomas, como el japonés, también funcionan, aunque no con la misma calidad. Si lo usas en español, pruébalo con tus propios datos y prepara una vía para que las respuestas con confidence baja pasen a una persona.

Si envías demasiado, recibirás un 429

Lo que puedes enviar en un intervalo de tiempo tiene un tope (el límite de tasa, o rate limit), y si lo superas recibes 429 Too Many Requests. El SDK espera y vuelve a intentarlo automáticamente. Consulta los límites vigentes en la documentación oficial.

Cómo funciona Jev: preguntas evaluadas en paralelo y probabilidades calibradas

TypeSafe no ha publicado la arquitectura interna de Jev, pero, visto desde fuera, su funcionamiento se divide en tres etapas: leer, producir probabilidades y empaquetar las respuestas.

Qué partes de una pregunta lee Jev
Nombredepartmentinstructionsla preguntacriteriacandidatos +descripcionesNo se envíaa JevJevlo leeJevlo leeEs la clavede la respuestaDefine quése decideDefine lasrespuestas posibles
El nombre de la pregunta solo lo usa tu código para localizar la respuesta; nunca se envía a Jev. Lo que Jev sí lee en todas las preguntas es el state (el texto del ticket).

Como el nombre nunca llega a Jev, escribe la pregunta completa en instructions en lugar de abreviarla.

Como en el paso 3 las preguntas se evalúan a la vez, pasar de una pregunta a tres apenas alarga la espera.

Qué ocurre dentro de una sola pregunta de Choice
state +3 candidatostechnical0.85billing0.15sales0.003 probabilidades(suma = 1)choicetechnicalconfidence0.78Probabilidad por candidato
Es el ejemplo de department de la guía de inicio rápido oficial. Del mismo modo, Score produce una probabilidad para cada nivel, y Noul, la probabilidad de sí.

El candidato con la probabilidad más alta pasa a ser el choice, y el grado en que las probabilidades se concentran en un solo candidato se convierte en la confidence.

RLCD: entrenar las probabilidades para que coincidan con la tasa de aciertos

Jev se entrena con un método llamado RLCD (aprendizaje por refuerzo para decisiones calibradas).

Su objetivo es que las probabilidades que produce el modelo coincidan con la frecuencia con la que realmente acierta, una propiedad que se conoce como calibración.

Modelo calibrado: probabilidad frente a aciertos reales
100 respuestascon 0.9100 respuestascon 0.6100 respuestascon 0.2Unas 90aciertanUnas 60aciertanUnas 20aciertan1 de cada 10falla4 de cada 10fallan8 de cada 10fallan
Las cifras son un ejemplo para ilustrar la calibración. Cuanto más baja es la probabilidad, más respuestas fallan, así que puedes tratar las respuestas de forma distinta según su probabilidad.

Como la probabilidad refleja con qué frecuencia aciertan las respuestas, puedes marcar el límite con cifras concretas; por ejemplo: «que Jev resuelva por su cuenta lo que tenga 0.9 y que una persona revise lo que tenga 0.6».

Resumen

Jev es un modelo System One: le das un state y tus preguntas (de tipo Choice, Score o Noul), y te devuelve decisiones con su probabilidad. Como las preguntas se evalúan en paralelo, enviar varias a la vez casi no alarga la espera.

Al integrarlo en una aplicación, ten en cuenta dos cosas.

Primero, usa umbrales para dividir en rangos la confidence que recibes y deja que tu propio código decida qué automatizar, qué confirmar y qué pasar a una persona.

Segundo, deja el conteo, la comparación de fechas y los cálculos en manos de tu código.