Skip to content

Tutorial 7 · Set up a model before you test it

An arm is a model and how it is called. A server chooses for everything an arm leaves unset: whether the model reasons before it answers, how long a reply may run, which build of the weights a tag names. Those defaults differ from model to model, so an arm that leaves them unset compares the defaults as much as the models. This tutorial sets a model up once, in a model record, checks it where it runs, then smokes an arm on a few items before its full run. The design is RFC-020; every command is in the RUNBOOK §16.

It runs on your own machine, at no cost, with Ollama and a small model:

ollama pull llama3.1:8b

Start from the project the GUIDE leaves (the tickets frozen and materialized). A server on this machine, or on Ollama's port anywhere, needs no key: the harness asks for OPENAI_API_KEY only for another address.

1 · A record for the model

One file per model, in data/models/. It says what the model is, and lists its deployments: each place and build it runs, here one, on this laptop.

# data/models/llama3.1-8b.yaml
model_id: llama3.1-8b
kind: llm
name: Llama 3.1 8B
aliases:
- llama3.1:8b          # the names runs record for it
weights: open
licence: Llama 3.1 Community License
deployments:
- id: laptop           # an arm names it with `deployment:`
  where: laptop
  tag: llama3.1:8b
  endpoint:
    provider: openai   # Ollama speaks the OpenAI API
    base_url: http://127.0.0.1:11434/v1
    model: llama3.1:8b

A model that runs in several places (a laptop, a GPU server, a hosted route) gets one deployment each, because the same tag can be a different build on each, and each is checked on its own.

2 · Onboard it

evh model-onboard llama3.1-8b --deployment laptop
model-onboard: llama3.1-8b (llm)
  build: the server reports 46e0c10c039e, the record None
  default settings: 2.86 s, 19 tokens out, reasoned: False, end stop
  record's settings (none): 0.46 s, 19 tokens out, reasoned: False, end stop
  JSON valid: True  deterministic: True  tokens/s: 41.5
ONBOARD PASS
  written into data/models/llama3.1-8b.yaml (deployment laptop)

It called the deployment the way an arm would and wrote what it found into the record: the digest of the build the server is serving (so a later run can tell when it changed), whether the model reasoned at the server's default and with the record's settings, whether it returns valid JSON, whether the same question twice gives the same answer, and its speed. Your digest and timings will differ.

Llama 3.1 does not reason first, so it needs no settings. A model that does (gpt-oss, Gemma 4, Qwen 3) is set in the record, with why, and onboarded again:

settings:
  reasoning_effort: none
settings_why:
  reasoning_effort: it reasoned by default on the onboarding probe; off unless a task needs it

What a model cannot change (gpt-oss reasons at every setting; low is the least it takes) is accepted, with why, so it is reported and passes rather than failing every check: accepted: {reasoning: "<why>"}, on the record, or on one deployment for what only that one raises (a hosted gateway has no build to pin).

3 · An arm that names it

# data/configs/tickets_llama.yaml
config_id: tickets_llama_v1
dataset_id: tickets_v1
model_record: llama3.1-8b
deployment: laptop
params:
  provider: openai
  model: llama3.1:8b
  base_url: http://127.0.0.1:11434/v1
  prompt: "Summarise this support ticket in one or two sentences."
  max_tokens: 200          # a summary is two sentences; 200 bounds a runaway

The record supplies the model's own settings; the arm adds the task's (its reply cap, its call limit), with a comment saying why. A record refuses those: they would reach every other eval's arms. Commit the record and the arm before running, so the run records a clean tree:

git add -A && git commit -qm "llama3.1-8b, set up; an arm that names it"

4 · Smoke it

evh arm-smoke --config data/configs/tickets_llama.yaml
arm-smoke: tickets_llama_v1 on tickets_v1, 3 item(s)
  settings: {'model': 'llama3.1:8b', 'max_tokens': 200}  · model record llama3.1-8b
  t01_login                                           2.14 s  out    381 ch  1 call(s)
      call    2.1 s  out    77 tok  reasoning      0  end stop
  ...  (t02_invoice, t03_export the same way)
  full run: 6 items, about 0.2 min (slowest item x all: 0.2 min), about $0.0
  determinism: item 1 twice gave the same output: repeats on this machine will be identical
SMOKE PASS
  written into data/models/llama3.1-8b.yaml

Three items, the arm's own settings, no run written: each item's time and output, whether the scorer can read it, a projection of the full run, and every model call (tokens out, whether it reasoned, how it ended). A SMOKE CHECK lists what to look at first:

flag means usually
reasoning a call reasoned and the arm sets no reasoning_effort set it in the record
cut off a reply hit max_tokens raise the cap (a reasoning model counts its thinking)
no answer a call failed or came back empty the server, the model's format, or a call limit too short
long reply past half the reply cap (with no cap, far past the arm's usual reply) a cap too tight, or a model that rambles
slow call over half its time limit raise call_timeout_s, or a smaller model
determinism the same item twice gave different outputs expected for a hosted model; repeats will vary

A passed smoke makes the model vetted: onboarded, and shown to work on a task's own items.

5 · Run it, and see it

evh run --config data/configs/tickets_llama.yaml
evh models
  model        kind  where        weights  build                     deployments  settings  onboarding       arms
  llama3.1-8b  llm   self-hosted  open     llama3.1:8b@46e0c10c039e  laptop       defaults  pass 2026-10-31  1

The run's fingerprint takes the weights, the server and where it ran from the record's deployment, so two runs of this arm on different builds cannot pass for one measurement. evh models --model llama3.1-8b prints the record in full: each deployment, its onboarding, the settings' history, and the arms that use it. The catalog shows the same on its Models page and a page per model (evh catalog, then tutorial 5).