26 sept 2026

Jev frente a pedirle JSON a un LLM

Por qué un modelo de decisiones y un modelo de lenguaje no son intercambiables — y cómo estructurar una base de código que use ambos.

Dos contratos distintos

Un modelo de chat escribe texto. Incluso con modo JSON o salidas estructuradas estrictas, sigue muestreando tokens hacia un esquema — la forma está garantizada, el contenido se genera. Jev funciona al revés: el contenido está garantizado (solo puede devolver una opción que declaraste) y lo que añade el modelo es la distribución de probabilidad sobre tus opciones declaradas. Son contratos distintos, y fallan de maneras distintas.

  • Modelo de chat con modo JSON: la forma sale bien, pero puede mostrar una etiqueta que no declaraste («billingx» en vez de «billing»), canonizar de forma inconsistente o envolver el payload en prosa. Escribes un parser, una comprobación de allowlist y un bucle de reintentos.
  • Modelo de decisiones: el espacio de respuestas son los criteria que enviaste. Una pregunta choice con tres opciones devuelve exactamente una de esas tres más una probabilidad para cada una. No hay nada que parsear, porque no se generó nada.

Dónde el LLM gana de verdad

Las tareas de generación — escribir el correo, resumir el ticket, redactar el SQL — pertenecen al modelo de chat. Nada más estrecho las reemplaza. Las salidas estructuradas también van bien cuando lo que necesitas es un objeto personalizado (campos extraídos de un documento) en lugar de una decisión de ramificación. Deja ese pipeline como está.

La costura es la línea de código que hoy dice: if (await classify(text) === "billing"). Esa línea necesita una respuesta acotada con una probabilidad calibrada, no texto fluido.

El problema de la confianza

Pídele un número de confianza a un modelo de chat y te dará uno — pero es una autocertificación sobre su propia fluidez, no una probabilidad calibrada sobre las opciones que declaraste. Dos llamadas que informan ambas «85% seguro» pueden estar en regímenes completamente distintos. Las probabilidades de un modelo de decisiones son comparables entre entradas, y eso es lo que te permite fijar un umbral («enviar a un humano por debajo de 0,8») y fiarte de él a lo largo de cientos de miles de llamadas.

Una comparación desarrollada

Tomemos la clasificación de intención en tres colas — billing, technical, sales.

  • Enfoque con modelo de chat: un prompt con las etiquetas, ejecutado en modo JSON. El coste escala con un system prompt y todo el contexto que reenvías en cada llamada. Te defiendes de las etiquetas sueltas con una allowlist, y los desvíos permanecen en silencio hasta que un cliente se queja.
  • Enfoque con decisión tipada: una pregunta choice con las tres descripciones de criteria. Un ticket corto pesa 300–500 tokens de entrada — mínimo 1 crédito, $0,0001 en Starter. Los desvíos se manifiestan como distribuciones de probabilidad de alta entropía sobre las que puedes poner umbral, en lugar de que el código acepte en silencio una etiqueta equivocada.

Usar ambos en el mismo proceso

  • Deja que el LLM genere o extraiga con libertad donde la creatividad o la comprensión son el punto.
  • Pon a Jev en las preguntas estrechas antes de que tu código actúe: qué cola, qué nivel de modelo, enviar a producción o bloquear.
  • No trates ninguna de las dos salidas como una decisión legal, médica o financiera — fija un umbral y mantén a una persona en el camino de alto riesgo.

La mayoría de los sistemas en producción acaban con ambos: Jev para la ramificación repetida, el modelo de chat para aquello en lo que es singularmente bueno.

Modos de fallo, lado a lado

  • Deriva de etiquetas en texto libre: el LLM devuelve «billing-related» donde tu switch quiere «billing». La llamada tipada indexa las probabilidades por las claves exactas que declaraste, así que la deriva es estructuralmente imposible.
  • Campos alucinados: el modo JSON puede añadir claves que no pediste. Un modelo de decisiones no puede — el esquema de respuesta lo fijan los tipos de pregunta.
  • Desvíos silenciosos: el caso de deriva que pasa porque el código downstream recurrió a un valor por defecto. En una decisión tipada puedes registrar la distribución de probabilidad completa por llamada, y revisar las bimodales.
  • Teatro de confianza: parsear y luego afirmar («estoy seguro de que esto es X») — impreciso, no calibrado. La confianza de Jev acompaña cada respuesta choice y score y alimenta tu camino de revisión humana.

Migrar un clasificador basado en parser

La migración es mecánica: deja de pedirle una etiqueta al modelo de chat y pon la misma taxonomía en los criteria de una pregunta choice, con la misma redacción que usaba el prompt. Resiste las ganas de redescribir las etiquetas; tu redacción actual del prompt ya codifica las distinciones del equipo. Ejecuta dos semanas pidiendo ambos, registra la concordancia — cuando los desacuerdos sean del 2% o menos, mira un puñado de casos, y el final siempre es el mismo: o la redacción de los criteria es ambigua, o el caso era genuinamente ambiguo y el sistema antiguo ya desviaba en silencio de todos modos.

La misma solicitud, de las dos maneras

Así se ven los dos contratos sobre el mismo ticket:

system: Classify the support message into billing, technical
or sales. Reply with {"queue": "..."}. Do not invent labels.
user: Charged twice for order A-104, please refund the duplicate.
Prompt de modelo de chat (etiqueta forzada en JSON)
{
  "state": "Charged twice for order A-104, please refund the duplicate.",
  "questions": {
    "queue": {
      "type": "choice",
      "instructions": "Which team handles this?",
      "criteria": {
        "billing":  "Payments, payouts, invoicing, refunds",
        "technical": "Bugs, outages, integrations",
        "sales":    "Pricing, upgrades, new accounts"
      }
    }
  }
}
Solicitud de decisión tipada

El primero devuelve {"queue": "billing"} cuando va bien, y cualquier cosa cuando va mal. El segundo devuelve billing con una probabilidad de, digamos, 0,97, distribuciones sobre las tres opciones y un valor de confianza — más el mismo contrato de fallo todas las veces (una forma de error con error.code, nunca una respuesta incorrecta que suene convincente). Diseña el código downstream en torno al fallo que prefieras depurar.

¿Un modelo de decisiones es solo un LLM con un prompt?

No. El espacio de respuestas está acotado en sí mismo — las probabilidades van sobre las opciones que declaraste — y el modelo está construido para ese trabajo, no para la fluidez. Por eso sus probabilidades están lo bastante calibradas como para ponerles umbral.

¿Qué es más barato para clasificación?

Por decisión, la vía tipada es difícil de superar: 1 crédito (el mínimo) por una clasificación corta — $0,0001 en Starter — frente a una llamada a modelo de chat que reenvía un system prompt en cada solicitud y luego necesita código de validación y reintentos.

¿Y la latencia para clasificación?

Las mediciones contra la pasarela en producción se agrupan en 400–560 ms de latencia por llamada. Una llamada de chat que hace la misma clasificación suele ser similar o más lenta, porque genera texto que luego hay que parsear, validar y quizá reintentar.

Prueba el playground de Jev AI para enviar tu primera decisión gratis cuando termines esta guía.