Nev-0.8B

Nev is a 0.8B decision model that picks the next browser action for one step of a web task. It reads the page as a numbered list of elements, the step's instruction, and the actions taken so far. It then returns a probability for every allowed answer to four typed questions: is the step done, which operation comes next, which element it acts on, and which input value goes in a field. It answers in one forward pass. There is no free-form text generation and no output parsing.

Nev runs on a laptop. On an Apple M5 it answers a browser step in about half a second through MLX.

Nev is a fine-tune of Kev-0.8B, which is a LoRA adapter and a pointer head on Qwen/Qwen3.5-0.8B-Base. It serves the System One API (POST /v1/systemone) through Kev's server. It was built for Contingency, a tool that runs and checks taught browser journeys. Nev is not affiliated with TypeSafe.

Model

  • Backbone: Qwen/Qwen3.5-0.8B-Base (24 layers: 18 Gated DeltaNet and 6 full attention), frozen.
  • Adapter: LoRA, rank 16, alpha 32, on the attention, MLP, and DeltaNet projections of every layer (11.3M parameters).
  • Head: Kev's pointer head. It scores each option's closing token against the question's final token. A softmax per question gives the probabilities.
  • Calibration: one temperature (1.231), stored in head.pt and applied when the model loads. On held-out sites, Nev was wrong with 90% or more confidence on 0.3% of its answers.

Files

File Purpose
adapter_model.safetensors, adapter_config.json LoRA adapter for Qwen3.5-0.8B-Base
head.pt Pointer head, temperature, and training metadata
tokenizer.json, tokenizer_config.json, chat_template.jinja Tokenizer with Kev's delimiter tokens
training_config.json, training_metrics.json Training arguments and run metrics
LICENSE Apache-2.0 license

The base model downloads separately from Qwen/Qwen3.5-0.8B-Base the first time Nev loads.

Usage

Nev runs with the Kev server. You need Python 3.12 or 3.13 and uv.

git clone https://github.com/jaredpalmer/kev.git && cd kev
uv sync --extra serve
uv run --extra serve python -m kev.serve --run akshat-OwO/nev-0.8b --port 8009

The server picks MLX on Apple Silicon and CUDA on an NVIDIA GPU. Any 4 GB GPU is enough.

A browser step

Send the page and the step. Element indexes are the option names, so Nev can only choose an element that is on the page. Input values stay in your code: Nev picks which input name goes in a field, and never writes the value itself.

curl -s localhost:8009/v1/systemone -H 'content-type: application/json' -d @step.json

step.json:

{
  "model": "nev",
  "state": {
    "elements": [
      {
        "index": "1",
        "role": "combobox",
        "name": "City"
      },
      {
        "index": "2",
        "role": "button",
        "name": "Save location"
      },
      {
        "index": "3",
        "role": "button",
        "name": "Add Trail Hammer to cart"
      }
    ],
    "page": {
      "content": [
        "heading: Delivery location",
        "status: Delivering to: No delivery location chosen"
      ],
      "title": "Shop",
      "url": "https://shop.example/"
    },
    "recent_actions": []
  },
  "questions": {
    "done": {
      "criteria": {
        "false": "The page does not show this yet, or shows something else.",
        "true": "The page visibly shows exactly this outcome now."
      },
      "instructions": {
        "condition": "The status line reads \"Delivering to: Boulder\".",
        "question": "Does the current `page` satisfy `condition`?"
      },
      "type": "noul"
    },
    "operation": {
      "criteria": {
        "SELECT": "Choose one of the provided input values in a dropdown list.",
        "CLICK": "Click a button, link, checkbox, tab, or other control.",
        "BLOCKED": "No listed element can make progress on the step."
      },
      "instructions": {
        "question": "Which operation is the single next action toward `step`? Do not repeat an action in `recent_actions` that already took effect.",
        "step": "Choose Boulder in the City list, then select Save location."
      },
      "type": "choice"
    },
    "select_target": {
      "criteria": {
        "1": "[1] combobox \"City\""
      },
      "instructions": {
        "question": "If the next action is SELECT, which target does `step` call for?",
        "step": "Choose Boulder in the City list, then select Save location."
      },
      "type": "choice"
    },
    "value_1": {
      "criteria": {
        "city": "Boulder",
        "product": "Trail Hammer"
      },
      "instructions": {
        "question": "Which input value does `step` put in [1] combobox \"City\"?",
        "step": "Choose Boulder in the City list, then select Save location."
      },
      "type": "choice"
    },
    "click_target": {
      "criteria": {
        "2": "[2] button \"Save location\"",
        "3": "[3] button \"Add Trail Hammer to cart\""
      },
      "instructions": {
        "question": "If the next action is CLICK, which target does `step` call for?",
        "step": "Choose Boulder in the City list, then select Save location."
      },
      "type": "choice"
    }
  }
}

Ask the questions with this exact wording: it is the wording Nev was trained on. Each choice answer has choice, confidence, and probabilities. A noul answer has the probability of true. For this page Nev answers done false, operation SELECT, select_target 1, and value_1 city.

Loop rules that matter

  • Treat a step with no action yet as finished only at a high done probability. A literal reading of a condition can be true before the step's work is done, for example a search box that is visible before its city is chosen. Contingency uses 0.9 before a step's first action and 0.5 after it.
  • Send at most about 150 elements. Nev trained on pages of that size. Trim long pages to interactive elements and the visible region first.
  • Hand back on BLOCKED or low confidence. Nev is the fast path. A larger agent should judge outcomes, recover from errors, and check that something is gone.

Input format

Field Description
state.page url, title, and content: visible text as role: text lines
state.elements Interactive elements: index, role, name, and optional value, checked, within
state.recent_actions Earlier actions in this run, newest last, such as FILL [6] textbox "Search" ← "Sector 14" → effect: dom
questions Typed questions, as in the System One API: noul, choice, or score

Nev answers any System One request, not only browser steps. See Kev's documentation for the full API.

Results

"Steps fully right" means the operation and the target element are both correct. "Explicit steps" name the element, as a written procedure does. "Goal only" gives just the task, so the model must plan the next step itself. Every test set uses websites, or whole domains, that never appear in training. The best value in each row is in bold.

Test set Nev-0.8B Kev-0.8B Laya
Mind2Web, unseen websites, explicit steps 91.0 6.7 2.7
Mind2Web, unseen domains, explicit steps 92.3 6.8 5.7
Mind2Web, unseen websites, goal only 39.7 0.0 2.0
Mind2Web, unseen domains, goal only 34.0 1.0 –
Held-out crawl and WebChain sites, with done checks 76.9 – 19.7
Kev's general decision set (not browser) 82.3 83.3 –

Each browser row scores 287 to 400 steps, sampled with a fixed seed. Laya shows its better result of the English model at 512 tokens and the multilingual model at 8,192 tokens. Most browser requests are 2,000 to 5,000 tokens with up to 120 options, which is outside the setting Laya was trained for.

On Kev's general decision set (491 questions), Nev scores within the noise of Kev-0.8B (standard error about 1.7 points). The fine-tune kept Kev's general skills because it mixed in 1,000 of Kev's own training records.

The held-out test set is published as akshat-OwO/nev-bench, with the IDs of the scored Mind2Web steps and the scripts that rebuild every number.

Speed

Hardware Time per browser step
Apple M5, MLX, bf16 about 0.35 to 0.6 s for 1,500 to 3,000-token requests

Limits

  • Planning from a goal alone is weak. Nev is built for explicit steps. Given only the task, it gets about a third of steps fully right.
  • Checking that something is gone is unreliable. Leave conditions such as "the banner is gone" to a larger model.
  • Pages above about 150 elements cost time and accuracy. Trim them first.
  • Languages: trained mostly on English pages, with some Chinese. Other languages are not measured.
  • Images: Nev reads text only.

Training

Start Kev-0.8B (Hub revision bf75a6a), adapter and head
Data 9,000 browser steps and 1,000 Kev records (below)
Recipe 1 epoch, learning rate 2e-5, batch 4, gradient accumulation 2, states up to 8,192 tokens, shared state prefix
Hardware One H100, about 1 h 40 min
Calibration Temperature fitted on 332 held-out records

Training data:

  • Mind2Web (CC BY 4.0): 3,500 steps from its training split. Deng et al., Mind2Web: Towards a Generalist Agent for the Web, NeurIPS 2023.
  • WebChain (CC BY 4.0): 3,000 steps from human trajectories on 239 sites. 26 more sites were held out for testing.
  • Contingency crawl: 2,500 generated steps on 111 public sites, captured with Contingency's own browser snapshots.
  • Kev public suite: 1,000 records from Kev's training set, so general skills are kept.

Each step became a request in the input format above. Explicit instructions were written from the recorded action. Goal-only instructions use the task text. The labels are the recorded operation, element, and value.

License

The adapter and head are released under Apache-2.0, as are Kev-0.8B and Qwen3.5-0.8B-Base. The training data includes Mind2Web and WebChain, both under CC BY 4.0. Credit them when you use or redistribute work derived from Nev.

Downloads last month
37
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for akshat-OwO/nev-0.8b

Finetuned
(4)
this model

Datasets used to train akshat-OwO/nev-0.8b