Modelos de solución Jev en Ollama: uso práctico /v1/systemone

Written by

in

A partir de la versión 0.35, Ollama admite modelos de decisión creados en la API Jev de TypeSafe. Estos no son modelos de chat en el sentido habitual: no escriben texto, sino que responden a una serie de preguntas escritas sobre el estado transferido. Para clasificación, enrutamiento, moderación y clasificación, esto resulta ser más rápido y confiable que pedirle a un LLM normal que devuelva JSON y luego analice su respuesta.

En esta publicación, veremos qué son los modelos de decisión, cómo funcionan a nivel HTTP, qué modelos ya están disponibles y cómo integrarlos en el código existente para que los modelos generativos regulares sigan funcionando.

¿En qué se diferencian los modelos de decisión de los habituales?

Un LLM normal recibe un mensaje y genera texto token por token. Incluso si le pides que responda en una palabra, la generación todavía ocurre en el interior y el formato de la respuesta debe controlarse mediante un diagrama, instrucciones y verificación posterior. El modelo de decisión funciona de manera diferente: pasa estados y preguntas con tipos, y el modelo devuelve probabilidades y opciones seleccionadas. Sin texto libre, sin análisis JSON de la respuesta.

El nuevo punto final se llama /v1/systemone. En una solicitud, puede hacer varias preguntas a la vez y el modelo las responderá todas. Esto es conveniente para tareas en las que es necesario tomar varias decisiones relacionadas: por ejemplo, determinar el equipo, la necesidad de devolución y la urgencia del billete.

Qué modelos están disponibles

Ahora puedes ejecutar tres modelos de decisión a través de Ollama:

  • nimble es un modelo abierto con 9 mil millones de parámetros de Bespoke Labs. Es el más grande y preciso disponible.
  • tev1 es un modelo experimental con 4 mil millones de parámetros de Together AI.
  • tev1:0.8b es un modelo experimental con 800 millones de parámetros de Together AI. El más rápido y sencillo.

Todos funcionan localmente, no requieren pago y no envían datos a un servicio externo. Se admiten Ollama 0.35 y posteriores.

Instalación

Primero revisa la versión de Ollama:

ollama --version

Luego descargue el modelo deseado. Para el más fácil:

ollama pull tev1:0.8b

Para la versión completa de tev1:

ollama pull tev1

Para ágil:

ollama pull nimble

El modelo ágil ocupa alrededor de 9,5 GB de espacio en disco, por lo que es una buena idea liberar algo de espacio antes de descargar. tev1:0.8b ocupa menos de un gigabyte.

Primera solicitud mediante curl

El ejemplo más sencillo es determinar si un texto es un anuncio de empleo:

curl http://localhost:11434/v1/systemone -d '{
  "model": "tev1:0.8b",
  "state": {
    "message": "Senior Swift developer, Berlin, remote friendly"
  },
  "questions": {
    "isJob": {
      "type": "noul",
      "instructions": "Does the message advertise a job posting that someone can apply to?"
    }
  }
}'

La respuesta se ve así:

{
  "model": "tev1:0.8b",
  "answers": {
    "isJob": {
      "type": "noul",
      "noul": 0.921
    }
  },
  "usage": {
    "input_tokens": 42,
    "output_tokens": 0
  }
}

El campo noul es una probabilidad de 0 a 1. La decisión se toma en comparación con un umbral, normalmente 0,5. A diferencia del modelo generativo, no es necesario pedir una respuesta en formato JSON y luego comprobar que el modelo no la ha roto.

Tipos de preguntas

Los modelos de decisión admiten tres tipos de preguntas.

noul es una pregunta binaria. Devuelve la probabilidad de que una afirmación sea verdadera:

{
  "questions": {
    "refund": {
      "type": "noul",
      "instructions": "Does the customer explicitly ask for a refund?"
    }
  }
}

elección: seleccionar una opción de un conjunto determinado. Devuelve la opción seleccionada, las probabilidades de todas las opciones y la confianza:

{
  "questions": {
    "team": {
      "type": "choice",
      "instructions": "Which team should handle this ticket?",
      "criteria": {
        "billing": "Payments and refunds",
        "technical": "Bugs and integrations",
        "other": "None of the above"
      }
    }
  }
}

puntuación: calificación en una escala. Devuelve el número, la leyenda y las probabilidades de cada punto de escala:

{
  "questions": {
    "urgency": {
      "type": "score",
      "instructions": "How urgent is this ticket?",
      "criteria": ["Routine", "Soon", "Urgent"]
    }
  }
}

Una solicitud puede contener varias preguntas de diferentes tipos a la vez. Esto es lo que hace que los modelos de decisión sean convenientes para la clasificación: una operación, un estado, varias decisiones independientes.

Python sin bibliotecas adicionales

Para solicitudes, la urllib estándar es suficiente; no se requiere un SDK separado:

import json
from urllib.request import Request, urlopen

OLLAMA_DECISION_URL = "http://localhost:11434/v1/systemone"

def ask_decision(state, questions, model="tev1:0.8b"):
    payload = {
        "model": model,
        "state": state,
        "questions": questions,
    }
    request = Request(
        OLLAMA_DECISION_URL,
        data=json.dumps(payload).encode(),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urlopen(request, timeout=3600) as response:
        return json.loads(response.read().decode())["answers"]

Uso:

answers = ask_decision(
    {"message": "Senior Swift developer, Berlin, remote friendly"},
    {
        "isJob": {
            "type": "noul",
            "instructions": "Does the message advertise a job posting that someone can apply to?"
        }
    },
)

probability = answers["isJob"]["noul"]
is_job = probability >= 0.5

Si necesita un SDK oficial de Python, se llama typesafe-sdk. Para localhost, se puede dirigir a Ollama con las variables de entorno TYPESAFE_BASE_URL, TYPESAFE_API_KEY y TYPESAFE_DEFAULT_MODEL. Pero para tareas sencillas, una solicitud HTTP directa es suficiente.

Cómo entender que un modelo apoya la decisión

Los modelos de decisión no pueden responder a través de /api/generate o /api/chat. Si envía dicha solicitud, Ollama devolverá un error 400 con un texto como:

"tev1:0.8b" does not support generate

Esto es importante si ya tiene código que funciona con modelos normales a través de /api/generate: si cambia el modelo a un modelo de decisión, dejará de funcionar. Es mejor conocer las capacidades del modelo de antemano a través de /api/show y elegir el método de llamada apropiado:

import json
from urllib.request import Request, urlopen

OLLAMA_SHOW_URL = "http://localhost:11434/api/show"

def supports_decision(model):
    request = Request(
        OLLAMA_SHOW_URL,
        data=json.dumps({"model": model}).encode(),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urlopen(request, timeout=30) as response:
            capabilities = json.loads(response.read().decode()).get("capabilities", [])
    except (OSError, TypeError, ValueError):
        return False
    return "decision" in capabilities

Los modelos de decisión sólo tendrán decisión en sus capacidades. Los modelos normales tendrán terminaciones, herramientas u otras características allí. Si Ollama no está disponible, es razonable considerar el modelo normal y utilizar la ruta generativa.

Cómo incrustar en código existente

La forma más sencilla no es reescribir el clasificador, sino dividirlo en dos estrategias. La estrategia generativa funciona como antes: recopila el mensaje, lo envía a /api/generate y analiza el JSON. La estrategia de decisión envía el estado y la pregunta escrita a /v1/systemone y compara la probabilidad con un umbral.

La elección de la estrategia ocurre en un solo lugar, al crear un clasificador:

def create_classifier(model):
    if supports_decision(model):
        return DecisionClassifier(model)
    return GenerativeClassifier(model)

Este enfoque tiene varias ventajas. Los modelos generativos continúan funcionando sin cambios. El modelo de decisión se puede habilitar cambiando una variable de entorno. Y toda la diferencia entre los dos métodos se concentra en dos clases pequeñas y no se distribuye por toda la aplicación.

Para una clasificación binaria, la estrategia de decisión se parece a esto:

async def classify(text):
    answers = await ask_decision(
        {"message": text},
        {
            "isJob": {
                "type": "noul",
                "instructions": instructions,
            }
        },
        model,
    )
    probability = answers["isJob"]["noul"]
    return probability >= 0.5, probability

Tenga en cuenta que el modelo de decisión no devuelve una explicación. Si su formato de resultado tiene un campo de motivo, puede construirlo a partir de la probabilidad: por ejemplo, almacene la probabilidad misma o una cadena como “el modelo calificó el mensaje en 0,935 como una vacante”. Esto es más honesto que inventar una razón que el modelo no dio.

Las instrucciones deben ser una pregunta

Ésta es la conclusión práctica más importante. Los modelos de decisión no entienden indicaciones largas del estilo de “usted clasifica los mensajes, responda verdadero si…, falso en caso contrario”. Quieren una pregunta breve y directa.

En el mismo mensaje sobre una vacante, recibí las siguientes probabilidades:

  • Pregunta directa “¿Este mensaje es una oferta de trabajo?” — 0,921.
  • Instrucciones largas que explican lo que se considera una vacante: 0,026.
  • Instrucciones largas con una pregunta al final: 0,391.

La diferencia es casi treinta veces. El modelo no se equivoca en la clasificación, simplemente no entiende lo que quieren de él cuando la pregunta está escondida dentro de un párrafo. Por lo tanto, para los modelos de decisión vale la pena mantener instrucciones breves separadas y dejar indicaciones largas para los modelos generativos.

Es conveniente crear una variable de entorno separada:

OLLAMA_JOB_CLASSIFIER_DECISION_INSTRUCTIONS=Does the message advertise a job posting that someone can apply to?

Y utilice un mensaje normal sólo para la ruta generativa.

Umbral y probabilidades

El umbral de 0,5 es adecuado como valor predeterminado, pero es útil incluirlo en la configuración. Para diferentes tareas, el costo de una respuesta falsa positiva y falsa negativa es diferente. Por moderación, es más seguro elevar el umbral; para buscar vacantes, es más seguro bajarlo para no perderse mensajes útiles.

También es útil registrar la probabilidad en sí, y no sólo el valor booleano resultante. Cuando el clasificador comete un error, el registro muestra si fue una respuesta segura o una decisión en el límite. Para las preguntas de elección, vale la pena guardar las probabilidades y la confianza: muestran cuánto fluctúa el modelo entre opciones.

Rendimiento y memoria

La velocidad depende en gran medida del tamaño del modelo y del hardware. En la CPU en mis pruebas obtuve los siguientes números:

  • tev1:0.8b: fracciones de segundo para resolver, cabe fácilmente en la memoria.
  • tev1 – 4B, notablemente más lento, pero aún adecuado para tareas interactivas.
  • ágil: 9B en Q8_0, aproximadamente 10 GB de memoria. La primera solicitud, incluida la carga del modelo, tardó unos 137 segundos, las soluciones posteriores tardaron entre 12 y 32 segundos en la CPU.

Nimble requiere mucha RAM. En una máquina con 16 GB y Docker/WSL con un límite de unos 8 GB, el modelo no encaja: el sistema comienza a intercambiar y los contenedores dejan de responder. Aumentar el límite de WSL a 12 GB a través del archivo .wslconfig ayudó:

[wsl2]
memory=12GB
swap=8GB

Después del cambio, necesita wsl –shutdown y reinicie Docker Desktop. Pero incluso con 12 GB, la reserva sigue siendo pequeña: el modelo ocupa unos 10 GB y no queda mucho para el sistema.

De forma predeterminada, Ollama descarga el modelo después de cinco minutos de inactividad, liberando memoria. Esto es conveniente: ágil no mantiene ocupados 10 GB todo el tiempo, pero cada nuevo lanzamiento, después de una pausa, comienza a cargar el modelo nuevamente.

Cuándo utilizar modelos de decisión

Los modelos de decisión son muy adecuados para tareas en las que se necesita una respuesta rápida y económica a una pregunta claramente formulada:

  • Clasificación de mensajes, tickets y solicitudes.
  • Enrutamiento por comandos o ejecutores.
  • Moderación de contenido y controles de seguridad.
  • Soluciones binarias y multivariadas rápidas en juegos o aplicaciones interactivas.

No son adecuados para tareas en las que se necesita texto detallado: explicación, extracción de campos, resumen, generación de respuestas. Para ello se mantienen los modelos generativos habituales. El mejor resultado se obtiene cuando se combinan: un modelo de decisión toma una decisión y un modelo generativo la explica o extrae datos.

Total

Los modelos de decisión en Ollama son una herramienta separada y más limitada que los LLM normales. No reemplazan a los modelos generativos, pero eliminan la parte rutinaria del trabajo: respuestas escritas, probabilidades en lugar de análisis de texto y un formato predecible. Si ya tiene un canal de clasificación, la transición se reduce a verificar las capacidades del modelo, una estrategia de llamadas separada y preguntas breves de instrucción.

Fuentes
https://ollama.com/blog/ollama-now-supports-jev-style-decision-models
https://ollama.com/library/nimble
https://ollama.com/library/tev1
https://typesafe.ai

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

DemensDeum
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.