Ir al contenido
angel.library

Jev: confianza, patrones de arquitectura y límites

Jev está pensado para vivir dentro de un sistema: el código manda y Jev toma decisiones estrechas y estructuradas. La habilidad clave es pensar en decisiones atómicas que se componen en comportamiento complejo.

Choice y Score devuelven probabilities (una distribución que suma 1) y confidence, un número de 0 a 1 que resume la forma de esa distribución:

  • concentrada en una opción → confianza alta;
  • repartida → confianza baja (a menudo ninguna opción encaja bien, o la pregunta es ambigua).

Para Choice con K opciones, la confianza se calcula como (p_max − 1/K) / (1 − 1/K): 0 si todo es uniforme, 1 si una opción tiene toda la probabilidad. Noul no trae confidence: su valor ya es una probabilidad.

La calibración se mide sobre grupos de predicciones: significa que, de muchas respuestas con 0,9, alrededor del 90 % acierta. No garantiza que una respuesta concreta sea correcta.

Un sistema que no puede expresar incertidumbre no es fiable. La confianza permite que el código se comporte distinto según lo seguro que esté el modelo:

RangoComportamiento
AltaActuar automáticamente
MediaProceder con cautela: pedir confirmación, marcar para revisión o recoger más datos
BajaNo actuar: pasar a una persona, pedir aclaración o usar otro sistema (por ejemplo, un LLM con razonamiento)

No hay un único umbral. En el mismo sistema, una acción de solo lectura puede ejecutarse con menos confianza que una destructiva. TypeSafe sugiere 0,5 como suelo para descartar lo genuinamente incierto y umbrales más altos cuanto más cara sea equivocarse.

from typesafe_sdk import Choice, TypeSafeClient
UMBRALES = {"leer": 0.5, "etiquetar": 0.7, "reembolsar": 0.9}
client = TypeSafeClient(model="jev-1.13.0") # umbrales ajustados contra esta versión
r = client.system_one(
state=ticket,
questions={"accion": Choice(
instructions="What should the support system do with this ticket?",
criteria={"leer": "Just log it", "etiquetar": "Tag it for a team", "reembolsar": "Issue a refund"},
)},
)
a = r.choices["accion"]
if a.confidence >= UMBRALES[a.choice]:
ejecutar(a.choice)
else:
enviar_a_revision(ticket, a)
PatrónIdeaBeneficio
Speculative fan-outEnviar muchas preguntas en una llamada, incluso especulativas, y que el código decida cuáles importanCoste, velocidad
Confidence-gated routingUsar la confianza como segundo eje: la respuesta dice qué; la confianza, si actuarFiabilidad, seguridad
Composite scoringPartir un juicio complejo en puntuaciones atómicas y combinarlas con pesos en códigoCoste, fiabilidad, velocidad
Intent routingClasificar la intención y enviar cada petición al manejador óptimo: lógica determinista, un LLM especialista o una personaCoste, velocidad

Como el estado se procesa una vez y las preguntas corren en paralelo, preguntar de más cuesta poco. Pregunta todo lo que podrías necesitar y usa solo lo que aplique según las respuestas.

from typesafe_sdk import Score
niveles = ["weak", "average", "strong"]
preguntas = {
"mercado": Score(instructions="How large is the addressable market?", criteria=niveles),
"tecnica": Score(instructions="How feasible is the technical plan?", criteria=niveles),
"diferenciacion": Score(instructions="How differentiated is the product?", criteria=niveles),
}
r = client.system_one(state=pitch, questions=preguntas)
PESOS = {"mercado": 0.5, "tecnica": 0.3, "diferenciacion": 0.2}
total = sum(PESOS[k] * r.scores[k].score for k in PESOS)

Si cambian las prioridades, cambias PESOS, no un prompt.

La documentación incluye recetas completas y medidas:

CookbookQué muestra
Parallel questions13 preguntas en una llamada: 12,2× más barato y 10× más rápido, mismas respuestas
Re-rankingTop-1 de 5 % a 18 % y top-10 de 38 % a 62 % sobre shortlists BM25 legales
Line-by-line searchBúsqueda semántica sobre 218 líneas con un Choice y un Noul para saber si hay respuesta
Guardrails for LLMsFiltrar cada mensaje de entrada y salida de una app con LLM con una sola petición
Function callingConvertir peticiones en lenguaje natural en llamadas a funciones tipadas
Skill suggestionElegir como mucho una skill de las 182 del catálogo de Hermes
Date extractionExtraer partes de fechas con Choice y hacer la aritmética en código
SDE cascadeExtracción en cascada (mini → verificación → razonamiento) con calidad de modelo grande a fracción del coste
Hierarchical classificationBeam search sobre jerarquías profundas usando las probabilidades de Choice
Classification using confidenceClasificar informes SEC en 75 grupos y bajar a la división superior si la confianza es baja

TypeSafe publica los «bordes dentados» del modelo (revisado el 17 de septiembre de 2026):

#FalloQué hacer
1Lectura literal: responde lo que escribiste, no lo que quisiste decirEscribe la condición exacta y los casos límite en los criterios
2Matemáticas y números: no cuenta bien ni compara valores numéricos (hex, RGB)Haz la aritmética en código; pasa números ya calculados o categorías con nombre
3Fechas y horas: las lee como texto, no como cantidades ordenadasExtrae día, mes y año con Choice y compara en código
4Indirección: dobles negaciones o varios saltos de razonamientoPregunta de la forma más directa; nombra la parte relevante del estado
5Estado grande con detalle irrelevante: el ruido distrae (context rot)Filtra antes en código o con un Noul de relevancia
6Contenido adversarialCriterios explícitos y pruebas antes de desplegar
7Instrucciones y criterios contradictoriosTrata los criterios como extensión de la instrucción
8Invariantes estructurales: P(sí) y 1 − P(no) de dos preguntas no tienen por qué sumar 1No traslades un umbral de un Noul a un Choice; formula cada decisión de una sola manera
9Generación: no está entrenado para producir textoExtrae candidatos con regex o un LLM y deja que Jev elija

Para contar, itera en código y haz una pregunta por elemento:

from typesafe_sdk import Noul
items = ["typesafe", "apple", "california", "banana", "orange"]
r = client.system_one(
{"items": items},
{f"item_{i}": Noul(instructions=f"Is `items[{i}]` the name of a fruit?") for i in range(len(items))},
)
frutas = sum(r.nouls[f"item_{i}"].noul > 0.5 for i in range(len(items)))

Resumen de lo que conviene evitar: preguntar algo que el código calcula exacto, esconder varios juicios en una pregunta, tareas de «Sistema 2» con muchas capas, y meter en state más contexto del que la pregunta necesita.