nassimjp
/

nassimjp Abhinav-jigsawstack commited on
Commit
ea5d33e
·
0 Parent(s):

Duplicate from interfaze-ai/lev

Browse files

Co-authored-by: Abhinav <Abhinav-jigsawstack@users.noreply.huggingface.co>

.gitattributes ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/leaderboard.png filter=lfs diff=lfs merge=lfs -text
37
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
38
+ assets/accuracy-per-parameter.png filter=lfs diff=lfs merge=lfs -text
39
+ assets/hero.png filter=lfs diff=lfs merge=lfs -text
40
+ assets/accuracy-by-subset.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: Qwen/Qwen3.5-4B
4
+ base_model_relation: adapter
5
+ library_name: peft
6
+ pipeline_tag: zero-shot-classification
7
+ inference: false
8
+ language:
9
+ - en
10
+ tags:
11
+ - lev
12
+ - system-one
13
+ - decision-model
14
+ - calibrated-decisions
15
+ - classification
16
+ - routing
17
+ - moderation
18
+ - lora
19
+ ---
20
+
21
+ <p align="center">
22
+ <img src="assets/hero.png" alt="lev: one state, many typed decisions, one forward pass" width="100%">
23
+ </p>
24
+
25
+ lev answers typed questions about a piece of context in a single forward pass. You give it a **state** (text, a ticket, an email, or JSON) and a set of yes/no, choice, and score questions. It reads each answer from the logits it already computed and returns calibrated probabilities over exactly the options you supplied. It is a LoRA adapter on Qwen3.5-4B, and it speaks TypeSafe's `/v1/systemone` protocol, so code written for the TypeSafe SDK works against it once you change the base URL.
26
+
27
+ <div align="center" style="line-height: 1;"><img src="https://img.shields.io/badge/license-Apache--2.0-2a78d6?style=flat-square" alt="Apache-2.0" style="display: inline-block; vertical-align: middle; margin: 2px;"> <img src="https://img.shields.io/badge/base-Qwen3.5--4B-2a78d6?style=flat-square" alt="Qwen3.5-4B" style="display: inline-block; vertical-align: middle; margin: 2px;"> <img src="https://img.shields.io/badge/output%20tokens-0-2a78d6?style=flat-square" alt="Zero output tokens" style="display: inline-block; vertical-align: middle; margin: 2px;"> <img src="https://img.shields.io/badge/API-%2Fv1%2Fsystemone-2a78d6?style=flat-square" alt="/v1/systemone compatible" style="display: inline-block; vertical-align: middle; margin: 2px;"> <a href="https://github.com/Abhinavexists/lev"><img src="https://img.shields.io/badge/code-GitHub-14181f?style=flat-square&logo=github" alt="GitHub" style="display: inline-block; vertical-align: middle; margin: 2px;"></a> <a href="https://interfaze.ai/blog/jev-now-open-source-lev"><img src="https://img.shields.io/badge/Blog-lev-yellow" alt="Blog" style="display: inline-block; vertical-align: middle; margin: 2px;"></a> <a href="https://interfaze.ai"><img src="https://img.shields.io/badge/Built_by-Interfaze--ai-4C1" alt="interfaze" style="display: inline-block; vertical-align: middle; margin: 2px;"></a></div>
28
+
29
+ <h2 align="center">68.9% on all 13 S1Bench subsets. 4B parameters. Zero output tokens.</h2>
30
+
31
+ <p align="center"><strong>Qwen3.5-4B + LoRA on one H100.</strong> On the six subsets the public S1Bench board completed, level with reflex-4b and behind only Jev and three open models of 26B–35B.</p>
32
+
33
+ <p align="center"><a href="#quickstart"><strong>Quickstart</strong></a> · <a href="#self-hosting-a-jev-compatible-http-server">Self-hosting</a> · <a href="#benchmarks">Benchmarks</a> · <a href="#speed">Speed</a> · <a href="#why-it-works">Why it works</a> · <a href="#training">Training</a> · <a href="#boundaries-worth-understanding">Boundaries</a> · <a href="https://github.com/Abhinavexists/lev">GitHub</a></p>
34
+
35
+ **No generated tokens, no JSON to parse, no retries.** lev cannot return a label outside your options, because the answer space is the option set you send. It can still pick the wrong option: the guarantee is structural, not a guarantee of correctness.
36
+
37
+ | Question | You give | You get |
38
+ | --- | --- | --- |
39
+ | `noul` | a yes/no question | `noul` = p(yes) |
40
+ | `choice` | instructions + options (name → description or `null`) | `choice`, `probabilities`, `confidence` |
41
+ | `score` | instructions + 2–10 ordered levels | `score` (expected level), `probabilities`, `confidence` |
42
+
43
+ It is built for the high-volume judgement calls inside a product: routing, moderation, intent detection, triage, grading, and checking LLM output.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install "lev[serve] @ git+https://github.com/Abhinavexists/lev#subdirectory=packages/lev"
49
+ ```
50
+
51
+ This needs Python 3.12 or newer and, for real-time use, a CUDA GPU. The `serve` extra installs torch, transformers, peft, and the HTTP server. The first load downloads the base model (Qwen/Qwen3.5-4B, about 8 GB) and this adapter (about 200 MB).
52
+
53
+ ## Quickstart
54
+
55
+ ```python
56
+ import lev
57
+
58
+ model = lev.load("interfaze-ai/lev")
59
+
60
+ state = "Hi, I was charged twice for my order #4471 and I want a refund."
61
+ questions = {
62
+ "intent": {
63
+ "type": "choice",
64
+ "instructions": "What does the customer want?",
65
+ "criteria": {
66
+ "refund": "wants money back",
67
+ "cancel": "wants to cancel an order",
68
+ "track": "wants to know where an order is",
69
+ "other": "anything else",
70
+ },
71
+ },
72
+ "urgent": {"type": "noul", "instructions": "Does this need a human within the hour?"},
73
+ "frustration": {
74
+ "type": "score",
75
+ "instructions": "How frustrated is the customer?",
76
+ "criteria": ["calm", "mildly annoyed", "annoyed", "angry"],
77
+ },
78
+ }
79
+
80
+ result = model.system_one(state, questions)
81
+ print(result.answers["intent"].choice) # refund
82
+ print(result.answers["intent"].probabilities)
83
+ # {'refund': 0.84, 'cancel': 0.094, 'track': 0.012, 'other': 0.054}
84
+ print(result.answers["urgent"].noul) # 0.43
85
+ print(result.answers["frustration"].score) # 1.57, between "mildly annoyed" and "annoyed"
86
+ print(result.usage.output_tokens) # 0
87
+ ```
88
+
89
+ These are real outputs from this checkpoint. The answers are objects, and `result.model_dump()` gives the same JSON the HTTP server returns.
90
+
91
+ All the questions share one forward pass, so asking three questions costs about the same as asking one. `lev.load` reads `lev_release.json` from this repository to find the base model and the prompt format the adapter was trained with. It also applies the shipped calibration and loads the matching head, so there is nothing to configure.
92
+
93
+ Because the probabilities are calibrated, you can gate on them. For example, act automatically above 0.9 and send anything lower to a person.
94
+
95
+ ## Self-hosting: a Jev-compatible HTTP server
96
+
97
+ ```bash
98
+ lev serve --checkpoint interfaze-ai/lev --host 0.0.0.0 --port 8000
99
+ ```
100
+
101
+ ```bash
102
+ curl -s localhost:8000/v1/systemone -H 'content-type: application/json' -d '{
103
+ "state": "The package arrived crushed and the screen is cracked.",
104
+ "questions": {"damaged": {"type": "noul", "instructions": "Was the item damaged?"}}
105
+ }'
106
+ ```
107
+
108
+ Existing TypeSafe clients work once you point them at the server:
109
+
110
+ ```python
111
+ from typesafe_sdk import Choice, Noul, TypeSafeClient
112
+
113
+ # The first request after startup compiles kernels; allow more than the default 10 s.
114
+ client = TypeSafeClient(base_url="http://localhost:8000", api_key="local", timeout=60)
115
+ response = client.system_one(
116
+ state={"ticket": "The app crashes every time I open settings."},
117
+ questions={
118
+ "team": Choice(
119
+ instructions="Which team owns this?",
120
+ criteria={"billing": "payments, refunds", "technical": "bugs, crashes", "other": None},
121
+ ),
122
+ "bug": Noul(instructions="Is this a bug report?"),
123
+ },
124
+ )
125
+ print(response.answers["team"].choice, response.answers["bug"].noul) # technical 0.92
126
+ ```
127
+
128
+ `GET /health` reports the loaded checkpoint, whether calibration is active, and the routing settings. The server batches every question in a request into one forward pass, accepts concurrent requests, and returns 422 with the reason for a malformed question.
129
+
130
+ ## Benchmarks
131
+
132
+ ### S1Bench
133
+
134
+ <p align="center"><img src="assets/accuracy-by-subset.png" alt="lev and Jev accuracy on each S1Bench subset" width="100%"></p>
135
+
136
+ | subset | task | **lev** | Jev | always the most common label |
137
+ | --- | --- | --: | --: | --: |
138
+ | vitaminc-dev | claim verification | 0.668 | **0.801** | 0.503 |
139
+ | massive-en-US | intent routing, 18 scenarios | 0.857 | **0.874** | 0.163 |
140
+ | massive-de-DE | intent routing, German | 0.823 | **0.871** | 0.163 |
141
+ | boolq | yes/no reading comprehension | 0.827 | **0.893** | 0.580 |
142
+ | squad2 | answerability | 0.813 | **0.836** | 0.502 |
143
+ | paws | adversarial paraphrase | 0.776 | **0.900** | 0.516 |
144
+ | multinli | natural language inference | **0.890** | 0.836 | 0.361 |
145
+ | civil_comments | toxicity | 0.760 | **0.803** | 0.893 |
146
+ | aegis2 | safety moderation | 0.800 | **0.804** | 0.568 |
147
+ | helpsteer2 | helpfulness, 5 levels | **0.386** | 0.341 | 0.422 |
148
+ | summeval-relevance | summary relevance, 5 levels | 0.358 | 0.358 | 0.458 |
149
+ | summeval-consistency | summary faithfulness, 5 levels | 0.271 | **0.812** | 0.840 |
150
+ | pubmedqa | biomedical yes/no/maybe | 0.732 | **0.764** | 0.532 |
151
+ | **macro** | | 0.689 | **0.761** | |
152
+
153
+ lev and TypeSafe Jev ran through the same harness on all 3,880 items S1Bench scores, pinned by [Nimble](https://github.com/bespokelabsai/nimble)'s manifests. Our Jev run lands within 0.8 points of TypeSafe's published figure on every subset, so the harness is not the gap.
154
+
155
+ - **Noise:** at these sizes a per-subset difference needs roughly 5–9 points to be real. lev's leads on multinli and helpsteer2 are inside that.
156
+ - **Where Jev is clearly ahead:** the minimal-edit pairs (paws −12.4, vitaminc −13.3) and summeval-consistency (−54.1), where lev rates most fully faithful summaries one level low. Fine-tuning introduced that: the untuned backbone scores 0.826.
157
+ - **Constant baselines:** on civil_comments (89% not toxic) and the three 5-level rating subsets, always answering the most common label beats both models.
158
+ - **Calibration:** mean ECE 0.115 for lev, 0.091 for Jev; lev is better calibrated on 5 of 13.
159
+
160
+ <p align="center"><img src="assets/leaderboard.png" alt="S1Bench leaderboard over the six subsets every listed model completed" width="100%"></p>
161
+
162
+ <p align="center"><img src="assets/accuracy-per-parameter.png" alt="Macro accuracy against parameter count" width="100%"></p>
163
+
164
+ ### Held-out split
165
+
166
+ A held-out split of the 29 training sources, with no row shared with training:
167
+
168
+ | metric | value |
169
+ | --- | --- |
170
+ | weighted accuracy | 0.807\* |
171
+ | expected calibration error | 0.061\* (0.180 before calibration) |
172
+ | banking77 (77 intents) | 0.980 |
173
+ | clinc_oos (151 intents) | 0.968 |
174
+ | FEVER claim verification | 0.872\* |
175
+
176
+ \* Measured on this checkpoint before the last serving update. That update routes choice sets of more than 68 options to label-token readout and re-selects the temperatures. The banking77 and clinc_oos rows come from after the update, which raised banking77 from 0.818. Smaller option sets are routed the same way as before.
177
+
178
+ ### Speed
179
+
180
+ <p align="center"><img src="assets/compute.png" alt="lev compute per call on one H100: 169 ms to 69 ms" width="100%"></p>
181
+
182
+ A call is one batched forward pass over every question, so compute stays flat from one question to eight, and a 60-option choice costs the same as a yes/no.
183
+
184
+ The 69 ms is engine compute for a short request (a three-sentence state), measured inside the container; S1Bench's longer states take more. End to end from a laptop, Jev's hosted API answered in 335–346 ms median and lev on one Modal H100 in 414–654 ms across two runs.
185
+
186
+ ## Why it works
187
+
188
+ <p align="center"><img src="assets/how-it-works.png" alt="State and questions go through one forward pass, then label-token readout or the candidate-path head, then per-bucket temperatures, then typed answers" width="460"></p>
189
+
190
+ - **Label-token readout.** Each option gets a short code, and the answer is read from the next-token logits over those codes. Codes that would split into two tokens are skipped, so every option stays one token. This handles yes/no, scores, and choice lists up to several hundred options. Choices are read in two option orders and averaged, which cancels position bias.
191
+ - **Candidate-path head.** Past that point, a small learned head matches the state against each option's text, so the number of options has no fixed ceiling.
192
+ - **Calibration.** Temperatures fitted after training are applied at load time. There is one per question type, readout mode, and choice option-count band. They were selected by how well they carry over to task families left out of the fit, not only by how well they fit held-out rows.
193
+
194
+ ### The optimizations that mattered
195
+
196
+ - **One batched forward instead of prefill-and-fork: 169 → 69 ms.** At this size the forward pass is bound by kernel launches, not arithmetic, so forking the cache saved FLOPs and cost time. One batched forward plus the depthwise-conv kernel cut compute by 59%. [ADR-023](https://github.com/Abhinavexists/lev/blob/main/docs/DECISIONS.md#adr-023--one-batched-forward-not-prefill-and-fork)
197
+ - **Label-token readout up to the tokenizer's limit: +51 points on MASSIVE's 60 intents.** Serving 60 options through label codes instead of the learned head took accuracy from 0.231 to 0.746. [ADR-025](https://github.com/Abhinavexists/lev/blob/main/docs/DECISIONS.md#adr-025--serving-routes-mode-a-up-to-the-tokenizer-limit-training-keeps-its-cap)
198
+ - **Skipping codes that split: banking77 0.818 → 0.980.** Passing over codes that tokenize to two tokens lifts label-token readout from 68 options to several hundred. [ADR-028](https://github.com/Abhinavexists/lev/blob/main/docs/DECISIONS.md#adr-028--skip-split-label-codes-when-serving-calibrate-for-families-the-model-has-not-seen)
199
+ - **The backbone's own prompt format: 0.653 → 0.710 frozen.** The untuned instruct model scored 5.7 points higher on the earlier six-subset S1Bench set when questions are dressed in its chat template, so the final run trained in that format. [ADR-027](https://github.com/Abhinavexists/lev/blob/main/docs/DECISIONS.md#adr-027--the-prompt-is-dressed-in-the-backbones-own-format)
200
+
201
+ ## Training
202
+
203
+ - **Data:** 200,000 examples from 29 sources built on 26 public Hugging Face datasets. The tasks cover topic, sentiment, and emotion classification; intent detection (banking77, clinc_oos, snips); NLI (SNLI, ANLI, FEVER); paraphrase (MRPC, QQP, PARADE, plus word-swapped hard negatives); multiple-choice QA (RACE, ARC, SciQ, OpenBookQA, CommonsenseQA, StrategyQA); toxicity and safety (ToxiGen, ToxicChat, BeaverTails); and helpfulness (UltraFeedback). Questions are paraphrased, negated, and recast between types, and option sets are shuffled and resized, so the model learns the question format and not one wording.
204
+ - **Contamination guard:** the data build refuses any source that resolves to one of the 13 S1Bench subsets.
205
+ - **Recipe:** LoRA r=32, α=64 on the q/k/v/o attention and MLP projections; 3 epochs, 18,750 steps, batch size 32, learning rate 5e-5, in the base model's chat format, on one H100 in 7.8 hours.
206
+
207
+ ## Boundaries worth understanding
208
+
209
+ - **Minimal edits and fine-grained ratings are weak.** Inputs that differ by one swapped word or number, and quality ratings over five levels, are where lev is least accurate and can be confidently wrong.
210
+ - **Calibration is fitted on the training distribution.** Temperatures are chosen to transfer across task families. Even so, a task very unlike the training mix may be less well calibrated. Check on your own data before you gate on the probabilities.
211
+ - **Questions are answered independently.** Answers in one request do not condition on each other. Encode a joint decision as one choice, or ask in stages.
212
+ - **English only.**
213
+ - **Needs a GPU for real-time use.** It runs on CPU, but a 4B backbone there takes seconds per call, not milliseconds.
214
+
215
+ ## Hosted classification
216
+
217
+ Text classification in Interfaze runs on a similar system to lev: the model reads the answer from the set of labels you define. The difference is that Interfaze is still token based, so it's a hybrid.
218
+
219
+ | Item | lev | Interfaze |
220
+ | :-- | :-- | :-- |
221
+ | Output | Probabilities, zero output tokens | Tokens, returned as structured output |
222
+ | Questions | Typed only: yes/no, choice, score | Any JSON schema, labels included |
223
+ | In the same request | Classification only | OCR, web search, transcription, extraction, and more |
224
+ | Where it runs | Your GPU | Interfaze API |
225
+
226
+ Tokens cost a little speed, but they let one request classify a document while also reading, searching, and extracting from it. Define your labels as an enum in the schema, and the label comes back as a typed field.
227
+
228
+ **Interfaze docs → [interfaze.ai/docs](https://interfaze.ai/docs)**
229
+
230
+ ## Files
231
+
232
+ | file | role |
233
+ | --- | --- |
234
+ | `adapter_model.safetensors`, `adapter_config.json` | LoRA adapter |
235
+ | `mode_b_head.pt` | candidate-path head (tensor state dict, loaded with `weights_only=True`) |
236
+ | `tokenizer*`, `chat_template.jinja` | the tokenizer that the label codes were verified against |
237
+ | `calibration.json` | fitted temperatures |
238
+ | `lev_release.json` | manifest: base model, prompt format, readout, training step |
239
+
240
+ ## License
241
+
242
+ The adapter is released under Apache-2.0, the same license as the base model. Some of the training datasets have their own terms, including non-commercial licenses. Review them before commercial use.
243
+
244
+ Not affiliated with or endorsed by TypeSafe AI.
245
+
246
+ Apache 2.0 · Interfaze
adapter_config.json ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alora_invocation_tokens": null,
3
+ "alpha_pattern": {},
4
+ "arrow_config": null,
5
+ "auto_mapping": null,
6
+ "base_model_name_or_path": "Qwen/Qwen3.5-4B",
7
+ "bias": "none",
8
+ "corda_config": null,
9
+ "ensure_weight_tying": false,
10
+ "eva_config": null,
11
+ "exclude_modules": null,
12
+ "fan_in_fan_out": false,
13
+ "inference_mode": true,
14
+ "init_lora_weights": true,
15
+ "kasa_config": null,
16
+ "layer_replication": null,
17
+ "layers_pattern": null,
18
+ "layers_to_transform": null,
19
+ "loftq_config": {},
20
+ "lora_alpha": 64,
21
+ "lora_bias": false,
22
+ "lora_dropout": 0.05,
23
+ "lora_ga_config": null,
24
+ "megatron_config": null,
25
+ "megatron_core": "megatron.core",
26
+ "modules_to_save": null,
27
+ "monteclora_config": null,
28
+ "peft_type": "LORA",
29
+ "peft_version": "0.21.0",
30
+ "qalora_group_size": 16,
31
+ "r": 32,
32
+ "rank_pattern": {},
33
+ "revision": null,
34
+ "target_modules": [
35
+ "gate_proj",
36
+ "down_proj",
37
+ "up_proj",
38
+ "k_proj",
39
+ "v_proj",
40
+ "o_proj",
41
+ "q_proj"
42
+ ],
43
+ "target_parameters": null,
44
+ "task_type": "CAUSAL_LM",
45
+ "trainable_token_indices": null,
46
+ "use_bdlora": null,
47
+ "use_dora": false,
48
+ "use_qalora": false,
49
+ "use_rslora": false,
50
+ "velora_config": null
51
+ }
adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:64c718974d7ed0c9b22a0304060669fa3289ff89b57e572d08b9e9a0dc0623c1
3
+ size 169903320
assets/accuracy-by-subset.png ADDED

Git LFS Details

  • SHA256: 2d5941819910e61034af2a48ac5800db2409eaa2ef786452b577477179c3e1b3
  • Pointer size: 131 Bytes
  • Size of remote file: 176 kB
assets/accuracy-per-parameter.png ADDED

Git LFS Details

  • SHA256: ed5465d6df019c81594c05434b7b1e890f5f8e696562dbc97d2b91f92f504022
  • Pointer size: 131 Bytes
  • Size of remote file: 103 kB
assets/compute.png ADDED
assets/hero.png ADDED

Git LFS Details

  • SHA256: a8d0d817ad2fd121347f51e61b268ed176f37a13c8e4487f4e17c0a60ef2c6c8
  • Pointer size: 131 Bytes
  • Size of remote file: 151 kB
assets/how-it-works.png ADDED
assets/leaderboard.png ADDED

Git LFS Details

  • SHA256: 0f758b2d7cc5638cff05dd34d498dc82fa0e4f19ab6ad7ecc5d22f0188a9dc57
  • Pointer size: 131 Bytes
  • Size of remote file: 241 kB
calibration.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "temperatures": {
3
+ "choice:B:large": 0.6333014152276044,
4
+ "choice:B": 0.6333014152276044,
5
+ "noul:A": 2.3332930831706458,
6
+ "score:A": 2.8033236630327885,
7
+ "choice:A": 1.7666659539679779,
8
+ "choice:A:small": 1.789783450971802,
9
+ "choice:A:mid": 1.6085685001661532,
10
+ "choice:A:large": 1.6641112617330986
11
+ },
12
+ "fitted_on": "calibration (transfer-selected)",
13
+ "n_samples": {
14
+ "choice:B:large": 10227,
15
+ "choice:B": 10227,
16
+ "noul:A": 12073,
17
+ "score:A": 12258,
18
+ "choice:A": 14133,
19
+ "choice:A:small": 11480,
20
+ "choice:A:mid": 1138,
21
+ "choice:A:large": 1515
22
+ }
23
+ }
chat_template.jinja ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set image_count = namespace(value=0) %}
2
+ {%- set video_count = namespace(value=0) %}
3
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
4
+ {%- if content is string %}
5
+ {{- content }}
6
+ {%- elif content is iterable and content is not mapping %}
7
+ {%- for item in content %}
8
+ {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
9
+ {%- if is_system_content %}
10
+ {{- raise_exception('System message cannot contain images.') }}
11
+ {%- endif %}
12
+ {%- if do_vision_count %}
13
+ {%- set image_count.value = image_count.value + 1 %}
14
+ {%- endif %}
15
+ {%- if add_vision_id %}
16
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
17
+ {%- endif %}
18
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
19
+ {%- elif 'video' in item or item.type == 'video' %}
20
+ {%- if is_system_content %}
21
+ {{- raise_exception('System message cannot contain videos.') }}
22
+ {%- endif %}
23
+ {%- if do_vision_count %}
24
+ {%- set video_count.value = video_count.value + 1 %}
25
+ {%- endif %}
26
+ {%- if add_vision_id %}
27
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
28
+ {%- endif %}
29
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
30
+ {%- elif 'text' in item %}
31
+ {{- item.text }}
32
+ {%- else %}
33
+ {{- raise_exception('Unexpected item type in content.') }}
34
+ {%- endif %}
35
+ {%- endfor %}
36
+ {%- elif content is none or content is undefined %}
37
+ {{- '' }}
38
+ {%- else %}
39
+ {{- raise_exception('Unexpected content type.') }}
40
+ {%- endif %}
41
+ {%- endmacro %}
42
+ {%- if not messages %}
43
+ {{- raise_exception('No messages provided.') }}
44
+ {%- endif %}
45
+ {%- if tools and tools is iterable and tools is not mapping %}
46
+ {{- '<|im_start|>system\n' }}
47
+ {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
48
+ {%- for tool in tools %}
49
+ {{- "\n" }}
50
+ {{- tool | tojson }}
51
+ {%- endfor %}
52
+ {{- "\n</tools>" }}
53
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
54
+ {%- if messages[0].role == 'system' %}
55
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
56
+ {%- if content %}
57
+ {{- '\n\n' + content }}
58
+ {%- endif %}
59
+ {%- endif %}
60
+ {{- '<|im_end|>\n' }}
61
+ {%- else %}
62
+ {%- if messages[0].role == 'system' %}
63
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
64
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
65
+ {%- endif %}
66
+ {%- endif %}
67
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
68
+ {%- for message in messages[::-1] %}
69
+ {%- set index = (messages|length - 1) - loop.index0 %}
70
+ {%- if ns.multi_step_tool and message.role == "user" %}
71
+ {%- set content = render_content(message.content, false)|trim %}
72
+ {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
73
+ {%- set ns.multi_step_tool = false %}
74
+ {%- set ns.last_query_index = index %}
75
+ {%- endif %}
76
+ {%- endif %}
77
+ {%- endfor %}
78
+ {%- if ns.multi_step_tool %}
79
+ {{- raise_exception('No user query found in messages.') }}
80
+ {%- endif %}
81
+ {%- for message in messages %}
82
+ {%- set content = render_content(message.content, true)|trim %}
83
+ {%- if message.role == "system" %}
84
+ {%- if not loop.first %}
85
+ {{- raise_exception('System message must be at the beginning.') }}
86
+ {%- endif %}
87
+ {%- elif message.role == "user" %}
88
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
89
+ {%- elif message.role == "assistant" %}
90
+ {%- set reasoning_content = '' %}
91
+ {%- if message.reasoning_content is string %}
92
+ {%- set reasoning_content = message.reasoning_content %}
93
+ {%- else %}
94
+ {%- if '</think>' in content %}
95
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
96
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
97
+ {%- endif %}
98
+ {%- endif %}
99
+ {%- set reasoning_content = reasoning_content|trim %}
100
+ {%- if loop.index0 > ns.last_query_index %}
101
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
102
+ {%- else %}
103
+ {{- '<|im_start|>' + message.role + '\n' + content }}
104
+ {%- endif %}
105
+ {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
106
+ {%- for tool_call in message.tool_calls %}
107
+ {%- if tool_call.function is defined %}
108
+ {%- set tool_call = tool_call.function %}
109
+ {%- endif %}
110
+ {%- if loop.first %}
111
+ {%- if content|trim %}
112
+ {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
113
+ {%- else %}
114
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
115
+ {%- endif %}
116
+ {%- else %}
117
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
118
+ {%- endif %}
119
+ {%- if tool_call.arguments is defined %}
120
+ {%- for args_name, args_value in tool_call.arguments|items %}
121
+ {{- '<parameter=' + args_name + '>\n' }}
122
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
123
+ {{- args_value }}
124
+ {{- '\n</parameter>\n' }}
125
+ {%- endfor %}
126
+ {%- endif %}
127
+ {{- '</function>\n</tool_call>' }}
128
+ {%- endfor %}
129
+ {%- endif %}
130
+ {{- '<|im_end|>\n' }}
131
+ {%- elif message.role == "tool" %}
132
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
133
+ {{- '<|im_start|>user' }}
134
+ {%- endif %}
135
+ {{- '\n<tool_response>\n' }}
136
+ {{- content }}
137
+ {{- '\n</tool_response>' }}
138
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
139
+ {{- '<|im_end|>\n' }}
140
+ {%- elif loop.last %}
141
+ {{- '<|im_end|>\n' }}
142
+ {%- endif %}
143
+ {%- else %}
144
+ {{- raise_exception('Unexpected message role.') }}
145
+ {%- endif %}
146
+ {%- endfor %}
147
+ {%- if add_generation_prompt %}
148
+ {{- '<|im_start|>assistant\n' }}
149
+ {%- if enable_thinking is defined and enable_thinking is false %}
150
+ {{- '<think>\n\n</think>\n\n' }}
151
+ {%- else %}
152
+ {{- '<think>\n' }}
153
+ {%- endif %}
154
+ {%- endif %}
lev_release.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "lev",
3
+ "preset": "4b-instruct",
4
+ "step": 18750,
5
+ "base_model": "Qwen/Qwen3.5-4B",
6
+ "lora_rank": 32,
7
+ "mode_b_head": true,
8
+ "calibrated": true,
9
+ "noul_readout": "rating",
10
+ "prompt_style": "chat",
11
+ "files": [
12
+ "adapter_config.json",
13
+ "adapter_model.safetensors",
14
+ "chat_template.jinja",
15
+ "mode_b_head.pt",
16
+ "tokenizer.json",
17
+ "tokenizer_config.json",
18
+ "calibration.json"
19
+ ],
20
+ "metrics": {},
21
+ "created": "2026-09-24T06:29:31+00:00"
22
+ }
mode_b_head.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:27eedf7bb9e20d66432882b91297ef6e1ce3d23d81e94ed105ffadba77c6d3ad
3
+ size 14698565
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:06b9509352d2af50381ab2247e083b80d32d5c0aba91c272ca9ff729b6a0e523
3
+ size 19989325
tokenizer_config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "audio_bos_token": "<|audio_start|>",
4
+ "audio_eos_token": "<|audio_end|>",
5
+ "audio_token": "<|audio_pad|>",
6
+ "backend": "tokenizers",
7
+ "bos_token": null,
8
+ "clean_up_tokenization_spaces": false,
9
+ "eos_token": "<|im_end|>",
10
+ "errors": "replace",
11
+ "image_token": "<|image_pad|>",
12
+ "is_local": false,
13
+ "local_files_only": false,
14
+ "model_max_length": 262144,
15
+ "model_specific_special_tokens": {
16
+ "audio_bos_token": "<|audio_start|>",
17
+ "audio_eos_token": "<|audio_end|>",
18
+ "audio_token": "<|audio_pad|>",
19
+ "image_token": "<|image_pad|>",
20
+ "video_token": "<|video_pad|>",
21
+ "vision_bos_token": "<|vision_start|>",
22
+ "vision_eos_token": "<|vision_end|>"
23
+ },
24
+ "pad_token": "<|endoftext|>",
25
+ "pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
26
+ "split_special_tokens": false,
27
+ "tokenizer_class": "Qwen2Tokenizer",
28
+ "unk_token": null,
29
+ "video_token": "<|video_pad|>",
30
+ "vision_bos_token": "<|vision_start|>",
31
+ "vision_eos_token": "<|vision_end|>"
32
+ }