webAI-Official commited on
Commit
2277cb8
·
0 Parent(s):

Publish TwIL-LM3-Pro

Browse files
.gitattributes ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ Meridian-smaller-F16.gguf filter=lfs diff=lfs merge=lfs -text
37
+ Meridian-smaller-Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text
38
+ Meridian-smaller-Q5_K_M.gguf filter=lfs diff=lfs merge=lfs -text
39
+ Meridian-smaller-Q6_K.gguf filter=lfs diff=lfs merge=lfs -text
40
+ Meridian-smaller-Q8_0.gguf filter=lfs diff=lfs merge=lfs -text
41
+ benchmarks.png filter=lfs diff=lfs merge=lfs -text
42
+ TwIL-LM3-Pro-F16.gguf filter=lfs diff=lfs merge=lfs -text
43
+ TwIL-LM3-Pro-Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text
44
+ TwIL-LM3-Pro-Q5_K_M.gguf filter=lfs diff=lfs merge=lfs -text
45
+ TwIL-LM3-Pro-Q6_K.gguf filter=lfs diff=lfs merge=lfs -text
46
+ TwIL-LM3-Pro-Q8_0.gguf filter=lfs diff=lfs merge=lfs -text
47
+ TwIL-LM3-Pro-Q4_0.gguf filter=lfs diff=lfs merge=lfs -text
LICENSE.md ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ webAI Non-Commercial License ver. 1.0
2
+
3
+
4
+ 1. Definitions
5
+
6
+ “Licensor” means any person or entity that distributes its Work. “Work” means (a) the original work of authorship made available under this license, which may include software, documentation, or other files, and (b) any additions to or derivative works thereof that are made available under this license. The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under U.S. copyright law; provided, however, that for the purposes of this license, derivative works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work. Works are “made available” under this license by including in or with the Work either (a) a copyright notice referencing the applicability of this license to the Work, or (b) a copy of this license.
7
+
8
+
9
+ 2. License Grant
10
+
11
+ 2.1 Copyright Grant. Subject to the terms and conditions of this license, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to use, reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form.
12
+
13
+
14
+ 3. Limitations
15
+
16
+ 3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this license, (b) you include a complete copy of this license with your distribution, and (c) you retain without modification any copyright, patent, trademark, or attribution notices that are present in the Work.
17
+
18
+ 3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and distribution of your derivative works of the Work (“Your Terms”) only if (a) Your Terms provide that the use limitation in Section 3.3 applies to your derivative works, and (b) you identify the specific derivative works that are subject to Your Terms. Notwithstanding Your Terms, this license (including the redistribution requirements in Section 3.1) will continue to apply to the Work itself.
19
+
20
+ 3.3 Use Limitation. The Work and any derivative works thereof only may be used or intended for use non-commercially. As used herein, “non-commercially” means for non-commercial research and educational purposes only.
21
+
22
+ 3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor (including any claim, cross-claim or counterclaim in a lawsuit) to enforce any patents that you allege are infringed by any Work, then your rights under this license from such Licensor (including the grant in Section 2.1) will terminate immediately.
23
+
24
+ 3.5 Trademarks. This license does not grant any rights to use any Licensor's or its affiliates' names, logos, or trademarks, except as necessary to reproduce the notices described in this license. Nothing in this license shall be construed as permission to use the trade names, trademarks, service marks, or product names of webAI, Inc. or its affiliates to endorse, promote, or imply association with any derivative work, product, service, or entity, without prior written consent from webAI, Inc. Use of the Work does not imply endorsement by webAI, Inc. of any derivative work, product, service, or entity.
25
+
26
+ 3.6 Termination. If you violate any term of this license, then your rights under this license (including the grant in Section 2.1) will terminate immediately.
27
+
28
+
29
+ 4. Disclaimer of Warranty.
30
+
31
+ THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER THIS LICENSE.
32
+
33
+
34
+ 5. Limitation of Liability.
35
+
36
+ EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER DAMAGES OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
README.md ADDED
@@ -0,0 +1,584 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ library_name: transformers
5
+ pipeline_tag: text-generation
6
+ base_model: ibm-granite/granite-4.2-3b
7
+ license: other
8
+ license_name: webai-non-commercial-license-ver.-1.0
9
+ license_link: https://huggingface.co/webAI-Official/TwIL-LM3-Pro/blob/main/LICENSE.md
10
+ tags:
11
+ - granite
12
+ - granite-4.2
13
+ - formal-logic
14
+ - reasoning
15
+ - lora
16
+ - model-merging
17
+ - wise-ft
18
+ - reinforcement-learning
19
+ - grpo
20
+ - gguf
21
+ ---
22
+
23
+ # TwIL-LM3-Pro
24
+
25
+ A 3.66B reasoning model for **formal logic** tasks, built from
26
+ [`ibm-granite/granite-4.2-3b`](https://huggingface.co/ibm-granite/granite-4.2-3b) through LoRA
27
+ supervised fine-tuning, checkpoint fusion, WiSE-FT weight interpolation, and entropy-weighted
28
+ GRPO reinforcement learning.
29
+
30
+ It improves in-domain formal-logic performance by **+28% relative** over its base model
31
+ (macro gate 0.431 → 0.554) **while holding held-out benchmark performance** — the 10-dataset
32
+ macro is level with the base (0.7942 → 0.7901) and the 14-dataset macro improves slightly
33
+ (0.7332 → 0.7425). On the same harness and sampled rows it reaches the highest Track A macro
34
+ gate, strict-7 and six-lane average of any arm in the tables below for which each can be
35
+ computed, including Qwen3-8B, Qwen3.5-4B, VibeThinker-3B and gpt-oss-120b (the 120B has no gate or strict-7
36
+ value).
37
+
38
+ ![TwIL-LM3-Pro formal and general reasoning benchmarks against VibeThinker-3B, VibeThinker-webAI-trained, Qwen3.5-4B, Qwen3-8B, gpt-oss-120b, LFM2.5-8B-A1B and TwIL-LM3](benchmarks.png)
39
+
40
+ *VibeThinker-webAI-trained is the public VibeThinker-3B after the same post-training pipeline (SLERP, d = 0.5, t = 0.5); see [Against the tuned VibeThinker-3B](#against-the-tuned-vibethinker-3b). It has no strict-7 or six-lane-average value, so those bars show n/a.*
41
+
42
+ ## Highlights
43
+
44
+ * **Large in-domain gain on the same harness.** Macro gate 0.4313 → 0.5539 (+0.123) and strict-7
45
+ 0.1821 → 0.2879 against its own base, measured on identical sampled rows. Both models are
46
+ heavily truncated at this budget (see [Limitations](#limitations-and-caveats)), and the base
47
+ more so, so the size of the gap is indicative rather than exact.
48
+ * **Top of the Track A summary rows at 3.66B.** Macro gate 0.5539 against Qwen3-8B's 0.5336
49
+ (2.2x the parameters) and TwIL-LM3's 0.4218; strict-7 0.2879 against 0.2093 and 0.1971;
50
+ six-lane average 0.5389 against gpt-oss-120b's 0.5192. The gate lead over Qwen3-8B is 0.020 —
51
+ smaller than the sampling noise at n = 200 per lane — so read that one as parity, not a win.
52
+ * **Strongest strict MCQ, and close to the best language-model fit.** `mcq_answer` strict accuracy
53
+ 0.4100 (next best 0.1700), `lean_critic` 0.7950 (tied with Qwen3-8B and its own base), the
54
+ lowest `lm_corpus` perplexity of any arm (2.3130) and a `math_corpus` perplexity of 3.6983 that
55
+ only Qwen3.5-4B beats (3.5926). Perplexity is per token, so it is only loosely comparable across
56
+ tokenizers.
57
+ * **Holds general capability.** Track B 10-dataset macro 0.7901 and 14-dataset macro 0.7425 —
58
+ ahead of LFM2.5-8B-A1B (0.7884 / 0.7378) at less than half its parameter count, and behind
59
+ Qwen3-8B (0.8493 / 0.7591) and gpt-oss-120b (0.8689 / 0.8086). It gains on BBH-logic
60
+ (0.9013 → 0.9540), MATH-500 (0.6567 → 0.7467) and MuSR (0.5922 → 0.6409), and gives back
61
+ GSM-Symbolic (0.8900 → 0.8267) and ARC (0.8933 → 0.8600).
62
+ * **Against VibeThinker-3B, a reasoning model of similar size.** TwIL-LM3-Pro leads it on all
63
+ six Track A lanes — macro gate 0.5539 against 0.4118, strict-7 0.2879 against 0.2021 — but not
64
+ on Track B, where VibeThinker-3B is ahead on the 10-dataset macro (0.8097 against 0.7901) and
65
+ TwIL-LM3-Pro is ahead on the 14-dataset macro (0.7425 against 0.7262). That 14-dataset lead
66
+ comes entirely from BBH-logic (0.9540 against 0.6107); without that row TwIL-LM3-Pro trails.
67
+ * **The pipeline is not tied to one model.** The same recipe was run on five base models. On
68
+ VibeThinker-3B it lifts the Track A macro gate from 0.374 to 0.508 (SLERP, the
69
+ *VibeThinker-webAI-trained* column) while the Track B 10-dataset macro moves from 0.815 to 0.802 — see
70
+ [One pipeline, several models](#one-pipeline-several-models).
71
+ * **Structured formal output.** Tuned for the objects rather than the prose: FOL translation,
72
+ entailment labels, semantic parses, Lean statements and Lean proof critique.
73
+ * **Runs anywhere.** 3.66B parameters in bf16 (6.82 GiB), with a Q4\_K\_M GGUF at 2.09 GiB for
74
+ CPU or 4 GB of VRAM.
75
+
76
+ It is **not the most efficient**: it reasons at length. Track A generations average 1,902 tokens,
77
+ against 564 for TwIL-LM3, and 24.2% of them hit the length cap. Its raw decode rate is high
78
+ (21,169 tok/s †) but the long answers bring it to about 11 completed
79
+ answers per second †, against 28.1 for TwIL-LM3 and 4.5 for Qwen3-8B. It is also not a general
80
+ assistant — there is no safety or preference tuning here beyond what Granite 4.2 carries. See
81
+ [Limitations](#limitations-and-caveats).
82
+
83
+ ## Model Details
84
+
85
+ | Property | Value |
86
+ | ------------------------- | ---------------------------------------------------------------------------------------------- |
87
+ | Model ID | `webAI-Official/TwIL-LM3-Pro` |
88
+ | Base model | [`ibm-granite/granite-4.2-3b`](https://huggingface.co/ibm-granite/granite-4.2-3b) |
89
+ | Total parameters | 3.66B (3,659,737,600) |
90
+ | Architecture | Granite decoder-only dense transformer (`GraniteForCausalLM`); 40 layers, hidden size 2560, 40 attention heads / 8 KV heads |
91
+ | Input / output | Text / text |
92
+ | Language | English |
93
+ | Tokenizer vocabulary size | 100,352 |
94
+ | Context window | 131,072 tokens |
95
+ | Checkpoint precision | bfloat16 (6.82 GiB), plus Q4\_0 / Q4\_K\_M / Q5\_K\_M / Q6\_K / Q8\_0 / F16 GGUF builds |
96
+ | Post-training | LoRA SFT → checkpoint fusion → WiSE-FT (α = 0.15) → MGPO reinforcement learning (β = 0.02, step 2580) |
97
+ | Reasoning format | Emits a `<think>…</think>` block before the answer (default chat template) |
98
+ | Evaluated decoding | Greedy, 2048 new tokens (one retry at 4096), `max_seq_len` 8192 |
99
+ | Specialisation | Formal logic: FOL translation, entailment, semantic parsing, Lean formalisation and critique |
100
+ | License | webAI Non-Commercial License ver. 1.0 |
101
+
102
+ The base model's 131,072-token context is carried through unchanged, but every score on this card
103
+ was measured inside an 8,192-token window; longer contexts are inherited rather than validated
104
+ here.
105
+
106
+ ## Results
107
+
108
+ ### Track A — in-domain formal logic
109
+
110
+ TwIL-LM3-Pro, its base and VibeThinker-3B were run through the same harness, prompts, decoding
111
+ settings and sampled rows described under [Evaluation protocol](#evaluation-protocol), and the
112
+ other peer columns are the values already published for TwIL-LM3 on its card, produced by that
113
+ same harness (see [Comparability](#limitations-and-caveats)). Throughput rows come from a
114
+ dedicated decode-throughput protocol: `ans/s` is defined throughout as
115
+ `tok/s ÷ mean generation length`, so it measures completed answers rather than raw decode rate.
116
+ Cells marked † need the engine note below.
117
+
118
+ | lane / metric | TwIL-LM3-Pro | Granite-4.2-3B base | VibeThinker-3B | VibeThinker-webAI-trained ★ | Qwen3.5-4B | TwIL-LM3 | Llama-3.2-3B | LFM2-2.6B | LFM2.5-8B-A1B | Qwen3-8B | gpt-oss-120b ‡ |
119
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
120
+ | lean_formalize token_f1 | 0.5092 | 0.2943 | 0.2087 | 0.527 | 0.4996 | 0.5869 | 0.3690 | 0.1321 | 0.4655 | 0.4022 | **0.6306** |
121
+ | rule_induction derivation | 0.4195 | 0.2267 | 0.2038 | 0.227 | 0.5078 | 0.3192 | 0.0825 | 0.0615 | 0.1936 | 0.3680 | **0.6518** |
122
+ | entailment_label accuracy | 0.6700 | 0.3000 | 0.5500 | 0.685 | 0.2400 | 0.5750 | 0.3300 | 0.4700 | 0.5400 | 0.5800 | **0.7750** |
123
+ | mcq_answer accuracy | **0.4100** | 0.1200 | 0.1700 | — | 0.0000 | 0.1100 | 0.0000 | 0.0150 | 0.0750 | 0.0000 | 0.0700 |
124
+ | semantic_parse token_f1 | 0.4295 | 0.3910 | 0.2422 | 0.392 | 0.3826 | **0.4416** | 0.3102 | 0.3665 | 0.3778 | 0.4257 | 0.4331 |
125
+ | lean_critic accuracy | **0.7950** | **0.7950** | 0.6000 | 0.685 | 0.5400 | 0.6600 | 0.5300 | 0.5900 | 0.5500 | **0.7950** | 0.5550 |
126
+ | lm_corpus perplexity ↓ | **2.3130** | 2.6334 | 16.9253 | 7.350 | 2.3916 | 2.8972 | 2.8478 | 4.3815 | 4.9472 | 2.5440 | 912.23 § |
127
+ | math_corpus perplexity ↓ | 3.6983 | 4.4864 | 27.0318 | 7.000 | **3.5926** | 3.8229 | 4.7531 | 6.7472 | 8.3323 | 4.0083 | 1045.63 § |
128
+ | average, 6 lanes | **0.5389** | 0.3545 | 0.3291 | — | 0.3617 | 0.4488 | 0.2703 | 0.2725 | 0.3670 | 0.4285 | 0.5192 |
129
+ | **macro gate** | **0.5539** | 0.4313 | 0.4118 | 0.508 | 0.4466 | 0.4218 | 0.2925 | 0.3473 | 0.3757 | 0.5336 | — |
130
+ | **strict-7** | **0.2879** | 0.1821 | 0.2021 | — | 0.1121 | 0.1971 | 0.1229 | 0.1579 | 0.1714 | 0.2093 | — |
131
+ | macro_primary | **0.5875** | 0.4825 | 0.4637 | 0.579 | 0.4313 | 0.4475 | 0.3450 | 0.4188 | 0.4213 | 0.5750 | — |
132
+ | tok/s | 21169 † | 21916 † | 28010 † | ≈28010 ★ † | 11097 † | 15880 | 16160 | 25230 | 22480 | 9420 | 3374 |
133
+ | mean gen length | 1902 | 2951 | 2688 | — | 2486 | **564** | 696 | 2296 | 1830 | 2094 | 1005 |
134
+ | **ans/s** | 11.1 † | 7.4 † | 10.4 † | — | 4.5 † | **28.1** | 23.2 | 10.9 | 12.0 | 4.5 | 3.4 |
135
+
136
+ ‡ **gpt-oss-120b** runs MXFP4 weights at tensor-parallel 2 — quantized and multi-GPU, so its
137
+ throughput rows are not directly comparable to the single-GPU BF16 arms. Its `procedural` lane
138
+ and the loose-match scorings were not collected, so the three summary rows below the six-lane
139
+ average cannot be computed for it; that is what the — cells mean, not a zero.
140
+
141
+ § The 120B's perplexities are three orders of magnitude off every other arm because its response
142
+ format and tokenizer make the corpus lanes score a different quantity. The number is reported
143
+ for completeness but is not a comparable measurement, and is excluded from the bolding.
144
+
145
+ ★ **VibeThinker-webAI-trained** is the public VibeThinker-3B after the same post-training pipeline as
146
+ TwIL-LM3-Pro, in its SLERP (d = 0.5, t = 0.5) configuration; it is not a checkpoint in this
147
+ repository, and [the section below](#against-the-tuned-vibethinker-3b) explains how it differs
148
+ from the base model. Its figures are taken from the internal family comparison tables, to three
149
+ decimals, not from the per-lane reports behind the other columns, so its column is indicative
150
+ rather than strictly paired with them. `macro gate` and `macro_primary` are the family tables'
151
+ "macro primary (rule)" and "primary" columns, which have the same definitions as above. The
152
+ family tables score `mcq_answer` with loose-match credit (0.695), so the strict MCQ row, the
153
+ six-lane average and strict-7 — which all need strict scoring — are left as —. Its perplexities
154
+ come from that separate run; the family table records the untuned VibeThinker-3B at 18.70 and
155
+ 21.80 there, against 16.93 and 27.03 in the columns above, so read them within their own source.
156
+ Its `tok/s` is an **estimate, not a measurement**: merging changes weights but not architecture,
157
+ parameter count or tokenizer, and the throughput protocol fixes the output at 512 generated tokens
158
+ with EOS ignored, so the decode rate does not depend on what the weights say. It is therefore set
159
+ equal to the 28,010 tok/s measured for the base VibeThinker-3B in the same session (a ≈ and both
160
+ marks in the cell). Mean generation length, and so `ans/s`, does depend on the weights and was not
161
+ measured, so those rows stay —.
162
+
163
+ † **Throughput for TwIL-LM3-Pro, its base and VibeThinker-3B** was measured with the same
164
+ dedicated protocol and prompt file as the peer columns (128 prompts × 512 generated tokens, EOS
165
+ ignored, greedy, `gpu_memory_utilization` 0.45, idle GPU), run on a single H200 with vLLM
166
+ 0.19.1 in a later session, whereas the other columns are figures recorded earlier on vLLM 0.11.2. Engine effects
167
+ are architecture-dependent: in the same session TwIL-LM3 re-measured at 15,248 tok/s
168
+ against its published 15,880 (−4%), while VibeThinker-3B measured
169
+ 28,010 against a published 18,116 (+55%). The †
170
+ cells are therefore comparable with each other, and only approximately with the older columns.
171
+ The Qwen3.5-4B figure comes from the earlier throughput sweep, which ran the Qwen3.5 models on the
172
+ newer engine (vLLM 0.19.1) according to its driver script, so it belongs with the † cells.
173
+ TwIL-LM3-Pro's two runs gave 20,454 and 21,884 tok/s (the first paid for cold
174
+ kernel caches) and the table shows their mean. `mean gen length` is measured directly under the
175
+ shared evaluation protocol and is comparable across every column.
176
+
177
+ **`average, 6 lanes`** is the plain mean of the six objective rows above it, each at whatever
178
+ scoring that row reports (Lean F1, rule derivation, entailment, MCQ strict, semantic F1, critic).
179
+ It is a coarser summary than the three that follow — it mixes token-F1 with accuracy — but it is
180
+ the only summary row every arm here can be compared on, including the 120B.
181
+
182
+ The next three rows aggregate more carefully. None of them include the perplexity lanes or the
183
+ token-F1 scorings, which are not on a common 0–1 accuracy scale.
184
+
185
+ **`macro gate`** is the headline metric and the one the training pipeline gates on. It is the
186
+ equal-weight mean of five objectives: the four bounded classification lanes (`entailment_label`,
187
+ `mcq_answer`, `procedural`, `lean_critic`) plus `rule_induction`, scored by its continuous
188
+ derivation score. In the gate, `mcq_answer` and `procedural` are credited as
189
+ `max(exact_match, loose_match)`: for free-text answer lanes, a response that is correct but
190
+ differently formatted is a formatting artefact rather than a reasoning failure. This affects the
191
+ aggregate only — the per-lane rows above stay strict. (TwIL-LM3-Pro's loose-match MCQ is
192
+ 0.6500 against the 0.4100 strict figure shown in the lane row.)
193
+
194
+ **`macro_primary`** is the same mean over the four classification lanes alone, without
195
+ `rule_induction`.
196
+
197
+ **`strict-7`** is the mean of seven lanes scored under strict metrics only (`fol_translation`,
198
+ `entailment_label`, `mcq_answer`, `semantic_parse` and `lean_formalize` exact match,
199
+ `lean_critic` and `procedural` accuracy), with no loose-match credit anywhere. It is deliberately
200
+ harsh — exact match on generative lanes is near zero for every arm — so it is useful for ranking
201
+ models against each other but not as an absolute capability measure.
202
+
203
+ TwIL-LM3-Pro leads all four summary rows that every arm with a computable value can be
204
+ compared on. The clearest margins are over the arms at its own scale and above: 0.5539 against
205
+ 0.3757 on the gate for LFM2.5-8B-A1B, and 0.2879 against 0.1971 on strict-7 for TwIL-LM3. Against
206
+ Qwen3-8B the gate gap is only 0.020, but strict-7 is 0.2879 against 0.2093 — a difference that
207
+ does not depend on loose-match credit — and TwIL-LM3-Pro leads on MCQ (strict 0.4100 against
208
+ 0.0000), rule induction (0.4195 against 0.3680) and both perplexity lanes.
209
+
210
+ VibeThinker-3B — WeiboAI's 3B reasoning model, with 37.1% of its Track A generations truncated
211
+ — trails TwIL-LM3-Pro on every objective lane and every summary row: macro gate 0.4118 against
212
+ 0.5539, strict-7 0.2021 against 0.2879, six-lane average 0.3291 against 0.5389. The gap is widest
213
+ on Lean formalisation (0.2087 against 0.5092) and narrowest on entailment (0.5500 against 0.6700).
214
+ Its corpus perplexities (16.93 and 27.03) are not comparable with the Granite-tokenizer models',
215
+ because perplexity is per token and its vocabulary is 151,936 against 100,352.
216
+
217
+ Qwen3.5-4B, a 4B reasoning model, sits between
218
+ the small models and TwIL-LM3-Pro: macro gate 0.4466 against 0.5539, strict-7 0.1121 against
219
+ 0.2879. It is ahead of TwIL-LM3-Pro on two rows only, `rule_induction` (0.5078 against 0.4195,
220
+ second in the table after gpt-oss-120b) and `math_corpus` perplexity (3.5926 against 3.6983), and
221
+ far behind on entailment (0.2400 against 0.6700) and strict MCQ (0.0000 against 0.4100).
222
+
223
+ It does not lead every lane. gpt-oss-120b is clearly stronger on `rule_induction` (0.6518),
224
+ entailment (0.7750) and Lean formalisation (0.6306), and TwIL-LM3 remains ahead on Lean
225
+ formalisation (0.5869 against 0.5092) and semantic parsing (0.4416 against 0.4295). The two weak
226
+ spots in absolute terms are `procedural` (strict 0.1200, loose 0.2350) and FOL translation
227
+ (exact match 0.0100).
228
+
229
+ ### Track B — held-out benchmarks
230
+
231
+ | dataset | TwIL-LM3-Pro | Granite-4.2-3B base | VibeThinker-3B | VibeThinker-webAI-trained ★ | Qwen3.5-4B | TwIL-LM3 | Llama-3.2-3B | LFM2-2.6B | LFM2.5-8B-A1B | Qwen3-8B | gpt-oss-120b ‡ |
232
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
233
+ | gsm8k | 0.9433 | 0.9533 | 0.9600 | 0.930 | 0.8633 | 0.8733 | 0.8300 | 0.8767 | 0.9133 | 0.9567 | **0.9767** |
234
+ | svamp | 0.9500 | 0.9200 | 0.9367 | **0.953** | 0.8867 | 0.8500 | 0.8200 | 0.9000 | 0.9133 | 0.9400 | 0.9400 |
235
+ | gsm_symbolic | 0.8267 | 0.8900 | 0.8167 | 0.883 | 0.7767 | 0.7567 | 0.8067 | **0.9767** | 0.9267 | 0.8133 | 0.8467 |
236
+ | arc_cot | 0.8600 | 0.8933 | 0.9033 | 0.877 | 0.9267 | 0.8467 | 0.7967 | 0.8667 | 0.9033 | 0.9633 | **0.9667** |
237
+ | logicbench | 0.7933 | 0.7733 | **0.8600** | 0.850 | 0.7200 | 0.7167 | 0.5733 | 0.6267 | 0.7200 | 0.8567 | 0.8533 |
238
+ | strategyqa | 0.5967 | 0.6267 | 0.6467 | 0.647 | 0.6967 | 0.6500 | 0.6533 | 0.6433 | 0.6667 | 0.7400 | **0.7867** |
239
+ | drop | 0.7367 | 0.7467 | 0.8467 | 0.790 | 0.6233 | 0.7467 | 0.6733 | 0.6900 | 0.6633 | **0.8833** | 0.8500 |
240
+ | csqa | 0.7667 | 0.7733 | 0.7367 | 0.687 | 0.7767 | 0.7367 | 0.7500 | 0.7433 | 0.7700 | **0.8633** | 0.8367 |
241
+ | musr | 0.6409 | 0.5922 | 0.5799 | 0.588 | 0.5696 | 0.4957 | 0.4932 | 0.4867 | 0.5703 | 0.6301 | **0.6852** |
242
+ | mmlu_redux | 0.7867 | 0.7733 | 0.8100 | 0.813 | 0.8433 | 0.6667 | 0.6000 | 0.7133 | 0.8367 | 0.8500 | **0.9467** |
243
+ | ifeval | 0.7500 | 0.7633 | 0.6633 | 0.557 | 0.2400 ¶¶¶ | 0.6433 | 0.7167 | 0.7300 | **0.8900** | 0.8400 | 0.7900 |
244
+ | rudas_ood | 0.0437 ¶¶ | 0.0012 | 0.0056 | 0.000 | 0.0084 ¶¶¶ | 0.0365 | **0.0733** | 0.0017 | 0.0061 | 0.0468 | 0.0000 ¶ |
245
+ | bbh_logic | 0.9540 | 0.9013 | 0.6107 | 0.829 | 0.9647 | 0.6633 | 0.5333 | 0.5713 | 0.7700 | 0.6367 | **0.9980** |
246
+ | math500 | 0.7467 | 0.6567 | 0.7900 | 0.790 | 0.3600 ¶¶¶ | 0.6900 | 0.4233 | 0.7133 | 0.7800 | 0.6100 | **0.8433** |
247
+ | **macro (10 CoT datasets)** | 0.7901 | 0.7942 | 0.8097 | 0.802 | 0.7683 | 0.7339 | 0.6997 | 0.7523 | 0.7884 | 0.8493 | **0.8689** |
248
+ | **macro (all 14)** | 0.7425 | 0.7332 | 0.7262 | 0.728 | 0.6611 | 0.6694 | 0.6245 | 0.6814 | 0.7378 | 0.7591 | **0.8086** |
249
+ | tok/s | 21169 † | 21916 † | 28010 † | ≈28010 ★ † | 11097 † | 15880 | 16160 | 25230 | 22480 | 9420 | 3374 |
250
+ | mean gen length | ≈792 | ≈1282 | ≈1789 | — | ≈2787 | **482** | 510 | ≈796 | ≈1327 | ≈1931 | 801 |
251
+ | **ans/s** | 26.7 † | 17.1 † | ≈15.7 † | — | ≈4.0 † | **32.9** | 31.7 | ≈31.7 | ≈16.9 | 4.9 | 4.2 |
252
+
253
+ ‡ MXFP4 weights, tensor-parallel 2 — quantized and multi-GPU, so not directly comparable to the
254
+ single-GPU BF16 rows. ¶ 74% of its `rudas_ood` generations hit the length cap, so that cell is a
255
+ truncation artefact rather than a measured score; excluding the row, its 13-dataset macro is
256
+ 0.8708. ¶¶ 93.7% of TwIL-LM3-Pro's `rudas_ood` generations also hit the length cap, so its
257
+ cell is likewise a truncation artefact rather than a measurement of the model's ability.
258
+ ¶¶¶ Qwen3.5-4B hits the length cap on 67.3% of IFEval, 59.0% of MATH-500 and 99.3% of `rudas_ood`
259
+ generations, so those three cells are truncation artefacts too.
260
+
261
+ Lengths marked ≈ are derived from stored generations rather than read from the run. For
262
+ TwIL-LM3-Pro, its base and VibeThinker-3B they were re-tokenized directly with each model's
263
+ own tokenizer and
264
+ averaged over the 14 datasets (MuSR counted once); the same method reproduces TwIL-LM3's measured
265
+ 482 to within 1%. The peer lengths marked ≈ use each model's characters-per-token ratio and are
266
+ carried over from the TwIL-LM3 card. † `tok/s` is the same throughput figure as in Track A (see
267
+ the engine note under that table) and `ans/s` divides it by the mean generation length shown. The
268
+ VibeThinker-3B Track B rows come from the same external-baseline run and vLLM 0.11.2 engine as
269
+ the other external peers.
270
+
271
+ The honest summary of this table is that TwIL-LM3-Pro does not lead it. Larger models score
272
+ higher, and gpt-oss-120b leads seven of the fourteen dataset rows. Three things are worth
273
+ extracting anyway. First, it holds its own base on the held-out suite (10-dataset macro 0.7901
274
+ against 0.7942, a difference well inside the sampling noise at n = 300 per dataset) while gaining
275
+ in-domain, which is the point of the WiSE-FT stage. Second, the 14-dataset macro rises 0.0093
276
+ over the base, driven by BBH-logic, MATH-500 and MuSR. Third, it edges LFM2.5-8B-A1B on both
277
+ macros at less than half the parameters and leads every untuned arm on SVAMP (0.9500; the
278
+ tuned VibeThinker-3B is at 0.953, one example out of 300 higher).
279
+
280
+ VibeThinker-3B is the stronger held-out model on the 10-dataset macro (0.8097 against 0.7901). It
281
+ is ahead of TwIL-LM3-Pro on seven datasets — GSM8K, ARC, LogicBench, StrategyQA, DROP,
282
+ MMLU-Redux and MATH-500 — and behind on the other seven: SVAMP, GSM-Symbolic, CSQA, MuSR, IFEval,
283
+ BBH-logic and `rudas_ood`. TwIL-LM3-Pro's 0.0163 lead on the 14-dataset macro comes entirely
284
+ from BBH-logic (0.9540 against 0.6107): on the other thirteen datasets it averages 0.7263 against
285
+ VibeThinker-3B's 0.7350. VibeThinker-3B also writes much longer answers on Track B (about 1,789
286
+ tokens against 792).
287
+
288
+ Track B here was run with the chat template's thinking mode **disabled** for TwIL-LM3-Pro and
289
+ its base (the prompt ends in an empty `<think></think>`), as it was for TwIL-LM3, whereas Track A
290
+ uses the default thinking mode. The Track B numbers therefore describe non-reasoning behaviour;
291
+ they are not a measure of what a thinking-mode generation would score. Some Track B cells are also
292
+ truncation-limited: MATH-500 hits the cap on 14.0% of rows, and SVAMP, GSM-Symbolic and
293
+ MuSR-team sit slightly above the 2% cap-hit threshold (3.0%, 3.0% and 2.8%).
294
+
295
+ ### Against the tuned VibeThinker-3B
296
+
297
+ The tables above use the public VibeThinker-3B checkpoint. The same post-training pipeline was also
298
+ applied to it, and two of its tuned configurations are the closest same-scale comparisons to
299
+ TwIL-LM3-Pro: WiSE-FT (λ = 0.50), and the SLERP merge (d = 0.5, t = 0.5) that appears in the
300
+ tables and plot as **VibeThinker-webAI-trained**. These values come from the family comparison tables
301
+ rather than from a per-lane raw report, so they are shown as a summary only:
302
+
303
+ | model | macro gate | macro_primary | B10 | B14 | Track A truncation |
304
+ |---|---:|---:|---:|---:|---:|
305
+ | TwIL-LM3-Pro | **0.554** | **0.588** | 0.790 | **0.743** | 24.2% |
306
+ | VibeThinker-webAI-trained (SLERP, d = 0.5, t = 0.5) | 0.508 | 0.579 | **0.802** | 0.728 | — |
307
+ | VibeThinker-3B, WiSE-FT λ = 0.50 | 0.541 | **0.588** | **0.802** | 0.728 ◊ | 14.3% |
308
+
309
+ ◊ There is no B14 row for the λ = 0.50 configuration; the figure is the one recorded for the SLERP
310
+ configuration in the row above. Truncation was not recorded for the SLERP configuration.
311
+
312
+ Against VibeThinker-webAI-trained, TwIL-LM3-Pro is ahead on Track A (macro gate 0.554 against 0.508,
313
+ `macro_primary` 0.588 against 0.579) and on the 14-dataset macro (0.743 against 0.728), and behind
314
+ on the 10-dataset macro (0.790 against 0.802). Against the WiSE-FT λ = 0.50 configuration the two
315
+ are effectively tied on Track A (gate 0.554 against 0.541, `macro_primary` equal at 0.588, both
316
+ within sampling noise at n = 200), and the tuned VibeThinker-3B is ahead on the 10-dataset macro
317
+ with a lower truncation rate. TwIL-LM3-Pro's edge is the 14-dataset macro, a gap that cannot be
318
+ broken down per dataset from the summary values.
319
+
320
+ #### How VibeThinker-webAI-trained differs from the base VibeThinker-3B
321
+
322
+ **Base VibeThinker-3B** is WeiboAI's public checkpoint, unmodified, and is what the untuned columns
323
+ in the tables above measure. **VibeThinker-webAI-trained** starts from those same weights and changes
324
+ them in two ways:
325
+
326
+ * **Formal-logic post-training.** A rank-64 LoRA is trained on the same synthetic formal-logic
327
+ corpus and Track A objectives used for TwIL-LM3-Pro (FOL translation, entailment, semantic
328
+ parsing, Lean formalisation and critique, procedural reasoning, rule induction), with multipath
329
+ distillation supplying the reasoning traces.
330
+ * **Merging back toward the base.** The tuned weights are not used raw. They are merged into the
331
+ pretrained VibeThinker-3B weights with a DARE-SLERP merge (d = 0.5, t = 0.5, the configuration
332
+ labels used in the family tables), the same conservative interpolation step that protects
333
+ held-out capability in TwIL-LM3-Pro.
334
+
335
+ The family tables record no reinforcement-learning (MGPO) run for VibeThinker-3B, so
336
+ VibeThinker-webAI-trained reflects the supervised and merging stages only, whereas TwIL-LM3-Pro also has
337
+ the MGPO stage. It is a reference point for the pipeline, not a checkpoint shipped in this
338
+ repository.
339
+
340
+ What that changes, on the family tables (one source, so the comparison is like for like):
341
+
342
+ | metric | VibeThinker-3B (base) | VibeThinker-webAI-trained | change |
343
+ |---|---:|---:|---:|
344
+ | macro gate | 0.374 | 0.508 | +0.134 |
345
+ | macro_primary | 0.444 | 0.579 | +0.135 |
346
+ | entailment | 0.480 | 0.685 | +0.205 |
347
+ | rule induction | 0.094 | 0.227 | +0.133 |
348
+ | lean_critic | 0.580 | 0.685 | +0.105 |
349
+ | `lm_corpus` perplexity ↓ | 18.70 | 7.35 | 2.5x lower |
350
+ | `math_corpus` perplexity ↓ | 21.80 | 7.00 | 3.1x lower |
351
+ | Track B, 10-dataset macro | 0.815 | 0.802 | −0.013 |
352
+ | Track B, 14-dataset macro | 0.729 | 0.728 | −0.001 |
353
+
354
+ The in-domain gain is large and the held-out change is inside sampling noise at n = 300 per
355
+ dataset, which is the same trade the pipeline makes on Granite 4.2. Two per-dataset shifts are
356
+ worth knowing: BBH-logic rises from 0.609 to 0.829, and IFEval falls from 0.660 to 0.557. Read the
357
+ base column of this table against the family source only; the lane tables above record the same
358
+ weights at a gate of 0.4118 from a separate run.
359
+
360
+ ### Checkpoint selection
361
+
362
+ MGPO checkpoints were compared on both tracks, and step 2580 was published because it has the
363
+ best (or tied-best) held-out score rather than the best in-domain gate:
364
+
365
+ | checkpoint | macro gate | macro_primary | B10 | B14 |
366
+ |---|---:|---:|---:|---:|
367
+ | WiSE-FT α = 0.15 (RL initialiser) | 0.531 | 0.583 | — | — |
368
+ | MGPO step 1200 | **0.569** | **0.598** | 0.7819 | 0.7362 |
369
+ | MGPO step 2000 | 0.557 | 0.581 | 0.7882 | 0.7425 |
370
+ | MGPO step 2200 | 0.567 | 0.583 | 0.7865 | 0.7406 |
371
+ | **MGPO step 2580 (published)** | 0.554 | 0.588 | **0.7901** | **0.7425** |
372
+
373
+ Track A gate here uses the same definition as the tables above (rule induction included).
374
+ Step 1200 leads the gate by 0.015 and `macro_primary` by 0.010, but step 2580 has the highest
375
+ 10-dataset macro and ties step 2000 on the 14-dataset macro (0.7425 for both at four decimals),
376
+ and the differences between the later checkpoints on Track A are within sampling noise at
377
+ n = 200. The checkpoint-selection probe recorded for this release (100 prompts each from FOL
378
+ translation, entailment and math MCQ, eight sampled completions per prompt at
379
+ `temperature = 0.8`, `top_p = 0.95`) gave macro Pass@1 0.4071 and macro Pass@8 0.5567. That probe
380
+ is a selection tool, not a benchmark claim.
381
+
382
+ ## Usage
383
+
384
+ ```python
385
+ import torch
386
+ from transformers import AutoModelForCausalLM, AutoTokenizer
387
+
388
+ model_id = "webAI-Official/TwIL-LM3-Pro"
389
+ tok = AutoTokenizer.from_pretrained(model_id)
390
+ model = AutoModelForCausalLM.from_pretrained(
391
+ model_id, torch_dtype=torch.bfloat16, device_map="auto"
392
+ )
393
+
394
+ messages = [{"role": "user", "content":
395
+ "Does 'All dogs are mammals. Rex is a dog.' entail 'Rex is a mammal'? "
396
+ "Answer entailment, contradiction, or neutral."}]
397
+ inputs = tok.apply_chat_template(
398
+ messages, add_generation_prompt=True,
399
+ return_tensors="pt", return_dict=True,
400
+ ).to(model.device)
401
+
402
+ out = model.generate(**inputs, max_new_tokens=2048, do_sample=False)
403
+ print(tok.decode(out[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True))
404
+ ```
405
+
406
+ `return_dict=True` matters on transformers 5.x, where `apply_chat_template` returns a
407
+ `BatchEncoding` rather than a bare tensor; the above works on both 4.x and 5.x. Use a
408
+ Transformers release with Granite 4.2 support.
409
+
410
+ The reported numbers use **greedy decoding** (`do_sample=False`) and a **2048-token** generation
411
+ budget. Note that the shipped `generation_config.json` enables sampling (`do_sample=true`,
412
+ `temperature=1.0`, `top_p=0.95`), so `do_sample=False` must be passed explicitly to reproduce the
413
+ evaluation. By default the chat template opens a `<think>` block, so the model reasons before it
414
+ answers and a short generation budget truncates that reasoning and scores far worse. The template
415
+ also accepts `enable_thinking=False` (empty think block, lower latency and lower quality on
416
+ reasoning-heavy tasks) and `reasoning_effort="low"` through `chat_template_kwargs`.
417
+
418
+ ### GGUF / llama.cpp
419
+
420
+ Quantized GGUF builds ship in this repository alongside the safetensors weights. The Granite
421
+ architecture is supported by llama.cpp; the model uses a ChatML-style template with `<|im_end|>`
422
+ as EOS, so run it in conversation mode (`-cnv`).
423
+
424
+ | file | quant | size | bits/weight | notes |
425
+ |---|---|---:|---:|---|
426
+ | `TwIL-LM3-Pro-Q4_0.gguf` | Q4_0 | 1.98 GiB | 4.65 | for the Snapdragon Hexagon NPU via GenieX (see below) |
427
+ | `TwIL-LM3-Pro-Q4_K_M.gguf` | Q4_K_M | 2.09 GiB | 4.91 | recommended default; runs on CPU or 4 GB of VRAM |
428
+ | `TwIL-LM3-Pro-Q5_K_M.gguf` | Q5_K_M | 2.43 GiB | 5.71 | a little more headroom than Q4_K_M |
429
+ | `TwIL-LM3-Pro-Q6_K.gguf` | Q6_K | 2.80 GiB | 6.57 | close to Q8_0 quality at about three-quarters the size |
430
+ | `TwIL-LM3-Pro-Q8_0.gguf` | Q8_0 | 3.63 GiB | 8.51 | near-lossless, for quality-sensitive use |
431
+ | `TwIL-LM3-Pro-F16.gguf` | F16 | 6.82 GiB | 16.01 | unquantized, for requantization or reference runs |
432
+
433
+ ```bash
434
+ llama-cli -hf webAI-Official/TwIL-LM3-Pro:Q4_K_M -cnv --temp 0 -n 2048
435
+ ```
436
+
437
+ Two things matter for reproducing the scores above under llama.cpp. Pass `--temp 0`, because the
438
+ evaluation is greedy while the packaged sampling defaults are not. And leave the generation
439
+ budget large — 2048 tokens or more — since the model emits a `<think>` block before answering
440
+ and a short budget truncates it, which costs far more accuracy than the quantization does.
441
+
442
+ F16 and Q8_0 were produced directly by `convert_hf_to_gguf.py` from the released bf16 weights; the
443
+ K-quants (Q4_K_M, Q5_K_M, Q6_K) and Q4_0 were quantized from the F16 build with `llama-quantize`,
444
+ without an importance matrix. F16 is not bit-identical to the released weights: bf16 and f16 carry the
445
+ same 16 bits but trade exponent range against mantissa precision, so the conversion is a
446
+ narrowing one, in practice negligible for inference.
447
+
448
+ The published Track A and Track B numbers were measured on the **bf16** weights through vLLM, not
449
+ on any of these GGUF builds, so expect small deviations — most likely at Q4_K_M and Q4_0 — that
450
+ have not been quantified here.
451
+
452
+ ### Snapdragon NPU / GenieX
453
+
454
+ The Q4_0 build is the one to use with [GenieX](https://github.com/qualcomm/GenieX) on Snapdragon
455
+ devices (for example Snapdragon X Elite / X2 Elite), since Q4_0 has the best Hexagon NPU support in
456
+ its llama.cpp runtime.
457
+
458
+ ```bash
459
+ geniex infer webAI-Official/TwIL-LM3-Pro:Q4_0 --nctx 16384
460
+ ```
461
+
462
+ ```python
463
+ from geniex import AutoModelForCausalLM
464
+
465
+ model = AutoModelForCausalLM.from_pretrained(
466
+ "webAI-Official/TwIL-LM3-Pro", precision="Q4_0", n_ctx=16384
467
+ )
468
+ ```
469
+
470
+ Set the context explicitly: GenieX defaults to a 4,096-token window for GGUF models, which is too
471
+ short for this model's `<think>` blocks (1,902 tokens on average on Track A). The GGUF carries the
472
+ full 131,072-token context, and on the NPU GenieX stores the KV cache in Q8_0, at about 42 KiB per
473
+ token — roughly 0.7 GiB at 16k and 1.3 GiB at 32k on top of the weights. As above, scores were
474
+ measured inside an 8,192-token window, and this build has not yet been benchmarked on device.
475
+
476
+ ## How it was built
477
+
478
+ Five stages on top of the base model:
479
+
480
+ 1. **LoRA supervised fine-tuning** on a synthetic formal-logic corpus covering the Track A
481
+ objectives (first-order-logic translation, entailment labelling, semantic parsing, Lean
482
+ formalisation and critique, procedural reasoning, rule induction).
483
+ 2. **Multipath Distillation** to generate different reasoning traces from a given input prompt.
484
+ 3. **Checkpoint fusion** — parameter-space averaging of intermediate SFT checkpoints, rather
485
+ than taking the final checkpoint.
486
+ 4. **WiSE-FT interpolation** along with **TIES** and **DARE-SLERP** merging toward the pretrained base. This conservative
487
+ interpolation is the direct reason held-out capability survives.
488
+ 5. **MGPO + Contrastive step loss** — entropy-weighted GRPO reinforcement learning against a programmatic verifier, with
489
+ partial credit for loose matches and token-F1 so that all-fail prompt groups still produce
490
+ gradient. Group size 16, learning rate 5e-6, sampling temperature 1.0, top-p 0.95,
491
+ γ = 3.0. The run was resumed at step 800 with β = 0.02 and trained through step 2580, and the
492
+ published checkpoint is **step 2580**. This release is the merged policy, not a LoRA adapter.
493
+
494
+ ## One pipeline, several models
495
+
496
+ The recipe above is not specific to Granite 4.2. Each stage takes a base checkpoint, the shared
497
+ formal-logic corpus and the programmatic verifier as inputs and hands the next stage a checkpoint
498
+ of the same shape, so pointing the pipeline at a different base model does not change its
499
+ structure. In the internal family comparison, the same rank-64 LoRA stage and the same merge
500
+ families (WiSE-FT, DARE, SLERP) were run on five bases that differ in vocabulary, pretraining and
501
+ size: an earlier Granite, SmolLM3, the TwIL base, VibeThinker-3B (151,936-token vocabulary) and
502
+ Granite 4.2 (100,352). The MGPO stage was run on the two Granite bases.
503
+
504
+ The one setting that is chosen per model is the merge coefficient, picked by a sweep over held-out
505
+ performance: the best WiSE-FT weight is 0.15 for SmolLM3, 0.20 for Granite and the TwIL base, and
506
+ 0.50 for VibeThinker-3B, which needs to keep far more of the tuned weights than the others do.
507
+
508
+ | base model | Track A macro gate (base → tuned) | Track B 10-dataset macro (base → tuned) |
509
+ |---|---:|---:|
510
+ | Granite | 0.309 → 0.454 | 0.777 → 0.786 |
511
+ | SmolLM3 | 0.344 → 0.446 | 0.723 → 0.736 |
512
+ | TwIL base | 0.423 → 0.435 | 0.729 → 0.716 |
513
+ | VibeThinker-3B | 0.374 → 0.541 | 0.810 → 0.802 |
514
+ | Granite 4.2 (this model)| 0.4313 → 0.5539 | 0.7942 → 0.7901 |
515
+
516
+ Track A improves on every base, from +0.012 to +0.167, and the Track B change stays within ±0.013,
517
+ inside sampling noise at n = 300 per dataset. The first four rows are from the family comparison
518
+ tables and the last from the paired run described under [Results](#results), so the base gates
519
+ are only comparable within a row. Reinforcement learning was applied only to the Granite bases
520
+ here, so the other rows show what the supervised and merging stages achieve without it.
521
+
522
+ ## Limitations and caveats
523
+
524
+
525
+ **Verbose by construction.** Track A generations average 1,902 tokens and Track B generations
526
+ about 792, so cost per answer is substantially higher than the TwIL-LM family (564 and 482 tokens)
527
+ even though quality per answer is higher on Track A.
528
+
529
+ **Scope.** Tuned for formal logic. The Track B suite does not cover code generation or tool use
530
+ (HumanEval, LiveCodeBench and BFCL were not run for this model or its base), so this release
531
+ makes no claim about those. The weak absolute areas inside the specialisation are FOL translation
532
+ (exact match 0.0100), `procedural` (strict 0.1200) and semantic parsing exact match (0.0000);
533
+ `rule_induction` parses only 56.5% of outputs.
534
+
535
+ **Comparability.** For Track A, TwIL-LM3-Pro, its base, VibeThinker-3B, Qwen3.5-4B, Qwen3-8B, LFM2-2.6B,
536
+ LFM2.5-8B-A1B and Llama-3.2-3B were checked to share the same sampled-row manifest and dataset
537
+ hash, seed and decoding; the TwIL-LM3 and gpt-oss-120b values are carried over from the TwIL-LM3
538
+ card, which describes the same harness. For Track B, the arms checked (including VibeThinker-3B
539
+ and Qwen3.5-4B, on all 18 tasks) share the same sampled rows and decoding, but the serving engine differs between
540
+ arms (vLLM 0.19.1 for TwIL-LM3-Pro, its base, Qwen3.5-4B, Qwen3-8B and LFM2.5-8B-A1B; vLLM 0.11.2 for
541
+ TwIL-LM3, Llama-3.2-3B and VibeThinker-3B), and the engine version is part of the protocol hash.
542
+ The VibeThinker-webAI-trained column (★) comes from the internal family comparison tables and is not
543
+ covered by the manifest checks described here. Throughput has its own, separate engine caveat (see the † note under the Track A table). With
544
+ n = 200 per lane on Track A and n = 300 per dataset on Track B, differences of two to three points
545
+ are within sampling noise.
546
+
547
+ ## Evaluation protocol
548
+
549
+ - Track A: `n = 200` per objective, greedy (`temperature = 0`), `max_new_tokens = 2048`, one
550
+ retry at 4096 for truncated rows, `max_seq_len = 8192`, seed 42, default (thinking-enabled)
551
+ chat template.
552
+ - Track B: 300 examples per task, greedy, `max_gen_toks = 4096`, `max_model_len = 8192`,
553
+ `repetition_penalty = 1.0`, chat template applied with thinking disabled, vLLM backend.
554
+ - Both tracks use the same protocol for the model and its base, in a paired run over identical
555
+ sampled rows.
556
+ - Throughput: 128 prompts drawn from a fixed Track A prompt file, 512 generated tokens each with
557
+ EOS ignored, greedy, vLLM `gpu_memory_utilization` 0.45, `max_model_len` 4096, on an otherwise
558
+ idle GPU (a single H200 for the TwIL-LM3-Pro, base and VibeThinker-3B runs); the reported rate is generated tokens over decode time, excluding engine start-up and
559
+ compilation.
560
+
561
+ `repetition_penalty = 1.0` is load-bearing. A 1.1 penalty produced apparent 20-point swings on
562
+ Track B that were pure decoding artefact; the decoding kwargs are hashed into the protocol
563
+ identity so a mismatched runner fails loudly instead of quietly producing a different number.
564
+
565
+ ## Relationship to TwIL-LM
566
+
567
+ TwIL-LM3-Pro applies the same post-training pipeline as the
568
+ [TwIL-LM3](https://huggingface.co/webAI-Official/TwIL-LM3) and TwIL-LM family — LoRA SFT,
569
+ checkpoint fusion, WiSE-FT and MGPO — to a different base, IBM's Granite 4.2 3B, instead of
570
+ SmolLM3 or SmolLM2 with some additional mechanisms. Compared with TwIL-LM3 it is a stronger in-domain model (macro gate 0.5539
571
+ against 0.4218) and a stronger held-out one (10-dataset macro 0.7901 against 0.7339), at the
572
+ price of much longer generations and a much higher truncation rate. Like the TwIL-LM models, it
573
+ ships as a full merged model on `main`, loaded directly with `AutoModelForCausalLM`.
574
+
575
+ ## License and attribution
576
+
577
+ Released under the **webAI Non-Commercial License ver. 1.0** — see `LICENSE.md` in this
578
+ repository.
579
+
580
+ The base model, [`ibm-granite/granite-4.2-3b`](https://huggingface.co/ibm-granite/granite-4.2-3b),
581
+ is Copyright IBM Corporation and is distributed under the Apache License 2.0; its licence text is
582
+ retained as `apache-2.0-LICENSE.txt` and all credit for the base model goes to IBM. Apache 2.0
583
+ permits distributing derivative works under different terms provided attribution is preserved,
584
+ which is what the pair of licence files in this repository does.
TwIL-LM3-Pro-F16.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:79e217f2b616c17993f4005f91222c41e3eaa42376bc4f91077daa5bf1d84b81
3
+ size 7323461056
TwIL-LM3-Pro-Q4_0.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:db09635d997275fc07d0df12ea3ab43aa7fe03fa612e061d904581583e9dbbcf
3
+ size 2129118656
TwIL-LM3-Pro-Q4_K_M.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8a7e0f48af1feea9a107e17e2c03e8ad8d0c397c47a5dae4a73b3d92e3533377
3
+ size 2244011744
TwIL-LM3-Pro-Q5_K_M.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7c367c005c5fb8af641434165220d476352704860bd1f66fd61dd0cf56936d4d
3
+ size 2613634496
TwIL-LM3-Pro-Q6_K.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0d1c2333e2bc60840f1e6df63cef935b0d1d0434e98c8b5f0e4fb20f2c3a6a63
3
+ size 3006358976
TwIL-LM3-Pro-Q8_0.gguf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4b4ba4a94bc5cbe4783f43be3ae428be9b5d9e3dffb725c36ae4908d27067906
3
+ size 3892651456
apache-2.0-LICENSE.txt ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
benchmarks.png ADDED

Git LFS Details

  • SHA256: 97640dc089cdcf2894f1f5c0f9277a40773d842d777e6f14dd7a59f76fb66780
  • Pointer size: 131 Bytes
  • Size of remote file: 136 kB
chat_template.jinja ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- macro tool_to_json(tool) -%}
2
+ {%- set ns_tool = namespace(first=true) -%}
3
+ {{- '{' -}}
4
+ {%- for k, v in tool.items() -%}
5
+ {%- if k != 'defer_loading' and k != 'strict' -%}
6
+ {%- if not ns_tool.first -%}{{- ', ' -}}{%- endif -%}
7
+ {%- set ns_tool.first = false -%}
8
+ {{- '"' ~ k ~ '": ' ~ (v | tojson(ensure_ascii=False)) -}}
9
+ {%- endif -%}
10
+ {%- endfor -%}
11
+ {{- '}' -}}
12
+ {%- endmacro -%}
13
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else True %}
14
+ {%- set low_effort = low_effort if low_effort is defined else False %}
15
+ {%- if reasoning_effort is defined and reasoning_effort is not none %}
16
+ {%- set low_effort = reasoning_effort == "low" %}
17
+ {%- endif %}
18
+ {%- set truncate_history_thinking = truncate_history_thinking if truncate_history_thinking is defined else True %}
19
+
20
+ {%- set ns = namespace(last_user_idx = -1) %}
21
+ {%- set loop_messages = messages %}
22
+ {%- for m in loop_messages %}
23
+ {%- if m["role"] == "user" %}
24
+ {%- set ns.last_user_idx = loop.index0 %}
25
+ {%- endif %}
26
+ {%- endfor %}
27
+
28
+ {%- if messages[0]["role"] == "system" %}
29
+ {%- set system_message = messages[0]["content"] %}
30
+ {%- set loop_messages = messages[1:] %}
31
+ {%- else %}
32
+ {%- set system_message = "" %}
33
+ {%- set loop_messages = messages %}
34
+ {%- endif %}
35
+ {%- if not tools is defined %}
36
+ {%- set tools = [] %}
37
+ {%- endif %}
38
+ {# Recompute last_user_idx relative to loop_messages after handling system #}
39
+ {%- set ns = namespace(last_user_idx = -1) %}
40
+ {%- for m in loop_messages %}
41
+ {%- if m["role"] == "user" %}
42
+ {%- set ns.last_user_idx = loop.index0 %}
43
+ {%- endif %}
44
+ {%- endfor %}
45
+ {%- if system_message is defined %}
46
+ {{- "<|im_start|>system\n" + system_message }}
47
+ {%- else %}
48
+ {%- if tools is iterable and tools | length > 0 %}
49
+ {{- "<|im_start|>system\n" }}
50
+ {%- endif %}
51
+ {%- endif %}
52
+ {%- if tools is iterable and tools | length > 0 %}
53
+ {%- if system_message is defined and system_message | length > 0 %}
54
+ {{- "\n\n" }}
55
+ {%- endif %}
56
+ {{- "# Tools\n\nYou have access to the following functions:\n\n" }}
57
+ {{- "<tools>" }}
58
+ {%- for tool in tools %}
59
+ {%- if tool.function is defined %}
60
+ {%- set tool = tool.function %}
61
+ {%- endif %}
62
+ {%- if tool.defer_loading is not defined or not tool.defer_loading %}
63
+ {{- '\n' ~ tool_to_json(tool) }}
64
+ {%- endif %}
65
+ {%- endfor %}
66
+ {{- "\n</tools>" }}
67
+
68
+ {{- '\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>' }}
69
+ {%- endif %}
70
+
71
+
72
+ {%- if system_message is defined %}
73
+ {{- '<|im_end|>\n' }}
74
+ {%- else %}
75
+ {%- if tools is iterable and tools | length > 0 %}
76
+ {{- '<|im_end|>\n' }}
77
+ {%- endif %}
78
+ {%- endif %}
79
+
80
+ {%- for message in loop_messages %}
81
+ {%- if message.role == "assistant" %}
82
+ {# Add reasoning content in to content field for unified processing below. #}
83
+ {%- if message.reasoning_content is defined and message.reasoning_content is string and message.reasoning_content | trim | length > 0 %}
84
+ {%- set content = "<think>\n" ~ message.reasoning_content ~ "\n</think>\n" ~ (message.content | default('', true)) %}
85
+ {%- else %}
86
+ {%- set content = message.content | default('', true) %}
87
+ {%- if content is string -%}
88
+ {# Allow downstream logic to to take care of broken thought, only handle coherent reasoning here. #}
89
+ {%- if '<think>' not in content and '</think>' not in content -%}
90
+ {%- set content = "<think></think>" ~ content -%}
91
+ {%- endif -%}
92
+ {%- else -%}
93
+ {%- set content = content -%}
94
+ {%- endif -%}
95
+ {%- endif %}
96
+ {%- if message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}
97
+ {# Assistant message has tool calls. #}
98
+ {{- '<|im_start|>assistant\n' }}
99
+ {%- set include_content = not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
100
+ {%- if content is string and content | trim | length > 0 %}
101
+ {%- if include_content %}
102
+ {{- (content | trim) ~ '\n' -}}
103
+ {%- else %}
104
+ {%- set c = (content | string) %}
105
+ {%- if '</think>' in c %}
106
+ {# Keep only content after the last closing think. Also generation prompt causes this. #}
107
+ {%- set c = c.split('</think>')[-1] %}
108
+ {%- elif '<think>' in c %}
109
+ {# If <think> was opened but never closed, drop the trailing think segment #}
110
+ {%- set c = c.split('<think>')[0] %}
111
+ {%- endif %}
112
+ {%- set c = "<think></think>" ~ c | trim %}
113
+ {%- if c | length > 0 %}
114
+ {{- c ~ '\n' -}}
115
+ {%- endif %}
116
+ {%- endif %}
117
+ {%- else %}
118
+ {{- "<think></think>" -}}
119
+ {%- endif %}
120
+ {%- for tool_call in message.tool_calls %}
121
+ {%- if tool_call.function is defined %}
122
+ {%- set tool_call = tool_call.function %}
123
+ {%- endif %}
124
+ {{- '<tool_call>\n<function=' ~ tool_call.name ~ '>\n' -}}
125
+ {%- if tool_call.arguments is defined %}
126
+ {%- for args_name, args_value in tool_call.arguments|items %}
127
+ {{- '<parameter=' ~ args_name ~ '>\n' -}}
128
+ {%- 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 %}
129
+ {{- args_value ~ '\n</parameter>\n' -}}
130
+ {%- endfor %}
131
+ {%- endif %}
132
+ {{- '</function>\n</tool_call>\n' -}}
133
+ {%- endfor %}
134
+ {{- '<|im_end|>\n' }}
135
+ {%- else %}
136
+ {# Assistant message doesn't have tool calls. #}
137
+ {%- if not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
138
+ {{- '<|im_start|>assistant\n' ~ (content | default('', true) | string | trim) ~ '<|im_end|>\n' }}
139
+ {%- else %}
140
+ {%- set c = (content | default('', true) | string) %}
141
+ {%- if '<think>' in c and '</think>' in c %}
142
+ {%- set c = "<think></think>" ~ c.split('</think>')[-1] %}
143
+ {%- endif %}
144
+ {%- set c = c | trim %}
145
+ {%- if c | length > 0 %}
146
+ {{- '<|im_start|>assistant\n' ~ c ~ '<|im_end|>\n' }}
147
+ {%- else %}
148
+ {{- '<|im_start|>assistant\n<|im_end|>\n' }}
149
+ {%- endif %}
150
+ {%- endif %}
151
+ {%- endif %}
152
+ {%- elif message.role == "user" or message.role == "system" %}
153
+ {{- '<|im_start|>' + message.role + '\n' }}
154
+ {%- set content = message.content | string %}
155
+ {%- if message.role == "user" and loop.index0 == ns.last_user_idx and low_effort %}
156
+ {{- content + '\n\n{reasoning effort: low}' }}
157
+ {%- else %}
158
+ {{- content }}
159
+ {%- endif %}
160
+ {{- '<|im_end|>\n' }}
161
+ {%- elif message.role == "tool" %}
162
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
163
+ {{- '<|im_start|>user\n' }}
164
+ {%- endif %}
165
+ {{- '<tool_response>\n' }}
166
+ {{- message.content }}
167
+ {{- '\n</tool_response>\n' }}
168
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
169
+ {{- '<|im_end|>\n' }}
170
+ {%- elif loop.last %}
171
+ {{- '<|im_end|>\n' }}
172
+ {%- endif %}
173
+ {%- else %}
174
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }}
175
+ {%- endif %}
176
+ {%- endfor %}
177
+
178
+ {%- if add_generation_prompt %}
179
+ {%- if enable_thinking %}
180
+ {{- '<|im_start|>assistant\n<think>\n' }}
181
+ {%- else %}
182
+ {{- '<|im_start|>assistant\n<think></think>' }}
183
+ {%- endif %}
184
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "GraniteForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "attention_multiplier": 0.015625,
8
+ "bos_token_id": 100283,
9
+ "dtype": "bfloat16",
10
+ "embedding_multiplier": 1.0,
11
+ "eos_token_id": 100257,
12
+ "hidden_act": "silu",
13
+ "hidden_size": 2560,
14
+ "initializer_range": 0.1,
15
+ "intermediate_size": 8192,
16
+ "logits_scaling": 1.0,
17
+ "max_position_embeddings": 131072,
18
+ "mlp_bias": false,
19
+ "model_type": "granite",
20
+ "num_attention_heads": 40,
21
+ "num_hidden_layers": 40,
22
+ "num_key_value_heads": 8,
23
+ "pad_token_id": 100257,
24
+ "residual_multiplier": 1.0,
25
+ "rms_norm_eps": 1e-05,
26
+ "rope_parameters": {
27
+ "rope_theta": 10000000,
28
+ "rope_type": "default"
29
+ },
30
+ "tie_word_embeddings": false,
31
+ "transformers_version": "5.15.0",
32
+ "use_cache": false,
33
+ "vocab_size": 100352
34
+ }
generation_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 100283,
4
+ "do_sample": true,
5
+ "eos_token_id": [
6
+ 100257
7
+ ],
8
+ "pad_token_id": 100257,
9
+ "temperature": 1.0,
10
+ "top_p": 0.95,
11
+ "transformers_version": "5.15.0"
12
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:217bd76d3f59eff93f7d71119788f4d371f19c0a9899af2822e9162b74b13954
3
+ size 7319517272
special_tokens_map.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "<|im_end|>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<|im_end|>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "unk_token": {
24
+ "content": "<unk>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ }
30
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,784 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "bos_token": "<s>",
4
+ "clean_up_tokenization_spaces": false,
5
+ "eos_token": "<|im_end|>",
6
+ "errors": "replace",
7
+ "local_files_only": false,
8
+ "model_max_length": 131072,
9
+ "pad_token": "<|im_end|>",
10
+ "padding_side": "left",
11
+ "tokenizer_class": "PreTrainedTokenizerFast",
12
+ "unk_token": "<unk>",
13
+ "added_tokens_decoder": {
14
+ "100256": {
15
+ "content": "<|im_start|>",
16
+ "lstrip": false,
17
+ "normalized": false,
18
+ "rstrip": false,
19
+ "single_word": false,
20
+ "special": true
21
+ },
22
+ "100257": {
23
+ "content": "<|im_end|>",
24
+ "lstrip": false,
25
+ "normalized": false,
26
+ "rstrip": false,
27
+ "single_word": false,
28
+ "special": true
29
+ },
30
+ "100258": {
31
+ "content": "<|fim_prefix|>",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false,
36
+ "special": false
37
+ },
38
+ "100259": {
39
+ "content": "<|fim_middle|>",
40
+ "lstrip": false,
41
+ "normalized": false,
42
+ "rstrip": false,
43
+ "single_word": false,
44
+ "special": false
45
+ },
46
+ "100260": {
47
+ "content": "<|fim_suffix|>",
48
+ "lstrip": false,
49
+ "normalized": false,
50
+ "rstrip": false,
51
+ "single_word": false,
52
+ "special": false
53
+ },
54
+ "100261": {
55
+ "content": "<|fim_pad|>",
56
+ "lstrip": false,
57
+ "normalized": false,
58
+ "rstrip": false,
59
+ "single_word": false,
60
+ "special": false
61
+ },
62
+ "100262": {
63
+ "content": "<|filename|>",
64
+ "lstrip": false,
65
+ "normalized": false,
66
+ "rstrip": false,
67
+ "single_word": false,
68
+ "special": false
69
+ },
70
+ "100263": {
71
+ "content": "<|reponame|>",
72
+ "lstrip": false,
73
+ "normalized": false,
74
+ "rstrip": false,
75
+ "single_word": false,
76
+ "special": false
77
+ },
78
+ "100264": {
79
+ "content": "<|unused_11|>",
80
+ "lstrip": false,
81
+ "normalized": false,
82
+ "rstrip": false,
83
+ "single_word": false,
84
+ "special": true
85
+ },
86
+ "100265": {
87
+ "content": "<|unused_12|>",
88
+ "lstrip": false,
89
+ "normalized": false,
90
+ "rstrip": false,
91
+ "single_word": false,
92
+ "special": true
93
+ },
94
+ "100266": {
95
+ "content": "<|unused_13|>",
96
+ "lstrip": false,
97
+ "normalized": false,
98
+ "rstrip": false,
99
+ "single_word": false,
100
+ "special": true
101
+ },
102
+ "100267": {
103
+ "content": "<|unused_14|>",
104
+ "lstrip": false,
105
+ "normalized": false,
106
+ "rstrip": false,
107
+ "single_word": false,
108
+ "special": true
109
+ },
110
+ "100268": {
111
+ "content": "<|unused_15|>",
112
+ "lstrip": false,
113
+ "normalized": false,
114
+ "rstrip": false,
115
+ "single_word": false,
116
+ "special": true
117
+ },
118
+ "100269": {
119
+ "content": "<unk>",
120
+ "lstrip": false,
121
+ "normalized": false,
122
+ "rstrip": false,
123
+ "single_word": false,
124
+ "special": true
125
+ },
126
+ "100270": {
127
+ "content": "<tool_call>",
128
+ "lstrip": false,
129
+ "normalized": false,
130
+ "rstrip": false,
131
+ "single_word": false,
132
+ "special": false
133
+ },
134
+ "100271": {
135
+ "content": "</tool_call>",
136
+ "lstrip": false,
137
+ "normalized": false,
138
+ "rstrip": false,
139
+ "single_word": false,
140
+ "special": false
141
+ },
142
+ "100272": {
143
+ "content": "<tool_response>",
144
+ "lstrip": false,
145
+ "normalized": false,
146
+ "rstrip": false,
147
+ "single_word": false,
148
+ "special": false
149
+ },
150
+ "100273": {
151
+ "content": "</tool_response>",
152
+ "lstrip": false,
153
+ "normalized": false,
154
+ "rstrip": false,
155
+ "single_word": false,
156
+ "special": false
157
+ },
158
+ "100274": {
159
+ "content": "<think>",
160
+ "lstrip": false,
161
+ "normalized": false,
162
+ "rstrip": false,
163
+ "single_word": false,
164
+ "special": false
165
+ },
166
+ "100275": {
167
+ "content": "</think>",
168
+ "lstrip": false,
169
+ "normalized": false,
170
+ "rstrip": false,
171
+ "single_word": false,
172
+ "special": false
173
+ },
174
+ "100276": {
175
+ "content": "[INST]",
176
+ "lstrip": false,
177
+ "normalized": false,
178
+ "rstrip": false,
179
+ "single_word": false,
180
+ "special": true
181
+ },
182
+ "100277": {
183
+ "content": "[/INST]",
184
+ "lstrip": false,
185
+ "normalized": false,
186
+ "rstrip": false,
187
+ "single_word": false,
188
+ "special": true
189
+ },
190
+ "100278": {
191
+ "content": "[AVAILABLE_TOOLS]",
192
+ "lstrip": false,
193
+ "normalized": false,
194
+ "rstrip": false,
195
+ "single_word": false,
196
+ "special": true
197
+ },
198
+ "100279": {
199
+ "content": "[/AVAILABLE_TOOLS]",
200
+ "lstrip": false,
201
+ "normalized": false,
202
+ "rstrip": false,
203
+ "single_word": false,
204
+ "special": true
205
+ },
206
+ "100280": {
207
+ "content": "[TOOL_RESULTS]",
208
+ "lstrip": false,
209
+ "normalized": false,
210
+ "rstrip": false,
211
+ "single_word": false,
212
+ "special": true
213
+ },
214
+ "100281": {
215
+ "content": "[/TOOL_RESULTS]",
216
+ "lstrip": false,
217
+ "normalized": false,
218
+ "rstrip": false,
219
+ "single_word": false,
220
+ "special": true
221
+ },
222
+ "100282": {
223
+ "content": "[TOOL_CALLS]",
224
+ "lstrip": false,
225
+ "normalized": false,
226
+ "rstrip": false,
227
+ "single_word": false,
228
+ "special": true
229
+ },
230
+ "100283": {
231
+ "content": "<s>",
232
+ "lstrip": false,
233
+ "normalized": false,
234
+ "rstrip": false,
235
+ "single_word": false,
236
+ "special": true
237
+ },
238
+ "100284": {
239
+ "content": "</s>",
240
+ "lstrip": false,
241
+ "normalized": false,
242
+ "rstrip": false,
243
+ "single_word": false,
244
+ "special": true
245
+ },
246
+ "100285": {
247
+ "content": "<|unused_16|>",
248
+ "lstrip": false,
249
+ "normalized": false,
250
+ "rstrip": false,
251
+ "single_word": false,
252
+ "special": true
253
+ },
254
+ "100286": {
255
+ "content": "<|unused_17|>",
256
+ "lstrip": false,
257
+ "normalized": false,
258
+ "rstrip": false,
259
+ "single_word": false,
260
+ "special": true
261
+ },
262
+ "100287": {
263
+ "content": "<|unused_18|>",
264
+ "lstrip": false,
265
+ "normalized": false,
266
+ "rstrip": false,
267
+ "single_word": false,
268
+ "special": true
269
+ },
270
+ "100288": {
271
+ "content": "<|unused_19|>",
272
+ "lstrip": false,
273
+ "normalized": false,
274
+ "rstrip": false,
275
+ "single_word": false,
276
+ "special": true
277
+ },
278
+ "100289": {
279
+ "content": "<|unused_20|>",
280
+ "lstrip": false,
281
+ "normalized": false,
282
+ "rstrip": false,
283
+ "single_word": false,
284
+ "special": true
285
+ },
286
+ "100290": {
287
+ "content": "<|unused_21|>",
288
+ "lstrip": false,
289
+ "normalized": false,
290
+ "rstrip": false,
291
+ "single_word": false,
292
+ "special": true
293
+ },
294
+ "100291": {
295
+ "content": "<|unused_22|>",
296
+ "lstrip": false,
297
+ "normalized": false,
298
+ "rstrip": false,
299
+ "single_word": false,
300
+ "special": true
301
+ },
302
+ "100292": {
303
+ "content": "<|unused_23|>",
304
+ "lstrip": false,
305
+ "normalized": false,
306
+ "rstrip": false,
307
+ "single_word": false,
308
+ "special": true
309
+ },
310
+ "100293": {
311
+ "content": "<|unused_24|>",
312
+ "lstrip": false,
313
+ "normalized": false,
314
+ "rstrip": false,
315
+ "single_word": false,
316
+ "special": true
317
+ },
318
+ "100294": {
319
+ "content": "<|unused_25|>",
320
+ "lstrip": false,
321
+ "normalized": false,
322
+ "rstrip": false,
323
+ "single_word": false,
324
+ "special": true
325
+ },
326
+ "100295": {
327
+ "content": "<|unused_26|>",
328
+ "lstrip": false,
329
+ "normalized": false,
330
+ "rstrip": false,
331
+ "single_word": false,
332
+ "special": true
333
+ },
334
+ "100296": {
335
+ "content": "<|unused_27|>",
336
+ "lstrip": false,
337
+ "normalized": false,
338
+ "rstrip": false,
339
+ "single_word": false,
340
+ "special": true
341
+ },
342
+ "100297": {
343
+ "content": "<|unused_28|>",
344
+ "lstrip": false,
345
+ "normalized": false,
346
+ "rstrip": false,
347
+ "single_word": false,
348
+ "special": true
349
+ },
350
+ "100298": {
351
+ "content": "<|unused_29|>",
352
+ "lstrip": false,
353
+ "normalized": false,
354
+ "rstrip": false,
355
+ "single_word": false,
356
+ "special": true
357
+ },
358
+ "100299": {
359
+ "content": "<|unused_30|>",
360
+ "lstrip": false,
361
+ "normalized": false,
362
+ "rstrip": false,
363
+ "single_word": false,
364
+ "special": true
365
+ },
366
+ "100300": {
367
+ "content": "<|unused_31|>",
368
+ "lstrip": false,
369
+ "normalized": false,
370
+ "rstrip": false,
371
+ "single_word": false,
372
+ "special": true
373
+ },
374
+ "100301": {
375
+ "content": "<|unused_32|>",
376
+ "lstrip": false,
377
+ "normalized": false,
378
+ "rstrip": false,
379
+ "single_word": false,
380
+ "special": true
381
+ },
382
+ "100302": {
383
+ "content": "<|unused_33|>",
384
+ "lstrip": false,
385
+ "normalized": false,
386
+ "rstrip": false,
387
+ "single_word": false,
388
+ "special": true
389
+ },
390
+ "100303": {
391
+ "content": "<|unused_34|>",
392
+ "lstrip": false,
393
+ "normalized": false,
394
+ "rstrip": false,
395
+ "single_word": false,
396
+ "special": true
397
+ },
398
+ "100304": {
399
+ "content": "<|unused_35|>",
400
+ "lstrip": false,
401
+ "normalized": false,
402
+ "rstrip": false,
403
+ "single_word": false,
404
+ "special": true
405
+ },
406
+ "100305": {
407
+ "content": "<|unused_36|>",
408
+ "lstrip": false,
409
+ "normalized": false,
410
+ "rstrip": false,
411
+ "single_word": false,
412
+ "special": true
413
+ },
414
+ "100306": {
415
+ "content": "<|unused_37|>",
416
+ "lstrip": false,
417
+ "normalized": false,
418
+ "rstrip": false,
419
+ "single_word": false,
420
+ "special": true
421
+ },
422
+ "100307": {
423
+ "content": "<|unused_38|>",
424
+ "lstrip": false,
425
+ "normalized": false,
426
+ "rstrip": false,
427
+ "single_word": false,
428
+ "special": true
429
+ },
430
+ "100308": {
431
+ "content": "<|unused_39|>",
432
+ "lstrip": false,
433
+ "normalized": false,
434
+ "rstrip": false,
435
+ "single_word": false,
436
+ "special": true
437
+ },
438
+ "100309": {
439
+ "content": "<|unused_40|>",
440
+ "lstrip": false,
441
+ "normalized": false,
442
+ "rstrip": false,
443
+ "single_word": false,
444
+ "special": true
445
+ },
446
+ "100310": {
447
+ "content": "<|unused_41|>",
448
+ "lstrip": false,
449
+ "normalized": false,
450
+ "rstrip": false,
451
+ "single_word": false,
452
+ "special": true
453
+ },
454
+ "100311": {
455
+ "content": "<|unused_42|>",
456
+ "lstrip": false,
457
+ "normalized": false,
458
+ "rstrip": false,
459
+ "single_word": false,
460
+ "special": true
461
+ },
462
+ "100312": {
463
+ "content": "<|unused_43|>",
464
+ "lstrip": false,
465
+ "normalized": false,
466
+ "rstrip": false,
467
+ "single_word": false,
468
+ "special": true
469
+ },
470
+ "100313": {
471
+ "content": "<|unused_44|>",
472
+ "lstrip": false,
473
+ "normalized": false,
474
+ "rstrip": false,
475
+ "single_word": false,
476
+ "special": true
477
+ },
478
+ "100314": {
479
+ "content": "<|unused_45|>",
480
+ "lstrip": false,
481
+ "normalized": false,
482
+ "rstrip": false,
483
+ "single_word": false,
484
+ "special": true
485
+ },
486
+ "100315": {
487
+ "content": "<|unused_46|>",
488
+ "lstrip": false,
489
+ "normalized": false,
490
+ "rstrip": false,
491
+ "single_word": false,
492
+ "special": true
493
+ },
494
+ "100316": {
495
+ "content": "<|unused_47|>",
496
+ "lstrip": false,
497
+ "normalized": false,
498
+ "rstrip": false,
499
+ "single_word": false,
500
+ "special": true
501
+ },
502
+ "100317": {
503
+ "content": "<|unused_48|>",
504
+ "lstrip": false,
505
+ "normalized": false,
506
+ "rstrip": false,
507
+ "single_word": false,
508
+ "special": true
509
+ },
510
+ "100318": {
511
+ "content": "<|unused_49|>",
512
+ "lstrip": false,
513
+ "normalized": false,
514
+ "rstrip": false,
515
+ "single_word": false,
516
+ "special": true
517
+ },
518
+ "100319": {
519
+ "content": "<|unused_50|>",
520
+ "lstrip": false,
521
+ "normalized": false,
522
+ "rstrip": false,
523
+ "single_word": false,
524
+ "special": true
525
+ },
526
+ "100320": {
527
+ "content": "<|unused_51|>",
528
+ "lstrip": false,
529
+ "normalized": false,
530
+ "rstrip": false,
531
+ "single_word": false,
532
+ "special": true
533
+ },
534
+ "100321": {
535
+ "content": "<|unused_52|>",
536
+ "lstrip": false,
537
+ "normalized": false,
538
+ "rstrip": false,
539
+ "single_word": false,
540
+ "special": true
541
+ },
542
+ "100322": {
543
+ "content": "<|unused_53|>",
544
+ "lstrip": false,
545
+ "normalized": false,
546
+ "rstrip": false,
547
+ "single_word": false,
548
+ "special": true
549
+ },
550
+ "100323": {
551
+ "content": "<|unused_54|>",
552
+ "lstrip": false,
553
+ "normalized": false,
554
+ "rstrip": false,
555
+ "single_word": false,
556
+ "special": true
557
+ },
558
+ "100324": {
559
+ "content": "<|unused_55|>",
560
+ "lstrip": false,
561
+ "normalized": false,
562
+ "rstrip": false,
563
+ "single_word": false,
564
+ "special": true
565
+ },
566
+ "100325": {
567
+ "content": "<|unused_56|>",
568
+ "lstrip": false,
569
+ "normalized": false,
570
+ "rstrip": false,
571
+ "single_word": false,
572
+ "special": true
573
+ },
574
+ "100326": {
575
+ "content": "<|unused_57|>",
576
+ "lstrip": false,
577
+ "normalized": false,
578
+ "rstrip": false,
579
+ "single_word": false,
580
+ "special": true
581
+ },
582
+ "100327": {
583
+ "content": "<|unused_58|>",
584
+ "lstrip": false,
585
+ "normalized": false,
586
+ "rstrip": false,
587
+ "single_word": false,
588
+ "special": true
589
+ },
590
+ "100328": {
591
+ "content": "<|unused_59|>",
592
+ "lstrip": false,
593
+ "normalized": false,
594
+ "rstrip": false,
595
+ "single_word": false,
596
+ "special": true
597
+ },
598
+ "100329": {
599
+ "content": "<|unused_60|>",
600
+ "lstrip": false,
601
+ "normalized": false,
602
+ "rstrip": false,
603
+ "single_word": false,
604
+ "special": true
605
+ },
606
+ "100330": {
607
+ "content": "<|unused_61|>",
608
+ "lstrip": false,
609
+ "normalized": false,
610
+ "rstrip": false,
611
+ "single_word": false,
612
+ "special": true
613
+ },
614
+ "100331": {
615
+ "content": "<|unused_62|>",
616
+ "lstrip": false,
617
+ "normalized": false,
618
+ "rstrip": false,
619
+ "single_word": false,
620
+ "special": true
621
+ },
622
+ "100332": {
623
+ "content": "<|unused_63|>",
624
+ "lstrip": false,
625
+ "normalized": false,
626
+ "rstrip": false,
627
+ "single_word": false,
628
+ "special": true
629
+ },
630
+ "100333": {
631
+ "content": "<|unused_64|>",
632
+ "lstrip": false,
633
+ "normalized": false,
634
+ "rstrip": false,
635
+ "single_word": false,
636
+ "special": true
637
+ },
638
+ "100334": {
639
+ "content": "<|unused_65|>",
640
+ "lstrip": false,
641
+ "normalized": false,
642
+ "rstrip": false,
643
+ "single_word": false,
644
+ "special": true
645
+ },
646
+ "100335": {
647
+ "content": "<|unused_66|>",
648
+ "lstrip": false,
649
+ "normalized": false,
650
+ "rstrip": false,
651
+ "single_word": false,
652
+ "special": true
653
+ },
654
+ "100336": {
655
+ "content": "<|unused_67|>",
656
+ "lstrip": false,
657
+ "normalized": false,
658
+ "rstrip": false,
659
+ "single_word": false,
660
+ "special": true
661
+ },
662
+ "100337": {
663
+ "content": "<|unused_68|>",
664
+ "lstrip": false,
665
+ "normalized": false,
666
+ "rstrip": false,
667
+ "single_word": false,
668
+ "special": true
669
+ },
670
+ "100338": {
671
+ "content": "<|unused_69|>",
672
+ "lstrip": false,
673
+ "normalized": false,
674
+ "rstrip": false,
675
+ "single_word": false,
676
+ "special": true
677
+ },
678
+ "100339": {
679
+ "content": "<|unused_70|>",
680
+ "lstrip": false,
681
+ "normalized": false,
682
+ "rstrip": false,
683
+ "single_word": false,
684
+ "special": true
685
+ },
686
+ "100340": {
687
+ "content": "<|unused_71|>",
688
+ "lstrip": false,
689
+ "normalized": false,
690
+ "rstrip": false,
691
+ "single_word": false,
692
+ "special": true
693
+ },
694
+ "100341": {
695
+ "content": "<|unused_72|>",
696
+ "lstrip": false,
697
+ "normalized": false,
698
+ "rstrip": false,
699
+ "single_word": false,
700
+ "special": true
701
+ },
702
+ "100342": {
703
+ "content": "<|unused_73|>",
704
+ "lstrip": false,
705
+ "normalized": false,
706
+ "rstrip": false,
707
+ "single_word": false,
708
+ "special": true
709
+ },
710
+ "100343": {
711
+ "content": "<|unused_74|>",
712
+ "lstrip": false,
713
+ "normalized": false,
714
+ "rstrip": false,
715
+ "single_word": false,
716
+ "special": true
717
+ },
718
+ "100344": {
719
+ "content": "<|unused_75|>",
720
+ "lstrip": false,
721
+ "normalized": false,
722
+ "rstrip": false,
723
+ "single_word": false,
724
+ "special": true
725
+ },
726
+ "100345": {
727
+ "content": "<|unused_76|>",
728
+ "lstrip": false,
729
+ "normalized": false,
730
+ "rstrip": false,
731
+ "single_word": false,
732
+ "special": true
733
+ },
734
+ "100346": {
735
+ "content": "<|unused_77|>",
736
+ "lstrip": false,
737
+ "normalized": false,
738
+ "rstrip": false,
739
+ "single_word": false,
740
+ "special": true
741
+ },
742
+ "100347": {
743
+ "content": "<|unused_78|>",
744
+ "lstrip": false,
745
+ "normalized": false,
746
+ "rstrip": false,
747
+ "single_word": false,
748
+ "special": true
749
+ },
750
+ "100348": {
751
+ "content": "<|unused_79|>",
752
+ "lstrip": false,
753
+ "normalized": false,
754
+ "rstrip": false,
755
+ "single_word": false,
756
+ "special": true
757
+ },
758
+ "100349": {
759
+ "content": "<|unused_80|>",
760
+ "lstrip": false,
761
+ "normalized": false,
762
+ "rstrip": false,
763
+ "single_word": false,
764
+ "special": true
765
+ },
766
+ "100350": {
767
+ "content": "<|unused_81|>",
768
+ "lstrip": false,
769
+ "normalized": false,
770
+ "rstrip": false,
771
+ "single_word": false,
772
+ "special": true
773
+ },
774
+ "100351": {
775
+ "content": "<|unused_82|>",
776
+ "lstrip": false,
777
+ "normalized": false,
778
+ "rstrip": false,
779
+ "single_word": false,
780
+ "special": true
781
+ }
782
+ },
783
+ "chat_template": "{%- macro tool_to_json(tool) -%}\n {%- set ns_tool = namespace(first=true) -%}\n {{- '{' -}}\n {%- for k, v in tool.items() -%}\n {%- if k != 'defer_loading' and k != 'strict' -%}\n {%- if not ns_tool.first -%}{{- ', ' -}}{%- endif -%}\n {%- set ns_tool.first = false -%}\n {{- '\"' ~ k ~ '\": ' ~ (v | tojson(ensure_ascii=False)) -}}\n {%- endif -%}\n {%- endfor -%}\n {{- '}' -}}\n{%- endmacro -%}\n{%- set enable_thinking = enable_thinking if enable_thinking is defined else True %}\n{%- set low_effort = low_effort if low_effort is defined else False %}\n{%- if reasoning_effort is defined and reasoning_effort is not none %}\n {%- set low_effort = reasoning_effort == \"low\" %}\n{%- endif %}\n{%- set truncate_history_thinking = truncate_history_thinking if truncate_history_thinking is defined else True %}\n\n{%- set ns = namespace(last_user_idx = -1) %}\n{%- set loop_messages = messages %}\n{%- for m in loop_messages %}\n {%- if m[\"role\"] == \"user\" %}\n {%- set ns.last_user_idx = loop.index0 %}\n {%- endif %}\n{%- endfor %}\n\n{%- if messages[0][\"role\"] == \"system\" %}\n {%- set system_message = messages[0][\"content\"] %}\n {%- set loop_messages = messages[1:] %}\n{%- else %}\n {%- set system_message = \"\" %}\n {%- set loop_messages = messages %}\n{%- endif %}\n{%- if not tools is defined %}\n {%- set tools = [] %}\n{%- endif %}\n{# Recompute last_user_idx relative to loop_messages after handling system #}\n{%- set ns = namespace(last_user_idx = -1) %}\n{%- for m in loop_messages %}\n {%- if m[\"role\"] == \"user\" %}\n {%- set ns.last_user_idx = loop.index0 %}\n {%- endif %}\n{%- endfor %}\n{%- if system_message is defined %}\n {{- \"<|im_start|>system\\n\" + system_message }}\n{%- else %}\n {%- if tools is iterable and tools | length > 0 %}\n {{- \"<|im_start|>system\\n\" }}\n {%- endif %}\n{%- endif %}\n{%- if tools is iterable and tools | length > 0 %}\n {%- if system_message is defined and system_message | length > 0 %}\n {{- \"\\n\\n\" }}\n {%- endif %}\n {{- \"# Tools\\n\\nYou have access to the following functions:\\n\\n\" }}\n {{- \"<tools>\" }}\n {%- for tool in tools %}\n {%- if tool.function is defined %}\n {%- set tool = tool.function %}\n {%- endif %}\n {%- if tool.defer_loading is not defined or not tool.defer_loading %}\n {{- '\\n' ~ tool_to_json(tool) }}\n {%- endif %}\n {%- endfor %}\n {{- \"\\n</tools>\" }}\n\n {{- '\\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>' }}\n{%- endif %}\n\n\n{%- if system_message is defined %}\n {{- '<|im_end|>\\n' }}\n{%- else %}\n {%- if tools is iterable and tools | length > 0 %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n\n{%- for message in loop_messages %}\n {%- if message.role == \"assistant\" %}\n {# Add reasoning content in to content field for unified processing below. #}\n {%- if message.reasoning_content is defined and message.reasoning_content is string and message.reasoning_content | trim | length > 0 %}\n {%- set content = \"<think>\\n\" ~ message.reasoning_content ~ \"\\n</think>\\n\" ~ (message.content | default('', true)) %}\n {%- else %}\n {%- set content = message.content | default('', true) %}\n {%- if content is string -%}\n {# Allow downstream logic to to take care of broken thought, only handle coherent reasoning here. #}\n {%- if '<think>' not in content and '</think>' not in content -%}\n {%- set content = \"<think></think>\" ~ content -%}\n {%- endif -%}\n {%- else -%}\n {%- set content = content -%}\n {%- endif -%}\n {%- endif %}\n {%- if message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}\n {# Assistant message has tool calls. #}\n {{- '<|im_start|>assistant\\n' }}\n {%- set include_content = not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}\n {%- if content is string and content | trim | length > 0 %}\n {%- if include_content %}\n {{- (content | trim) ~ '\\n' -}}\n {%- else %}\n {%- set c = (content | string) %}\n {%- if '</think>' in c %}\n {# Keep only content after the last closing think. Also generation prompt causes this. #}\n {%- set c = c.split('</think>')[-1] %}\n {%- elif '<think>' in c %}\n {# If <think> was opened but never closed, drop the trailing think segment #}\n {%- set c = c.split('<think>')[0] %}\n {%- endif %}\n {%- set c = \"<think></think>\" ~ c | trim %}\n {%- if c | length > 0 %}\n {{- c ~ '\\n' -}}\n {%- endif %}\n {%- endif %}\n {%- else %}\n {{- \"<think></think>\" -}}\n {%- endif %}\n {%- for tool_call in message.tool_calls %}\n {%- if tool_call.function is defined %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '<tool_call>\\n<function=' ~ tool_call.name ~ '>\\n' -}}\n {%- if tool_call.arguments is defined %}\n {%- for args_name, args_value in tool_call.arguments|items %}\n {{- '<parameter=' ~ args_name ~ '>\\n' -}}\n {%- 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 %}\n {{- args_value ~ '\\n</parameter>\\n' -}}\n {%- endfor %}\n {%- endif %}\n {{- '</function>\\n</tool_call>\\n' -}}\n {%- endfor %}\n {{- '<|im_end|>\\n' }}\n {%- else %}\n {# Assistant message doesn't have tool calls. #}\n {%- if not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}\n {{- '<|im_start|>assistant\\n' ~ (content | default('', true) | string | trim) ~ '<|im_end|>\\n' }}\n {%- else %}\n {%- set c = (content | default('', true) | string) %}\n {%- if '<think>' in c and '</think>' in c %}\n {%- set c = \"<think></think>\" ~ c.split('</think>')[-1] %}\n {%- endif %}\n {%- set c = c | trim %}\n {%- if c | length > 0 %}\n {{- '<|im_start|>assistant\\n' ~ c ~ '<|im_end|>\\n' }}\n {%- else %}\n {{- '<|im_start|>assistant\\n<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n {%- endif %}\n {%- elif message.role == \"user\" or message.role == \"system\" %}\n {{- '<|im_start|>' + message.role + '\\n' }}\n {%- set content = message.content | string %}\n {%- if message.role == \"user\" and loop.index0 == ns.last_user_idx and low_effort %}\n {{- content + '\\n\\n{reasoning effort: low}' }}\n {%- else %}\n {{- content }}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.previtem and loop.previtem.role != \"tool\" %}\n {{- '<|im_start|>user\\n' }}\n {%- endif %}\n {{- '<tool_response>\\n' }}\n {{- message.content }}\n {{- '\\n</tool_response>\\n' }}\n {%- if not loop.last and loop.nextitem.role != \"tool\" %}\n {{- '<|im_end|>\\n' }}\n {%- elif loop.last %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- else %}\n {{- '<|im_start|>' + message.role + '\\n' + message.content + '<|im_end|>\\n' }}\n {%- endif %}\n{%- endfor %}\n\n{%- if add_generation_prompt %}\n {%- if enable_thinking %}\n {{- '<|im_start|>assistant\\n<think>\\n' }}\n {%- else %}\n {{- '<|im_start|>assistant\\n<think></think>' }}\n {%- endif %}\n{%- endif %}\n"
784
+ }