wazn-2b-v0.1
Wazn is a decision model: given a context, optional rules and an instruction, it returns a probability distribution over a set of labels you supply, each with an optional definition and few-shot examples. Nothing is generated. The label set is yours, per request, with no retraining: two labels or a thousand. Large sets (hundreds to 1,000+ classes) are handled by tournaments.
Beta. For trying the model out, not for production. Requests run one at a time, and the API may change between
0.xreleases.
Code, full docs and examples: github.com/numid-ai/wazn-experimental.
How it works

- Encode each candidate. The rules, context and instruction are followed by one
candidate label (its definition and examples), closed by a
</choice>tag. The frozen Qwen3.5-2B backbone, with LoRA adapters, reads this sequence, and the hidden state at</choice>is projected into a representation of that candidate. - Compare the candidates. A relational judge compares the candidate representations against each other, rather than scoring each label alone, and outputs a probability for each one.
- Check that any label fits. A NONE gate estimates the probability that at least one candidate is valid. Below a threshold the answer is NONE; otherwise it is the most likely candidate.
Use
Python 3.11+. Install the wazn-experimental
package in a virtual environment, then start a local server with this checkpoint:
python -m venv .venv && source .venv/bin/activate
pip install --pre "wazn-experimental[server]"
wazn-experimental serve --model numidlabs/wazn-2b-v0.1
# serving on http://127.0.0.1:8000
[server]installs PyTorch (a large download). On Linux with an NVIDIA GPU, use"wazn-experimental[server,cuda]"for the fast kernels.- Besides a server,
Wazn.load()runs the model in process (e.g. in a notebook).
Then query it from Python:
from wazn_experimental import Client, Request, Instruction, Label
request = Request(
context="My running shoes arrived in the wrong size. Can I swap them?",
instructions=[Instruction(
"Which team should handle this?",
labels=[Label("returns", "Exchanges, refunds, wrong or damaged items"),
Label("shipping", "Delivery status, delays, lost packages"),
Label("billing", "Charges, invoices, payment problems")],
)],
)
answer = Client().predict(request).answer
print(answer.choice, answer.confidence) # e.g. returns 0.93
print(answer.probabilities) # distribution over the labels, sums to 1
print(answer.none_probability) # P(none of the labels applies)
For more than a few dozen labels, give the instruction a tournament=Tournament(group_size=10, top_k=2). See the README.
Speed
| Config | Instructions × labels | Input tokens (context / instructions / labels) | Median | p90 |
|---|---|---|---|---|
| Normal context, few labels | 1 × 5 | 105 (60 / 13 / 32) | 35 ms | 37 ms |
| Short query, banking77 intents (snake_case names)¹ | 1 × 77 (tournament, groups of 10, top 2) | ~492 (~17 / 12 / 463) | 48 ms | 50 ms |
| Normal context, many labels, all at once | 1 × 219 | 1,052 (60 / 13 / 979) | 121 ms | 122 ms |
| Normal context, many labels | 1 × 219 (tournament, groups of 10, top 2) | 1,052 (60 / 13 / 979) | 86 ms | 87 ms |
| Normal context, very many labels (random names) | 1 × 1,000 (tournament, groups of 10, top 2) | 5,483 (60 / 13 / 5,410) | 317 ms | 319 ms |
| Long context (NDA, ContractNLI) | 1 × 10 | 6,485 (6,317 / 14 / 154) | 152 ms | 153 ms |
| Normal context, many instructions (incident report) | 10 × 4 | 1,621 (648 / 189 / 784) | 154 ms | 156 ms |
On an NVIDIA RTX 5090, bfloat16, [server,cuda]. Server-side time over 10 requests sent one
after another, after a warm-up request; no input was truncated. The first request after a
start is slower, because it compiles the GPU kernels. Without [cuda], or on Apple Silicon
or CPU, expect much slower requests; see the
README.
¹ 50 different banking77 test queries, one request each, rather than one request repeated; tokens are medians (queries run 9 to 30 tokens).
Limitations
TODO: known weak spots, training data summary, evaluation results.
License
The head weights are released under Apache-2.0. The backbone keeps its own
license; see Qwen/Qwen3.5-2B-Base.