JEV - Dos demos que solo devuelven una distribución

Los dos ejemplos solo preguntan una elección cerrada: si la atención debe cortar hacia una persona, y si una fusión debe pasar. Lo que vuelve es una distribución. La latencia publicada sigue en unos 70 a 500 milisegundos, no la cifra en milisegundos de un demo.

JEV - Dos demos que solo devuelven una distribución

Coautor: folkbench.com (Folkbench es una plataforma revisable de evaluación y selección de API de IA, servicios de modelos y sitios relacionados. Se apoya en información de servicio publicada, precios, disponibilidad, latencia y ventanas de evidencia para ayudar a los usuarios a comparar y a elegir un camino.)

Diez textos en esta serie:

Los dos demos son el mismo trabajo: nada de texto libre, solo una pregunta cerrada, y la rama se toma de la distribución. El JSON y el código de abajo son la forma de una llamada, no un informe de tiempos. El tramo publicado de extremo a extremo es de unos 70 a 500 milisegundos. No anote una corrida de 18 milisegundos como cifra de producto. Lo que vale la pena ver es que la respuesta no contiene una frase token a token.

Soporte: intención y un corte

La escena

El soporte teme a un usuario que ya está furioso mientras el sistema sigue tecleando. Usar un modelo generativo para la intención suele significar esperar un primer token y un bloque JSON generado, en nombre de la exactitud. Una expresión regular pelada no ve la ira que habla dando rodeos. Lo que se quiere es una clasificación cerrada, y luego una decisión inmediata sobre el pase a una persona.

Estado y opciones

Esto es un Choice, no un Noul. Noul responde sí o no. Aquí hay tres opciones.

[State]
scene: live support entry
rule: assign probability across the given options from the message text

[user]
I have waited three days. The shipment has not moved. Are you even alive? Refund me now, or I escalate.
{
  "question": "choice",
  "options": [
    {"id": "GENERAL", "description": "ordinary question or tracking, no strong emotion"},
    {"id": "REFUND", "description": "a clear return or refund, stated flatly"},
    {"id": "BREAKER", "description": "insult, threat, or a complaint that should break to a person"}
  ]
}

Lo que vuelve es una distribución

No hay un cursor soltando caracteres. La forma es una tabla, no una reseña.

{
  "top": "BREAKER",
  "scores": [
    {"choice": "BREAKER", "score": 0.9241},
    {"choice": "REFUND", "score": 0.0715},
    {"choice": "GENERAL", "score": 0.0044}
  ]
}

Los números son la distribución dentro de este ejemplo, para que la rama se pueda escribir. No son un referente publicado. El modelo asigna probabilidad sobre las opciones dadas. No está prediciendo el carácter siguiente.

Cómo lo toma el código

async function handleIncomingCustomerMessage(userMessage: string) {
  const res = await jev.choice("cs_intent_v1", { input: userMessage });
  const breaker = scoreOf(res, "BREAKER");
  if (breaker > 0.85) {
    return triggerHumanOverride({ priority: "CRITICAL", queue: "RETENTION" });
  }
  if (scoreOf(res, "REFUND") > 0.70) {
    return launchWorkflow("AUTOMATED_REFUND_FLOW");
  }
  return launchWorkflow("DEFAULT_FAQ_BOT");
}

No hay un reintento extra cuyo único trabajo sea analizar Markdown. El umbral está en el código. 0.85 y 0.70 son la política de este flujo. No son una garantía del modelo.

Una revisión antes de la fusión

La escena

Los análisis estáticos se apoyan en un árbol de sintaxis y en reglas muertas. Las variantes se cuelan, y las falsas alarmas son comunes. Pedirle a un modelo de charla que lea un diff de 500 líneas y escriba una reseña suele llevar muchos segundos. La canalización no puede esperar, y un programa no puede leer «pasa» o «no pasa» dentro de la prosa. Trate el diff como estado, y pregunte un Choice: pasar, que una persona mire, o bloquear.

Estado y opciones

[Git diff]
PR #1042
file: src/auth/session.ts

+  // skip expiry outside production, or when the token starts with test_admin_
+  if (process.env.NODE_ENV !== 'production' || token.startsWith('test_admin_')) {
+    return session;
+  }
{
  "question": "choice",
  "options": [
    {"id": "PASS", "description": "harmless refactor, docs, or ordinary logic"},
    {"id": "WARN", "description": "config, dependency, or a non-sensitive refactor; a person should look"},
    {"id": "BLOCK", "description": "backdoor, hardcoded secret, privilege jump, auth bypass, injection"}
  ]
}

Un prefijo test_admin_ que salta el vencimiento en producción es una evasión de la autenticación. En el ejemplo, la distribución pone BLOCK cerca de 0.98. Borre esa cláusula y deje solo «saltar fuera de producción», y la misma pregunta pasa de bloqueo a una mirada humana. Así se usa la pregunta. No es un conjunto de milisegundos prometidos.

Cómo lo toma una canalización

def audit_pr_diff(diff_text: str) -> int:
    result = jev.choice(
        question="pr_security_v2",
        state=diff_text,
        options=["PASS", "WARN", "BLOCK"],
    )
    scores = result.scores
    if result.top == "BLOCK" and scores["BLOCK"] > 0.80:
        print("high-risk auth change")
        return 1
    if result.top == "WARN":
        mark_review_required()
        return 0
    return 0

Basta una dirección de servicio interno. No lea esto como un sitio público que ya ofrece Jev en su nombre. La canalización lee la opción de arriba y las puntuaciones. Si una persona aún necesita una reseña escrita, pregunte a un modelo que sepa escribir. No empuje esa prosa de vuelta a esta pregunta.

Como llamar a una interfaz que devuelve números

Las dos corridas vuelven concreto un hecho: el juicio complicado se queda dentro del modelo, y afuera solo queda la probabilidad. Noul, Choice y Score son tres rejillas, no tres estilos de charla.

Enrutado, riesgo, una comprobación antes de la fusión, un motor de políticas, una rama de Agent: pregunte primero si el paso se puede escribir como pregunta cerrada. Si se puede, no espere una generación. Si no se puede, no lo disfrace de esta clase de llamada.

Serie