Cómo llamar a Jev en AiHubMix: Un tutorial de clasificación estructurada

AIHubMix5 min de lectura
Cómo llamar a Jev en AiHubMix: Un tutorial de clasificación estructurada

Respuesta corta: jev-1.13 no genera texto. Envías un fragmento de texto más un conjunto de preguntas nombradas a https://aihubmix.com/v1/systemone, y recibes respuestas tipificadas asociadas a los nombres de tus preguntas: una categoría, una puntuación o una probabilidad. Nada que analizar. A continuación se muestra una solicitud funcional, el formato completo de respuesta y el único error de diseño que te costará precisión.

Para qué sirve Jev

Úsalo cuando necesites un juicio, no un párrafo: enrutar un ticket de soporte, puntuar la gravedad, señalar urgencia, restringir contenido. La página del modelo lo establece claramente: "Sin generación de texto, nada que analizar."

Utiliza un modelo de chat normal en su lugar cuando necesites explicaciones, resúmenes o cualquier salida en formato libre. Jev no puede producir eso.

Antes de comenzar

  • [ ] Python 3 instalado (la biblioteca estándar es suficiente)
  • [ ] Una cuenta de AiHubMix y una clave API
  • [ ] Clave exportada como AIHUBMIX_API_KEY, nunca codificada en el código fuente

No necesitas un SDK de OpenAI, LangChain o el paquete requests.

Paso 1 — Conocer el endpoint

POST https://aihubmix.com/v1/systemone
Authorization: Bearer YOUR_KEY
Content-Type: application/json

Esta es una ruta específica del modelo, no /v1/chat/completions. Los clientes compatibles con OpenAI no pueden llamarlo. Usa HTTP simple.

Paso 2 — Elegir tus tipos de preguntas

Hay tres, y puedes mezclarlas libremente en una solicitud:

TipoUsarlo paraProporcionas
choiceElegir una categoríacriteria como un dict: etiqueta → definición
scoreCalificación en una escala ordenadacriteria como una lista, de menor a mayor
noulUn juicio de sí/nonada más que instructions

Paso 3 — Construir la solicitud

state es el texto a juzgar. questions las claves son nombres que inventas; la respuesta utiliza los mismos nombres.

payload = {
    "model": "jev-1.13",
    "state": "Hola, he estado tratando de conectar mi cuenta de Stripe durante 3 días "
             "y sigue fallando. Estoy perdiendo ventas. Por favor, ayuda ASAP.",
    "questions": {
        "department": {
            "type": "choice",
            "instructions": "Qué equipo debería manejar esto",
            "criteria": {
                "billing":   "Problemas de pago o suscripción",
                "technical": "Errores o problemas de integración",
                "sales":     "Preguntas sobre precios o cuentas",
            },
        },
        "frustration": {
            "type": "score",
            "instructions": "Cuán frustrado parece el cliente",
            "criteria": [
                "Calmado, solo exponiendo hechos",
                "Frustrado pero civil",
                "Muy enojado, lenguaje fuerte",
            ],
        },
        "is_urgent": {
            "type": "noul",
            "instructions": "El mensaje transmite urgencia o sensibilidad al tiempo",
        },
    },
}

Paso 4 — Envíalo con la biblioteca estándar

import json, os, urllib.error, urllib.request

def ask(payload):
    req = urllib.request.Request(
        "https://aihubmix.com/v1/systemone",
        data=json.dumps(payload).encode(),
        headers={"Authorization": "Bearer " + os.environ["AIHUBMIX_API_KEY"],
                 "Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=60) as r:
            return json.loads(r.read())
    except urllib.error.HTTPError as e:
        raise SystemExit(f"HTTP {e.code}: {e.read().decode(errors='replace')[:500]}")

Mantén la construcción de la solicitud dentro de una función. Si construyes y envías a nivel de módulo, importar el archivo vuelve a activar la llamada y gasta tokens.

Paso 5 — Leer las respuestas

Cada respuesta almacena su valor bajo una clave que coincide con su type, así que un accesorio cubre los tres:

data = ask(payload)
for name, ans in data["answers"].items():
    kind = ans["type"]
    print(name, kind, ans[kind], ans.get("confidence"))
print("usage:", data.get("usage"))

Salida verificada:

department   choice  billing   0.51
frustration  score   1         1
is_urgent    noul    1         None
usage: {'input_tokens': 424, 'output_tokens': 73}

Paso 6 — Entender el sobre completo

El bucle de impresión oculta campos útiles. El JSON crudo para una score respuesta:

{
  "type": "score",
  "score": 1,
  "legend": {"0": "Calmado, solo exponiendo hechos", "1": "Frustrado pero civil", "2": "Muy enojado, lenguaje fuerte"},
  "probabilities": {"0": 0, "1": 1, "2": 0},
  "confidence": 1
}
  • legend asocia el índice de vuelta a tu propia redacción: el entero es autodescriptivo, por lo que no necesitas una tabla de búsqueda en tu código.
  • probabilities ofrece la distribución completa, útil para detectar un empate cercano.
  • noul no tiene campo de confidence. Su probabilidad es la señal.

El nivel superior también devuelve usage, id, provider (TypeSafe), y la versión de backend resuelta typesafe/jev-1.13-20260917.

El error que te cuesta precisión

En la solicitud anterior, department devolvió billing con una confianza de 0.51. Repetir la solicitud idéntica devolvió la misma etiqueta con 0.38 — la respuesta fue estable, la certeza declarada no.

La causa está en los criterios, no en el modelo. billing es "Problemas de pago o suscripción" y technical es "Errores o problemas de integración." Una integración de Stripe que sigue fallando coincide genuinamente con ambas. El modelo estaba informando una ambigüedad que estaba escrita en el esquema.

Dos reglas antes de la producción:

  1. Escribe criterios de choice que sean mutuamente excluyentes. Si un humano dudaría entre dos etiquetas, el modelo también lo hará.
  2. Establece un umbral de confianza y enruta resultados de baja confianza a una cola humana en lugar de aceptarlos como decisiones. Un modelo que admite incertidumbre es más valioso que uno que la oculta.

Lista de verificación previa al lanzamiento

  • [ ] Clave cargada desde el entorno o un archivo en modo 600 que tu VCS ignora
  • [ ] choice criterios revisados para superposición
  • [ ] Umbral de confianza definido, con un camino de respaldo por debajo de él
  • [ ] noul respuestas manejadas por separado — no llevan confidence
  • [ ] Preguntas no utilizadas eliminadas (3 preguntas cuestan 424 tokens de entrada; 2 cuestan 355)
  • [ ] Respuestas no 2xx registradas con el cuerpo crudo

FAQ

¿Puedo usar el SDK de OpenAI? No. /v1/systemone no es una ruta compatible con OpenAI.

¿Puede jev devolver una oración o resumen? No. Solo responde a las preguntas tipificadas que defines.

¿Cuántas preguntas por solicitud? Las pruebas verificadas utilizaron dos y tres. Cada pregunta añade tokens de entrada y salida, así que incluye solo lo que vas a utilizar.

¿Hay un alias de versión? La página del modelo enumera un jev-latest alias junto a jev-1.13. Fija la versión explícita si la reproducibilidad es importante.

¿Cuánto cuesta? La página del modelo publica $0.0462 / M tokens de entrada y $0 / M tokens de salida. Estas son cifras del proveedor: confirma los precios actuales antes de presupuestar.

¿Cuál es la ventana de contexto? La página del modelo es inconsistente: 64K en su encabezado, 32K en la tabla del proveedor. Verifica contra tu propia entrada más larga antes de confiar en cualquiera de las dos.

Alcance de esta guía

Todo lo anterior fue verificado con tres llamadas en vivo contra una sola entrada. No cubre latencia, agrupamiento, rendimiento o comportamiento en entradas diferentes al ejemplo. La deriva de confianza es una observación reproducida, no una tasa de error medida: repítela con tus propios datos antes de establecer un umbral.

Comienza en AiHubMix

jev-1.13 está disponible a través de AiHubMix, y la página del modelo contiene todo lo que este tutorial mencionó: el /v1/systemone endpoint, los tres tipos de preguntas con sus formatos de criteria, los campos de respuesta completos y la tarifa publicada de $0.0462 / M tokens de entrada con $0 / M tokens de salida. El alias jev-latest se resuelve a la versión más nueva, por lo que se mantiene actualizado a medida que las versiones cambian.

Comienza aquí: https://aihubmix.com/model/jev-latest

Próximos pasos:

  1. Crea una cuenta de AiHubMix y genera una clave API
  2. Copia la solicitud del Paso 3 y la función ask() del Paso 4
  3. Reemplaza state con un registro real de tu propia cola
  4. Compara el resultado con la forma en que clasificas ese registro hoy

Si esta guía fue útil, suscríbete para futuros posts sobre modelos de salida estructurada y pipelines de clasificación.