Modelos de solução Jev em Ollama: uso prático /v1/systemone

Written by

in

A partir da versão 0.35, Ollama suporta modelos de decisão construídos na API Jev do TypeSafe. Estes não são modelos de chat no sentido usual: eles não escrevem texto, mas respondem a um conjunto de perguntas digitadas sobre o estado transferido. Para classificação, roteamento, moderação e triagem, isso acaba sendo mais rápido e confiável do que pedir a um LLM normal que retorne JSON e depois analise sua resposta.

Nesta postagem, veremos o que são modelos de decisão, como funcionam no nível HTTP, quais modelos já estão disponíveis e como construí-los no código existente para que os modelos generativos regulares continuem a funcionar.

Como os modelos de decisão diferem dos modelos normais

Um LLM regular recebe um prompt e gera texto token por token. Mesmo que você peça que ela responda em uma palavra, a geração ainda ocorre internamente, e o formato da resposta deve ser controlado por diagrama, instruções e posterior verificação. O modelo de Decisão funciona de maneira diferente: você passa estados e questões com tipos, e o modelo retorna probabilidades e opções selecionadas. Sem texto livre, sem análise de JSON da resposta.

O novo endpoint é chamado /v1/systemone. Em uma solicitação, você pode fazer várias perguntas ao mesmo tempo, e o modelo responderá a todas elas. Isso é conveniente para tarefas em que você precisa tomar diversas decisões relacionadas: por exemplo, determinar a equipe, a necessidade de retorno e a urgência do ticket.

Quais modelos estão disponíveis

Agora você pode executar três modelos de decisão por meio do Ollama:

  • nimble é um modelo aberto com 9 bilhões de parâmetros do Bespoke Labs. É o maior e mais preciso disponível.
  • tev1 é um modelo experimental com 4 bilhões de parâmetros da Together AI.
  • tev1:0.8b é um modelo experimental com 0,8 bilhão de parâmetros do Together AI. O mais rápido e fácil.

Todos trabalham localmente, não exigem pagamento e não enviam dados para serviço externo. Ollama 0.35 e posteriores são suportados.

Instalação

Primeiro verifique a versão do Ollama:

ollama --version

Em seguida, baixe o modelo desejado. Para o mais fácil:

ollama pull tev1:0.8b

Para a versão completa do tev1:

ollama pull tev1

Para ágil:

ollama pull nimble

O modelo ágil ocupa cerca de 9,5 GB de espaço em disco, por isso é uma boa ideia liberar espaço antes de fazer o download. tev1:0.8b ocupa menos de um gigabyte.

Primeira solicitação via curl

O exemplo mais simples é determinar se um texto é um anúncio de emprego:

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?"
    }
  }
}'

A resposta é assim:

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

O campo noul é uma probabilidade de 0 a 1. A decisão é tomada por comparação com um limite, geralmente 0,5. Ao contrário do modelo generativo, não há necessidade de solicitar uma resposta no formato JSON e depois verificar se o modelo não a quebrou.

Tipos de perguntas

Os modelos de decisão suportam três tipos de perguntas.

noul é uma questão binária. Retorna a probabilidade de uma afirmação ser verdadeira:

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

escolha – selecionar uma opção de um determinado conjunto. Retorna a opção selecionada, as probabilidades de todas as opções e a confiança:

{
  "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"
      }
    }
  }
}

pontuação – classificação em uma escala. Retorna o número, a legenda e as probabilidades de cada ponto da escala:

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

Uma solicitação pode conter várias perguntas de diferentes tipos ao mesmo tempo. É isto que torna os modelos de decisão convenientes para a triagem: uma operação, um estado, várias decisões independentes.

Python sem bibliotecas adicionais

Para solicitações, o urllib padrão é suficiente; um SDK separado não é necessário:

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

Se você precisar de um SDK oficial do Python, ele será chamado typesafe-sdk. Para localhost, pode ser direcionado para Ollama com as variáveis ​​de ambiente TYPESAFE_BASE_URL, TYPESAFE_API_KEY e TYPESAFE_DEFAULT_MODEL. Mas para tarefas simples, uma solicitação HTTP direta é suficiente.

Como entender que um modelo apoia a decisão

Os modelos de decisão não podem responder via /api/generate ou /api/chat. Se você enviar tal solicitação, Ollama retornará um erro 400 com um texto como:

"tev1:0.8b" does not support generate

Isso é importante se você já possui código que funciona com modelos regulares via /api/generate: se você alterar o modelo para um modelo de decisão, ele irá parar de funcionar. É melhor descobrir antecipadamente os recursos do modelo via /api/show e escolher o método de chamada apropriado:

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

Os modelos de decisão terão apenas decisão em suas capacidades. Os modelos regulares terão acabamento, ferramentas ou outros recursos. Se Ollama não estiver disponível, é razoável considerar o modelo normal e utilizar o caminho generativo.

Como incorporar em código existente

A maneira mais simples não é reescrever o classificador, mas sim dividi-lo em duas estratégias. A estratégia generativa funciona como antes: ela coleta o prompt, envia-o para /api/generate e analisa o JSON. A estratégia de decisão envia o estado e a pergunta digitada para /v1/systemone e compara a probabilidade com um limite.

A escolha da estratégia ocorre em um só lugar, ao criar um classificador:

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

Esta abordagem tem várias vantagens. Os modelos generativos continuam a funcionar inalterados. O modelo de decisão pode ser ativado alterando uma variável de ambiente. E toda a diferença entre os dois métodos está concentrada em duas pequenas classes, e não está espalhada por toda a aplicação.

Para uma classificação binária, a estratégia de decisão é mais ou menos assim:

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

Observe que o modelo de decisão não retorna uma explicação. Se o seu formato de resultado tiver um campo de razão, você poderá construí-lo a partir da probabilidade: por exemplo, armazene a própria probabilidade ou uma string como “o modelo classificou a mensagem em 0,935 como uma vaga”. Isto é mais honesto do que inventar uma razão que o modelo não deu.

As instruções devem ser uma pergunta

Esta é a conclusão prática mais importante. Os modelos de decisão não entendem prompts longos no estilo “você classifica as mensagens, responda verdadeiro se…, falso caso contrário”. Eles querem uma pergunta curta e direta.

Na mesma mensagem sobre uma vaga, recebi as seguintes probabilidades:

  • Pergunta direta “Esta mensagem é um anúncio de emprego?” — 0,921.
  • Instruções longas explicando o que é considerado uma vaga – 0,026.
  • Instruções longas com uma pergunta no final – 0,391.

A diferença é de quase trinta vezes. O modelo não se engana na classificação, simplesmente não entende o que querem dele quando a questão está escondida dentro de um parágrafo. Portanto, para modelos de decisão vale a pena manter instruções curtas separadas e deixar prompts longos para modelos generativos.

É conveniente criar uma variável de ambiente separada:

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

E use um prompt regular apenas para o caminho gerador.

Limite e probabilidades

O limite de 0,5 é adequado como valor padrão, mas é útil incluí-lo na configuração. Para tarefas diferentes, o custo de uma resposta falso positiva e falsa negativa é diferente. Para moderação, é mais seguro aumentar o limite; para a busca de vagas é mais seguro baixá-la, para não perder mensagens úteis.

Também é útil registrar a probabilidade em si, e não apenas o booleano resultante. Quando o classificador comete um erro, o log mostra se foi uma resposta segura ou uma decisão na fronteira. Para questões de escolha, vale guardar as probabilidades e a confiança: elas mostram o quanto o modelo oscila entre as opções.

Desempenho e memória

A velocidade depende muito do tamanho do modelo e do hardware. Na CPU em meus testes obtive os seguintes números:

  • tev1:0.8b – fração de segundos para resolver, cabe facilmente na memória.
  • tev1 – 4B, visivelmente mais lento, mas ainda adequado para tarefas interativas.
  • ágil – 9B em Q8_0, cerca de 10 GB de memória. A primeira solicitação, incluindo o carregamento do modelo, levou cerca de 137 segundos, as soluções subsequentes levaram de 12 a 32 segundos na CPU.

Nimble requer muita RAM. Em uma máquina com 16 GB e Docker/WSL com limite de cerca de 8 GB, o modelo não cabe: o sistema começa a trocar e os containers param de responder. Aumentar o limite WSL para 12 GB por meio do arquivo .wslconfig ajudou:

[wsl2]
memory=12GB
swap=8GB

Após a alteração, você precisa de wsl –shutdown e reinicie o Docker Desktop. Mas mesmo com 12 GB, a reserva continua pequena: o modelo ocupa cerca de 10 GB e não sobra muito para o sistema.

Por padrão, o Ollama descarrega o modelo após cinco minutos de inatividade, liberando memória. Isso é conveniente: o ágil não mantém 10 GB ocupados o tempo todo, mas cada novo lançamento após uma pausa começa a carregar o modelo novamente.

Quando usar modelos de decisão

Os modelos de decisão são adequados para tarefas em que você precisa de uma resposta rápida e barata para uma pergunta claramente formulada:

  • Classificação de mensagens, tickets e solicitações.
  • Roteamento por comandos ou executores.
  • Moderação de conteúdo e verificações de segurança.
  • Soluções binárias e multivariadas rápidas em jogos ou aplicativos interativos.

Eles são pouco adequados para tarefas onde é necessário texto detalhado: explicação, extração de campos, resumo, geração de respostas. Para este efeito, permanecem os modelos generativos habituais. O melhor resultado é obtido quando combinados: um modelo de decisão toma uma decisão e um modelo generativo a explica ou extrai dados.

Total

Os modelos de decisão no Ollama são uma ferramenta separada e mais restrita do que os LLMs regulares. Eles não substituem os modelos generativos, mas eliminam a parte rotineira do trabalho: respostas digitadas, probabilidades em vez de análise de texto e um formato previsível. Se você já possui um pipeline de classificação, a transição se resume à verificação dos recursos do modelo, uma estratégia de chamada separada e perguntas instrucionais curtas.

Fontes
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.