monstah0811 commited on
Commit
659438c
·
0 Parent(s):
.gitattributes ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
37
+ figures/audio.png filter=lfs diff=lfs merge=lfs -text
38
+ figures/hero.png filter=lfs diff=lfs merge=lfs -text
39
+ figures/release.png filter=lfs diff=lfs merge=lfs -text
40
+ figures/text.png filter=lfs diff=lfs merge=lfs -text
41
+ figures/vision.png filter=lfs diff=lfs merge=lfs -text
LICENSE 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.
README.md ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: transformers
4
+ base_model: google/gemma-4-E4B-it
5
+ base_model_relation: finetune
6
+ pipeline_tag: any-to-any
7
+ language:
8
+ - en
9
+ tags:
10
+ - decisions
11
+ - typed-decisions
12
+ - audio
13
+ - vision
14
+ - calibration
15
+ - on-device
16
+ - smaug
17
+ - abacusai
18
+ ---
19
+ <div align="center">
20
+ <picture>
21
+ <img src="https://cdn-avatars.huggingface.co/v1/production/uploads/63128dd099791aa61d180c72/dJ6uR23m09M-YEafBpmea.png" width="20%" alt="Smaug-Decisions">
22
+ </picture>
23
+ </div>
24
+ <hr>
25
+ <div align="center" style="line-height:1">
26
+ <a href="https://abacus.ai" target="_blank"><img alt="Homepage" src="https://img.shields.io/badge/Homepage-Abacus.AI-white?color=1783ff&logoColor=white"/></a>
27
+ <a href="https://huggingface.co/abacusai" target="_blank"><img alt="Hugging Face" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Abacus.AI-ffc107?color=ffc107&logoColor=white"/></a>
28
+ </div>
29
+ <div align="center" style="line-height: 1;">
30
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/License-Apache_2.0-f5de53?&color=f5de53"/></a>
31
+ <a href="https://huggingface.co/abacusai/Smaug-Audio-Decisions-0.7B" target="_blank"><img alt="Fast tier" src="https://img.shields.io/badge/Fast_tier-Smaug--Audio--Decisions--0.7B-1783ff?&color=1783ff"/></a>
32
+ <a href="https://huggingface.co/abacusai/Smaug-Decisions-LiteRT" target="_blank"><img alt="On phones" src="https://img.shields.io/badge/On_phones-Smaug--Decisions--LiteRT-1783ff?&color=1783ff"/></a>
33
+ </div>
34
+
35
+ <p align="center"><b>State-of-the-art audio decisions in 4B parameters, and it sees and reads too.</b><br>
36
+ 60.1 Earshot audio skill, ahead of Gemini 4 Argon (59.4) and Gemini 3.8 Flash (50.5), and better calibrated than both.</p>
37
+
38
+ ## 1. Model Introduction
39
+
40
+ Smaug-Decisions is a 4B decision model that hears, sees and reads. A fine-tune of Google's
41
+ [Gemma 4 E4B-it](https://huggingface.co/google/gemma-4-E4B-it) by Abacus.AI, it answers a typed question about **audio, an image or
42
+ text** with a calibrated probability per option, in one forward pass and with no generated text.
43
+
44
+ <p align="center"><img src="figures/demo.svg" width="100%" alt="Four example decisions over audio, an image and text, each answered with a probability per option in one forward pass"></p>
45
+
46
+ <p align="center"><img src="figures/stats.svg" width="100%" alt="60.1 Earshot audio skill, three input types, one forward pass per decision, 0.069 calibration error"></p>
47
+
48
+ It is the only 4B decision model with results on all three input types. On audio it is ahead of the frontier APIs: **60.1** skill on
49
+ **Earshot**, our 6,671-item audio decision benchmark, against 59.4 for Gemini 4 Argon and 50.5 for Gemini 3.8 Flash, and better
50
+ calibrated than both (ECE 0.069 vs 0.123 and 0.204). On the public Jev Decision Index it scores **57.9** on images and **56.6** on text,
51
+ the best Gemma 4 E4B on both.
52
+
53
+ ```python
54
+ import sys
55
+ from huggingface_hub import snapshot_download
56
+ sys.path.insert(0, snapshot_download("abacusai/Smaug-Decisions", allow_patterns=["smaug_decide.py"]))
57
+ from smaug_decide import SmaugDecide # ships with this repo
58
+
59
+ model = SmaugDecide.from_pretrained("abacusai/Smaug-Decisions")
60
+ model("call.wav", "Has the speaker finished their turn?") # -> {'Yes': 0.93, 'No': 0.07}
61
+ ```
62
+
63
+ <p align="center"><img src="figures/matrix.svg" width="100%" alt="Every 4B decision model by input type: Smaug-Decisions is the only one with audio, image and text results"></p>
64
+
65
+ ## 2. Highlights
66
+
67
+ - **Ahead of the frontier APIs on audio,** and better calibrated, so the probabilities work as thresholds.
68
+ - **Hears, sees and reads:** audio up to 30 s, images and text through one prompt and one readout.
69
+ - **One pass, no decoding:** about 200 ms per audio decision on an H100.
70
+ - **Runs on phones:** [Smaug-Decisions-LiteRT](https://huggingface.co/abacusai/Smaug-Decisions-LiteRT) is 3.45 GB, keeps 59.4 audio skill and answers
71
+ a text question in about 0.6 s on an iPhone 14 Pro Max, fully offline.
72
+
73
+ ## 3. Model Summary
74
+
75
+ <div align="center">
76
+ <table>
77
+ <tbody>
78
+ <tr><td align="center"><strong>Architecture</strong></td><td align="center">Gemma 4 E4B-it (language model + audio and vision encoders); letter-logit readout</td></tr>
79
+ <tr><td align="center"><strong>Parameters</strong></td><td align="center">4B effective, 8.6B stored (3.5B of the stored weights are embedding tables that are looked up, not computed; the Hugging Face counter shows the stored total)</td></tr>
80
+ <tr><td align="center"><strong>Input</strong></td><td align="center">Audio up to 30 s (16 kHz mono), an image (560 image tokens), or text, plus a question with 2 to 20 options</td></tr>
81
+ <tr><td align="center"><strong>Output</strong></td><td align="center">A calibrated probability per option (softmax for one answer, sigmoid for select-all)</td></tr>
82
+ <tr><td align="center"><strong>Hardware</strong></td><td align="center">NVIDIA GPU (bfloat16), Apple Silicon (MPS) and CPU through Transformers; phones through <a href="https://huggingface.co/abacusai/Smaug-Decisions-LiteRT">Smaug-Decisions-LiteRT</a></td></tr>
83
+ <tr><td align="center"><strong>Precision</strong></td><td align="center">bfloat16</td></tr>
84
+ <tr><td align="center"><strong>Formats</strong></td><td align="center">Transformers (repo root); LiteRT-LM for phones (<a href="https://huggingface.co/abacusai/Smaug-Decisions-LiteRT">Smaug-Decisions-LiteRT</a>)</td></tr>
85
+ <tr><td align="center"><strong>Base Model</strong></td><td align="center"><code>google/gemma-4-E4B-it</code></td></tr>
86
+ <tr><td align="center"><strong>Adaptation</strong></td><td align="center">Full fine-tune</td></tr>
87
+ </tbody>
88
+ </table>
89
+ </div>
90
+
91
+ ## 4. Evaluation
92
+
93
+ ### Audio: Earshot
94
+
95
+ **Earshot** is our audio decision benchmark: 6,671 items and 17.2 hours of audio in four tracks: **conversation dynamics** (turn
96
+ completion, next speaker, speaker count, speech activity; from VoxConverse, AMI and Smart Turn), **external turn completion** (Smart
97
+ Turn v3.2 test), **sound and music** (genre, instrument, tempo, scene, sound events) and a small **pilot** track. **Audio skill** is
98
+ the mean task skill per track, averaged over the tracks: 0 is guessing, 100 is perfect. No benchmark recording or item is in the
99
+ training data.
100
+
101
+ <p align="center"><img src="figures/earshot.svg" width="100%" alt="Earshot audio skill per track, and calibration error"></p>
102
+
103
+ <details>
104
+ <summary><b>Earshot table</b></summary>
105
+
106
+ <div style="max-width:1100px;margin:0 auto">
107
+ <table style="width:100%;table-layout:fixed;border-collapse:collapse;font-size:13px">
108
+ <thead><tr><th style="padding:10px 6px;text-align:left;border-bottom:2px solid #2a78d6;width:26%"></th>
109
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;font-weight:600;background:rgba(42,120,214,0.10);">Smaug-Decisions</th>
110
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">Gemini 4 Argon<div style="font-size:10px;font-weight:400;color:#6B6B6B">(API)</div></th>
111
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">Gemini 3.8 Flash<div style="font-size:10px;font-weight:400;color:#6B6B6B">(API)</div></th>
112
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">AudioJev<div style="font-size:10px;font-weight:400;color:#6B6B6B">(Qwen2.5-Omni-3B)</div></th>
113
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">Gemma 4 E4B-it<div style="font-size:10px;font-weight:400;color:#6B6B6B">(zero-shot)</div></th>
114
+ </tr></thead>
115
+ <tbody>
116
+ <tr><td colspan="6" style="padding:7px 10px;font-weight:600;color:#1a5fb4;background:#e8f0fc;border-bottom:1px solid rgba(42,120,214,0.2)">Earshot (audio decisions)</td></tr>
117
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Audio skill (headline) &uarr;</td>
118
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.47)"><strong>60.1</strong></td>
119
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.46)">59.4</td>
120
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.40)">50.5</td>
121
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.34)">43.6</td>
122
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">5.0</td>
123
+ </tr>
124
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">ECE &darr;</td>
125
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.47)"><strong>0.069</strong></td>
126
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.41)">0.123</td>
127
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.33)">0.204</td>
128
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.34)">0.191</td>
129
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">0.464</td>
130
+ </tr>
131
+ <tr><td colspan="6" style="padding:7px 10px;font-weight:600;color:#1a5fb4;background:#e8f0fc;border-bottom:1px solid rgba(42,120,214,0.2)">Per track (skill) &uarr;</td></tr>
132
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Conversation dynamics (3,000)</td>
133
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.46)">48.2</td>
134
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>49.6</strong></td>
135
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.46)">48.5</td>
136
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.26)">26.7</td>
137
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">3.6</td>
138
+ </tr>
139
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">External turn completion (1,000)</td>
140
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.46)">80.8</td>
141
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.44)">76.5</td>
142
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>81.8</strong></td>
143
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.35)">62.0</td>
144
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">11.2</td>
145
+ </tr>
146
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Sound &amp; music (1,115)</td>
147
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.47)"><strong>66.1</strong></td>
148
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.46)">64.7</td>
149
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.31)">42.4</td>
150
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.41)">57.6</td>
151
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">5.2</td>
152
+ </tr>
153
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Pilot (80)</td>
154
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.45)">45.2</td>
155
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>47.0</strong></td>
156
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.31)">29.1</td>
157
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.30)">28.2</td>
158
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">0.1</td>
159
+ </tr>
160
+ </tbody></table>
161
+ <div style="font-size:11.5px;color:#6B6B6B;margin-top:6px">Bold = best in the row. Shading is relative within each row (darker = better). Every model scored on the same 6,671 items with the same harness; the APIs received the audio and returned JSON probabilities. Skill = (accuracy &minus; chance) / (1 &minus; chance), times 100.</div>
162
+ </div>
163
+
164
+ </details>
165
+
166
+ Need it faster? [Smaug-Audio-Decisions-0.7B](https://huggingface.co/abacusai/Smaug-Audio-Decisions-0.7B) scores 53.0 on Earshot at 9.7 ms; in front of this
167
+ model as a [cascade](https://huggingface.co/abacusai/Smaug-Audio-Decisions-0.7B#the-cascade) it matches this model's accuracy (60.1) at 130 ms
168
+ instead of 210 ms.
169
+
170
+ ### Images and text: the public Jev Decision Index
171
+
172
+ The matrix at the top has the headline numbers: 57.9 on images and 56.6 on text, the best Gemma 4 E4B on both (Winnow-E4B, the
173
+ other Gemma 4 E4B fine-tune on the boards: 48.1 and 41.7). Images: our run of the official vision kit (0.4, public sets) at 560 image
174
+ tokens.
175
+
176
+ <details>
177
+ <summary><b>Full Decision Index breakdown</b></summary>
178
+
179
+ <p align="center"><img src="figures/text.svg" width="100%" alt="Text decision skill per area"></p>
180
+
181
+ <div style="max-width:1100px;margin:0 auto">
182
+ <table style="width:100%;table-layout:fixed;border-collapse:collapse;font-size:13px">
183
+ <thead><tr><th style="padding:10px 6px;text-align:left;border-bottom:2px solid #2a78d6;width:26%"></th>
184
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;font-weight:600;background:rgba(42,120,214,0.10);">Smaug-Decisions<div style="font-size:10px;font-weight:400;color:#6B6B6B">(audio + image + text)</div></th>
185
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">Perplexity Decider Flash<div style="font-size:10px;font-weight:400;color:#6B6B6B">(4B)</div></th>
186
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">vLLM-SR d3-mini<div style="font-size:10px;font-weight:400;color:#6B6B6B">(4B)</div></th>
187
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">RSI-Jev v6.1 VL<div style="font-size:10px;font-weight:400;color:#6B6B6B">(4B)</div></th>
188
+ <th style="padding:10px 4px;text-align:center;font-weight:500;border-bottom:2px solid #2a78d6;color:#2a78d6;font-size:13px;">Winnow<div style="font-size:10px;font-weight:400;color:#6B6B6B">(Gemma 4 E4B)</div></th>
189
+ </tr></thead>
190
+ <tbody>
191
+ <tr><td colspan="6" style="padding:7px 10px;font-weight:600;color:#1a5fb4;background:#e8f0fc;border-bottom:1px solid rgba(42,120,214,0.2)">Jev Decision Index 0.4.1, text (same 35 public benchmarks)</td></tr>
192
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Public skill &uarr;</td>
193
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.36)">56.6</td>
194
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>61.8</strong></td>
195
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.36)">56.7</td>
196
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.28)">52.9</td>
197
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">41.7</td>
198
+ </tr>
199
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Knowledge &amp; reasoning</td>
200
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.25)">35.1</td>
201
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>46.0</strong></td>
202
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.44)">44.3</td>
203
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.25)">35.2</td>
204
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">25.3</td>
205
+ </tr>
206
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Language</td>
207
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.45)">66.4</td>
208
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>67.2</strong></td>
209
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.33)">60.4</td>
210
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.30)">59.2</td>
211
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">47.5</td>
212
+ </tr>
213
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Retrieval</td>
214
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.46)">64.7</td>
215
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>65.2</strong></td>
216
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.44)">63.6</td>
217
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.31)">57.1</td>
218
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">43.8</td>
219
+ </tr>
220
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Tools</td>
221
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.29)">72.9</td>
222
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>81.0</strong></td>
223
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.27)">72.0</td>
224
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.18)">68.4</td>
225
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">62.5</td>
226
+ </tr>
227
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Arts</td>
228
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.36)">41.6</td>
229
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.47)"><strong>46.6</strong></td>
230
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.28)">37.7</td>
231
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.45)">45.7</td>
232
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;background:rgba(42,120,214,0.05)">26.9</td>
233
+ </tr>
234
+ <tr><td colspan="6" style="padding:7px 10px;font-weight:600;color:#1a5fb4;background:#e8f0fc;border-bottom:1px solid rgba(42,120,214,0.2)">Earshot (audio decisions)</td></tr>
235
+ <tr><td style="padding:8px 6px;padding-left:16px;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600">Audio skill &uarr;</td>
236
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;font-weight:600;background:rgba(42,120,214,0.47)"><strong>60.1</strong></td>
237
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;color:#9aa0a6">&mdash;</td>
238
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;color:#9aa0a6">&mdash;</td>
239
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;color:#9aa0a6">&mdash;</td>
240
+ <td style="padding:8px 6px;text-align:center;border-bottom:1px solid rgba(128,128,128,0.15);font-size:14px;color:#9aa0a6">&mdash;</td>
241
+ </tr>
242
+ </tbody></table>
243
+ <div style="font-size:11.5px;color:#6B6B6B;margin-top:6px">Bold = best in the row. Other models: the public Decision Index board as of 2026-10-28 (text 0.4.1). Smaug-Decisions: our runs of the official Decision Index kit (text on a 3,000-row sample of the public suite, compared on the same 35 benchmarks); self-reported, not board submissions. &mdash; = no published result.</div>
244
+ </div>
245
+
246
+ </details>
247
+
248
+ ## 5. Training Approach
249
+
250
+ - **Readout, not generation.** The answer is read from the LM-head logits of the option letters at the answer position (tanh
251
+ softcap 30, then softmax; select-all uses a sigmoid with one learned threshold). A decision costs one prefill.
252
+ - **Decision-tuned and calibrated.** Full fine-tune of Gemma 4 E4B-it on a broad mix of typed decision tasks over audio, images and
253
+ text, with calibration as an explicit objective and options shuffled so the model learns the options, not their positions.
254
+
255
+ ## 6. Limitations
256
+
257
+ - **Decisions, not text:** each call answers one typed question with a probability per option; the model does not write text.
258
+ - **Per request:** one audio clip of up to 30 s (longer audio keeps its last 30 s), one image at 560 image tokens, up to 20 options.
259
+ - **Thresholds:** set decision thresholds on your own data for high-stakes uses.
260
+
261
+ ## 7. Usage
262
+
263
+ ```bash
264
+ pip install "transformers>=5.20" torch soundfile pillow huggingface_hub
265
+ ```
266
+
267
+ ```python
268
+ import sys
269
+ from huggingface_hub import snapshot_download
270
+ sys.path.insert(0, snapshot_download("abacusai/Smaug-Decisions", allow_patterns=["smaug_decide.py"]))
271
+ from smaug_decide import SmaugDecide
272
+
273
+ model = SmaugDecide.from_pretrained("abacusai/Smaug-Decisions") # CUDA, Apple Silicon (MPS) or CPU, picked automatically
274
+ model("call.wav", "Has the speaker finished their turn?") # predicate -> {'Yes': p, 'No': 1-p}
275
+ model("song.wav", "Which genre is playing?", ["rock", "jazz", "classical"]) # choice -> probabilities sum to 1
276
+ model("room.wav", "Which sounds are present?", ["speech", "music", "alarm"], multi=True) # select-all -> one probability each
277
+ model("receipt.jpg", "Does the total exceed $50?") # images
278
+ model("The order never arrived.", "How upset is the customer?", ["calm", "annoyed", "angry"],
279
+ descriptions=["neutral tone", "complains", "threatens to leave"], rules="Judge the tone, not the facts.")
280
+ ```
281
+
282
+ `from_pretrained` downloads the checkpoint (about 16 GB). Any runtime can reproduce the readout: run the prompt in
283
+ `smaug_decide.render`, take the LM-head logits of the tokens `A`..`T` at the last position, apply the softcap from `readout.json`,
284
+ then softmax (one answer) or `sigmoid(z - b)` with `b` from `readout.json` (select-all). With plain Transformers,
285
+ `AutoModelForMultimodalLM.from_pretrained("abacusai/Smaug-Decisions", dtype="bfloat16")` loads the weights.
286
+
287
+ ### On phones
288
+
289
+ [Smaug-Decisions-LiteRT](https://huggingface.co/abacusai/Smaug-Decisions-LiteRT) is this model in one **3.45 GB** file for Google's on-device
290
+ runtime LiteRT-LM, running on the phone GPU. At about a fifth of the size it keeps almost all of this model's quality. It runs in
291
+ the Cascade app on iPhone and Android next to [Smaug-Audio-Decisions-0.7B](https://huggingface.co/abacusai/Smaug-Audio-Decisions-0.7B), which answers the easy
292
+ audio questions first. App source: [github.com/abacusai/Smaug-Decisions-Mobile](https://github.com/abacusai/Smaug-Decisions-Mobile).
293
+
294
+ | | Smaug-Decisions (16 GB) | Smaug-Decisions-LiteRT (3.45 GB) | change |
295
+ |---|---|---|---|
296
+ | Earshot audio skill | 60.1 | **59.4** | &minus;0.7 |
297
+ | Earshot calibration error (ECE, lower is better) | 0.069 | **0.074** | +0.005 |
298
+ | Decision Index text | 56.6 | **53.9** | &minus;2.7 |
299
+ | Decision Index images, 560 image tokens<sup>*</sup> | 57.2 | **55.1** | &minus;2.1 |
300
+ | Decision Index images, 280 image tokens<sup>*</sup> | 54.8 | **51.8** | &minus;3.0 |
301
+
302
+ Same items, same harness; the phone-build scores come from a PyTorch replica of the file's quantized weights. <sup>*</sup>10 of the 11 public
303
+ vision sets (Winoground left out; this model's 11-set index is 57.9).
304
+
305
+ | iPhone 14 Pro Max (6 GB RAM, phone GPU) | measured |
306
+ |---|---|
307
+ | first load (one time) / later loads | 13-21 s / 0.48 s |
308
+ | text decision | ~0.6 s |
309
+ | audio decision | ~1.6 s |
310
+ | image decision (280 image tokens) | ~7.4 s |
311
+ | peak app memory, with Smaug-Audio-Decisions-0.7B loaded | 1.35 GB |
312
+ | storage | the 3.45 GB file + a ~2.4 GB cache written on first load |
313
+
314
+ ## 8. License
315
+
316
+ Apache 2.0, the same license as the base model, Gemma 4 E4B-it.
317
+
318
+ ## 9. Citation
319
+
320
+ ```bibtex
321
+ @misc{abacusai2026smaugdecisions,
322
+ title = {Smaug-Decisions: calibrated typed decisions over audio, images and text},
323
+ author = {Abacus.AI},
324
+ year = {2026},
325
+ url = {https://huggingface.co/abacusai/Smaug-Decisions}
326
+ }
327
+ ```
328
+
329
+ ## 10. Contact Us
330
+
331
+ If you have any questions, please reach out at [Abacus.AI](https://abacus.ai).
chat_template.jinja ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#
2
+ Template: Google Gemma 4 Canonical Chat Template
3
+ Author: Google Gemma Engineering Team
4
+ Published: 2026-07-09
5
+ Context: Fixed tool-calling loops, turn closures, and thinking content-ordering.
6
+ #}
7
+ {%- macro format_parameters(properties, required, filter_keys=false) -%}
8
+ {%- set standard_keys = ['description', 'type', 'properties', 'required', 'nullable'] -%}
9
+ {%- set ns = namespace(found_first=false) -%}
10
+ {%- for key, value in properties | dictsort -%}
11
+ {%- set add_comma = false -%}
12
+ {%- if not filter_keys or key not in standard_keys -%}
13
+ {%- if ns.found_first %},{% endif -%}
14
+ {%- set ns.found_first = true -%}
15
+ {{ key }}:{
16
+ {%- if value['description'] -%}
17
+ description:<|"|>{{ value['description'] }}<|"|>
18
+ {%- set add_comma = true -%}
19
+ {%- endif -%}
20
+ {%- if value['type'] | upper == 'STRING' -%}
21
+ {%- if value['enum'] -%}
22
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
23
+ enum:{{ format_argument(value['enum']) }}
24
+ {%- endif -%}
25
+ {%- elif value['type'] | upper == 'ARRAY' -%}
26
+ {%- if value['items'] is mapping and value['items'] -%}
27
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
28
+ items:{
29
+ {%- set ns_items = namespace(found_first=false) -%}
30
+ {%- for item_key, item_value in value['items'] | dictsort -%}
31
+ {%- if item_value is not none -%}
32
+ {%- if ns_items.found_first %},{% endif -%}
33
+ {%- set ns_items.found_first = true -%}
34
+ {%- if item_key == 'properties' -%}
35
+ properties:{
36
+ {%- if item_value is mapping -%}
37
+ {{- format_parameters(item_value, value['items']['required'] | default([])) -}}
38
+ {%- endif -%}
39
+ }
40
+ {%- elif item_key == 'required' -%}
41
+ required:[
42
+ {%- for req_item in item_value -%}
43
+ <|"|>{{- req_item -}}<|"|>
44
+ {%- if not loop.last %},{% endif -%}
45
+ {%- endfor -%}
46
+ ]
47
+ {%- elif item_key == 'type' -%}
48
+ {%- if item_value is string -%}
49
+ type:{{ format_argument(item_value | upper) }}
50
+ {%- else -%}
51
+ type:{{ format_argument(item_value | map('upper') | list) }}
52
+ {%- endif -%}
53
+ {%- else -%}
54
+ {{ item_key }}:{{ format_argument(item_value) }}
55
+ {%- endif -%}
56
+ {%- endif -%}
57
+ {%- endfor -%}
58
+ }
59
+ {%- endif -%}
60
+ {%- endif -%}
61
+ {%- if value['nullable'] %}
62
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
63
+ nullable:true
64
+ {%- endif -%}
65
+ {%- if value['type'] | upper == 'OBJECT' -%}
66
+ {%- if value['properties'] is defined and value['properties'] is mapping -%}
67
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
68
+ properties:{
69
+ {{- format_parameters(value['properties'], value['required'] | default([])) -}}
70
+ }
71
+ {%- elif value is mapping -%}
72
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
73
+ properties:{
74
+ {{- format_parameters(value, value['required'] | default([]), filter_keys=true) -}}
75
+ }
76
+ {%- endif -%}
77
+ {%- if value['required'] -%}
78
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
79
+ required:[
80
+ {%- for item in value['required'] | default([]) -%}
81
+ <|"|>{{- item -}}<|"|>
82
+ {%- if not loop.last %},{% endif -%}
83
+ {%- endfor -%}
84
+ ]
85
+ {%- endif -%}
86
+ {%- endif -%}
87
+ {%- if add_comma %},{%- else -%} {%- set add_comma = true -%} {% endif -%}
88
+ type:<|"|>{{ value['type'] | upper }}<|"|>}
89
+ {%- endif -%}
90
+ {%- endfor -%}
91
+ {%- endmacro -%}
92
+ {%- macro format_function_declaration(tool_data) -%}
93
+ declaration:{{- tool_data['function']['name'] -}}{description:<|"|>{{- tool_data['function']['description'] -}}<|"|>
94
+ {%- set params = tool_data['function']['parameters'] -%}
95
+ {%- if params -%}
96
+ ,parameters:{
97
+ {%- if params['properties'] -%}
98
+ properties:{ {{- format_parameters(params['properties'], params['required']) -}} },
99
+ {%- endif -%}
100
+ {%- if params['required'] -%}
101
+ required:[
102
+ {%- for item in params['required'] -%}
103
+ <|"|>{{- item -}}<|"|>
104
+ {{- ',' if not loop.last -}}
105
+ {%- endfor -%}
106
+ ],
107
+ {%- endif -%}
108
+ {%- if params['type'] -%}
109
+ type:<|"|>{{- params['type'] | upper -}}<|"|>}
110
+ {%- endif -%}
111
+ {%- endif -%}
112
+ {%- if 'response' in tool_data['function'] -%}
113
+ {%- set response_declaration = tool_data['function']['response'] -%}
114
+ ,response:{
115
+ {%- if response_declaration['description'] -%}
116
+ description:<|"|>{{- response_declaration['description'] -}}<|"|>,
117
+ {%- endif -%}
118
+ {%- if response_declaration['type'] | upper == 'OBJECT' -%}
119
+ type:<|"|>{{- response_declaration['type'] | upper -}}<|"|>}
120
+ {%- endif -%}
121
+ {%- endif -%}
122
+ }
123
+ {%- endmacro -%}
124
+ {%- macro format_argument(argument, escape_keys=True) -%}
125
+ {%- if argument is none -%}
126
+ {{- 'null' -}}
127
+ {%- elif argument is string -%}
128
+ {{- '<|"|>' + argument + '<|"|>' -}}
129
+ {%- elif argument is boolean -%}
130
+ {{- 'true' if argument else 'false' -}}
131
+ {%- elif argument is mapping -%}
132
+ {{- '{' -}}
133
+ {%- set ns = namespace(found_first=false) -%}
134
+ {%- for key, value in argument | dictsort -%}
135
+ {%- if ns.found_first %},{% endif -%}
136
+ {%- set ns.found_first = true -%}
137
+ {%- if escape_keys -%}
138
+ {{- '<|"|>' + key + '<|"|>' -}}
139
+ {%- else -%}
140
+ {{- key -}}
141
+ {%- endif -%}
142
+ :{{- format_argument(value, escape_keys=escape_keys) -}}
143
+ {%- endfor -%}
144
+ {{- '}' -}}
145
+ {%- elif argument is sequence -%}
146
+ {{- '[' -}}
147
+ {%- for item in argument -%}
148
+ {{- format_argument(item, escape_keys=escape_keys) -}}
149
+ {%- if not loop.last %},{% endif -%}
150
+ {%- endfor -%}
151
+ {{- ']' -}}
152
+ {%- else -%}
153
+ {{- argument -}}
154
+ {%- endif -%}
155
+ {%- endmacro -%}
156
+ {%- macro strip_thinking(text) -%}
157
+ {%- set ns = namespace(result='') -%}
158
+ {%- for part in text.split('<channel|>') -%}
159
+ {%- if '<|channel>' in part -%}
160
+ {%- set ns.result = ns.result + part.split('<|channel>')[0] -%}
161
+ {%- else -%}
162
+ {%- set ns.result = ns.result + part -%}
163
+ {%- endif -%}
164
+ {%- endfor -%}
165
+ {{- ns.result | trim -}}
166
+ {%- endmacro -%}
167
+
168
+ {%- macro format_tool_response_block(tool_name, response) -%}
169
+ {{- '<|tool_response>' -}}
170
+ {%- if response is mapping -%}
171
+ {{- 'response:' + tool_name + '{' -}}
172
+ {%- for key, value in response | dictsort -%}
173
+ {{- key -}}:{{- format_argument(value, escape_keys=False) -}}
174
+ {%- if not loop.last %},{% endif -%}
175
+ {%- endfor -%}
176
+ {{- '}' -}}
177
+ {%- else -%}
178
+ {{- 'response:' + tool_name + '{value:' + format_argument(response, escape_keys=False) + '}' -}}
179
+ {%- endif -%}
180
+ {{- '<tool_response|>' -}}
181
+ {%- endmacro -%}
182
+
183
+ {#- ===== SETUP ===== -#}
184
+ {%- set ns = namespace(prev_message_type=None, prev_non_tool_role=None) -%}
185
+ {%- set loop_messages = messages -%}
186
+ {%- set enable_thinking = enable_thinking | default(false) -%}
187
+ {%- set preserve_thinking = preserve_thinking | default(false) -%}
188
+ {{- bos_token -}}
189
+ {#- Handle System/Tool Definitions Block -#}
190
+ {%- if enable_thinking or tools or (messages and messages[0]['role'] in ['system', 'developer']) -%}
191
+ {{- '<|turn>system\n' -}}
192
+ {#- Inject Thinking token at the very top of the FIRST system turn -#}
193
+ {%- if enable_thinking -%}
194
+ {{- '<|think|>\n' -}}
195
+ {%- set ns.prev_message_type = 'think' -%}
196
+ {%- endif -%}
197
+ {%- if messages and messages[0]['role'] in ['system', 'developer'] -%}
198
+ {%- if messages[0]['content'] is string -%}
199
+ {{- messages[0]['content'] | trim -}}
200
+ {%- elif messages[0]['content'] is sequence -%}
201
+ {%- for item in messages[0]['content'] -%}
202
+ {{- item['text'] | trim + ' '-}}
203
+ {%- endfor -%}
204
+ {%- endif -%}
205
+ {%- set loop_messages = messages[1:] -%}
206
+ {%- endif -%}
207
+ {%- if tools -%}
208
+ {%- for tool in tools %}
209
+ {{- '<|tool>' -}}
210
+ {{- format_function_declaration(tool) | trim -}}
211
+ {{- '<tool|>' -}}
212
+ {%- endfor %}
213
+ {%- set ns.prev_message_type = 'tool' -%}
214
+ {%- endif -%}
215
+ {{- '<turn|>\n' -}}
216
+ {%- endif %}
217
+
218
+ {#- Pre-scan: find last user message index for reasoning guard -#}
219
+ {%- set ns_turn = namespace(last_user_idx=-1) -%}
220
+ {%- for i in range(loop_messages | length) -%}
221
+ {%- if loop_messages[i]['role'] == 'user' -%}
222
+ {%- set ns_turn.last_user_idx = i -%}
223
+ {%- endif -%}
224
+ {%- endfor -%}
225
+
226
+ {#- Loop through messages -#}
227
+ {%- for message in loop_messages -%}
228
+ {%- if message['role'] != 'tool' -%}
229
+ {%- set ns.prev_message_type = None -%}
230
+ {%- set role = 'model' if message['role'] == 'assistant' else message['role'] -%}
231
+ {#- Detect continuation using tracked state — O(1) instead of O(n) backward scan -#}
232
+ {%- set continue_same_model_turn = (role == 'model' and ns.prev_non_tool_role == 'assistant') -%}
233
+ {%- if not continue_same_model_turn -%}
234
+ {{- '<|turn>' + role + '\n' }}
235
+ {%- endif -%}
236
+
237
+ {#- Render reasoning/reasoning_content as thinking channel -#}
238
+ {%- set thinking_text = message.get('reasoning') or message.get('reasoning_content') -%}
239
+ {%- set thinking_gate = (loop.index0 > ns_turn.last_user_idx) or (preserve_thinking and message.get('tool_calls')) -%}
240
+ {%- if thinking_text and thinking_gate -%}
241
+ {{- '<|channel>thought\n' + thinking_text + '\n<channel|>' -}}
242
+ {%- endif -%}
243
+
244
+ {%- if message.get('tool_calls') -%}
245
+ {%- for tool_call in message.get('tool_calls') -%}
246
+ {%- set function = tool_call['function'] -%}
247
+ {{- '<|tool_call>call:' + function['name'] + '{' -}}
248
+ {%- if function['arguments'] is mapping -%}
249
+ {%- set ns_args = namespace(found_first=false) -%}
250
+ {%- for key, value in function['arguments'] | dictsort -%}
251
+ {%- if ns_args.found_first %},{% endif -%}
252
+ {%- set ns_args.found_first = true -%}
253
+ {{- key -}}:{{- format_argument(value, escape_keys=False) -}}
254
+ {%- endfor -%}
255
+ {%- elif function['arguments'] is none -%}
256
+ {%- else -%}
257
+ {{- raise_exception(
258
+ "chat_template: tool_calls[].function.arguments must be a "
259
+ "JSON object (mapping), not a string. Deserialize arguments "
260
+ "before passing to the template."
261
+ ) -}}
262
+ {%- endif -%}
263
+ {{- '}<tool_call|>' -}}
264
+ {%- endfor -%}
265
+ {%- set ns.prev_message_type = 'tool_call' -%}
266
+ {%- endif -%}
267
+
268
+ {%- set ns_tr_out = namespace(flag=false) -%}
269
+ {%- if message.get('tool_responses') -%}
270
+ {#- Legacy: tool_responses embedded on the assistant message (Google/Gemma native) -#}
271
+ {%- for tool_response in message.get('tool_responses') -%}
272
+ {{- format_tool_response_block(tool_response['name'] | default('unknown', true), tool_response['response']) -}}
273
+ {%- set ns_tr_out.flag = true -%}
274
+ {%- set ns.prev_message_type = 'tool_response' -%}
275
+ {%- endfor -%}
276
+ {%- elif message.get('tool_calls') -%}
277
+ {#- OpenAI Chat Completions: forward-scan consecutive role:tool messages -#}
278
+ {%- set ns_tool_scan = namespace(stopped=false) -%}
279
+ {%- for k in range(loop.index0 + 1, loop_messages | length) -%}
280
+ {%- if ns_tool_scan.stopped -%}
281
+ {%- elif loop_messages[k]['role'] != 'tool' -%}
282
+ {%- set ns_tool_scan.stopped = true -%}
283
+ {%- else -%}
284
+ {%- set follow = loop_messages[k] -%}
285
+ {#- Resolve tool_call_id to function name -#}
286
+ {%- set ns_tname = namespace(name=follow.get('name') or 'unknown') -%}
287
+ {%- for tc in message.get('tool_calls') -%}
288
+ {%- if tc.get('id') == follow.get('tool_call_id') -%}
289
+ {%- set ns_tname.name = tc['function']['name'] -%}
290
+ {%- endif -%}
291
+ {%- endfor -%}
292
+ {#- Handle content as string or content-parts array -#}
293
+ {%- set tool_body = follow.get('content') -%}
294
+ {%- if tool_body is string -%}
295
+ {{- format_tool_response_block(ns_tname.name, tool_body) -}}
296
+ {%- elif tool_body is sequence and tool_body is not string -%}
297
+ {%- set ns_txt = namespace(s='') -%}
298
+ {%- for part in tool_body -%}
299
+ {%- if part.get('type') == 'text' -%}
300
+ {%- set ns_txt.s = ns_txt.s + (part.get('text') | default('')) -%}
301
+ {%- endif -%}
302
+ {%- endfor -%}
303
+ {{- format_tool_response_block(ns_tname.name, ns_txt.s) -}}
304
+ {%- for part in tool_body -%}
305
+ {%- if part.get('type') in ['image', 'image_url'] -%}
306
+ {{- '<|image|>' -}}
307
+ {%- elif part.get('type') in ['audio', 'input_audio'] -%}
308
+ {{- '<|audio|>' -}}
309
+ {%- elif part.get('type') == 'video' -%}
310
+ {{- '<|video|>' -}}
311
+ {%- endif -%}
312
+ {%- endfor -%}
313
+ {%- else -%}
314
+ {{- format_tool_response_block(ns_tname.name, tool_body) -}}
315
+ {%- endif -%}
316
+ {%- set ns_tr_out.flag = true -%}
317
+ {%- set ns.prev_message_type = 'tool_response' -%}
318
+ {%- endif -%}
319
+ {%- endfor -%}
320
+ {%- endif -%}
321
+
322
+ {%- set captured_content -%}
323
+ {%- if message.get('content') is string -%}
324
+ {%- if role == 'model' -%}
325
+ {{- strip_thinking(message['content']) -}}
326
+ {%- else -%}
327
+ {{- message['content'] | trim -}}
328
+ {%- endif -%}
329
+ {%- elif message.get('content') is sequence -%}
330
+ {%- for item in message['content'] -%}
331
+ {%- if item.get('type') == 'text' -%}
332
+ {%- if role == 'model' -%}
333
+ {{- strip_thinking(item['text']) -}}
334
+ {%- else -%}
335
+ {{- item['text'] | trim -}}
336
+ {%- endif -%}
337
+ {%- elif item.get('type') in ['image', 'image_url'] -%}
338
+ {{- '<|image|>' -}}
339
+ {%- elif item.get('type') in ['audio', 'input_audio'] -%}
340
+ {{- '<|audio|>' -}}
341
+ {%- elif item.get('type') == 'video' -%}
342
+ {{- '<|video|>' -}}
343
+ {%- endif -%}
344
+ {%- endfor -%}
345
+ {%- endif -%}
346
+ {%- endset -%}
347
+
348
+ {{- captured_content -}}
349
+ {%- set has_content = captured_content | trim | length > 0 -%}
350
+
351
+ {#- Forward-scan: find next non-tool message role for continuation detection -#}
352
+ {%- set next_nt = namespace(role=None, found=false) -%}
353
+ {%- for j in range(loop.index0 + 1, loop_messages | length) -%}
354
+ {%- if not next_nt.found -%}
355
+ {%- if loop_messages[j]['role'] != 'tool' -%}
356
+ {%- set next_nt.role = loop_messages[j]['role'] -%}
357
+ {%- set next_nt.found = true -%}
358
+ {%- endif -%}
359
+ {%- endif -%}
360
+ {%- endfor -%}
361
+
362
+ {%- set continues_into_next = (
363
+ role == 'model'
364
+ and next_nt.role == 'assistant'
365
+ and (not message.get('tool_calls') or ns_tr_out.flag)
366
+ ) -%}
367
+
368
+ {%- if ns.prev_message_type == 'tool_call' and not ns_tr_out.flag -%}
369
+ {{- '<|tool_response>' -}}
370
+ {%- elif continues_into_next -%}
371
+ {%- elif not (ns_tr_out.flag and not has_content and not next_nt.found) -%}
372
+ {{- '<turn|>\n' -}}
373
+ {%- endif -%}
374
+
375
+ {#- Track previous non-tool role for next iteration (avoids O(n) backward scan) -#}
376
+ {%- set ns.prev_non_tool_role = message['role'] -%}
377
+ {%- endif -%}
378
+ {%- endfor -%}
379
+
380
+ {%- if add_generation_prompt -%}
381
+ {%- if ns.prev_message_type != 'tool_response' and ns.prev_message_type != 'tool_call' -%}
382
+ {{- '<|turn>model\n' -}}
383
+ {%- elif ns.prev_message_type == 'tool_response' and enable_thinking -%}
384
+ {{- '<|channel>thought\n' -}}
385
+ {%- endif -%}
386
+ {%- endif -%}
config.json ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Gemma4ForConditionalGeneration"
4
+ ],
5
+ "audio_config": {
6
+ "attention_chunk_size": 12,
7
+ "attention_context_left": 13,
8
+ "attention_context_right": 0,
9
+ "attention_invalid_logits_value": -1000000000.0,
10
+ "attention_logit_cap": 50.0,
11
+ "conv_kernel_size": 5,
12
+ "dtype": "bfloat16",
13
+ "gradient_clipping": 10000000000.0,
14
+ "hidden_act": "silu",
15
+ "hidden_size": 1024,
16
+ "initializer_range": 0.02,
17
+ "model_type": "gemma4_audio",
18
+ "num_attention_heads": 8,
19
+ "num_hidden_layers": 12,
20
+ "output_proj_dims": 1536,
21
+ "residual_weight": 0.5,
22
+ "rms_norm_eps": 1e-06,
23
+ "subsampling_conv_channels": [
24
+ 128,
25
+ 32
26
+ ],
27
+ "use_clipped_linears": true
28
+ },
29
+ "audio_token_id": 258881,
30
+ "boa_token_id": 256000,
31
+ "boi_token_id": 255999,
32
+ "dtype": "float32",
33
+ "eoa_token_id": 258883,
34
+ "eoa_token_index": 258883,
35
+ "eoi_token_id": 258882,
36
+ "eos_token_id": [
37
+ 1,
38
+ 106
39
+ ],
40
+ "image_token_id": 258880,
41
+ "initializer_range": 0.02,
42
+ "model_type": "gemma4",
43
+ "text_config": {
44
+ "attention_bias": false,
45
+ "attention_dropout": 0.0,
46
+ "attention_k_eq_v": false,
47
+ "bos_token_id": 2,
48
+ "dtype": "bfloat16",
49
+ "enable_moe_block": false,
50
+ "eos_token_id": 1,
51
+ "expert_intermediate_size": null,
52
+ "final_logit_softcapping": 30.0,
53
+ "head_dim": 256,
54
+ "hidden_activation": "gelu_pytorch_tanh",
55
+ "hidden_size": 2560,
56
+ "hidden_size_per_layer_input": 256,
57
+ "initializer_range": 0.02,
58
+ "intermediate_size": 10240,
59
+ "layer_types": [
60
+ "sliding_attention",
61
+ "sliding_attention",
62
+ "sliding_attention",
63
+ "sliding_attention",
64
+ "sliding_attention",
65
+ "full_attention",
66
+ "sliding_attention",
67
+ "sliding_attention",
68
+ "sliding_attention",
69
+ "sliding_attention",
70
+ "sliding_attention",
71
+ "full_attention",
72
+ "sliding_attention",
73
+ "sliding_attention",
74
+ "sliding_attention",
75
+ "sliding_attention",
76
+ "sliding_attention",
77
+ "full_attention",
78
+ "sliding_attention",
79
+ "sliding_attention",
80
+ "sliding_attention",
81
+ "sliding_attention",
82
+ "sliding_attention",
83
+ "full_attention",
84
+ "sliding_attention",
85
+ "sliding_attention",
86
+ "sliding_attention",
87
+ "sliding_attention",
88
+ "sliding_attention",
89
+ "full_attention",
90
+ "sliding_attention",
91
+ "sliding_attention",
92
+ "sliding_attention",
93
+ "sliding_attention",
94
+ "sliding_attention",
95
+ "full_attention",
96
+ "sliding_attention",
97
+ "sliding_attention",
98
+ "sliding_attention",
99
+ "sliding_attention",
100
+ "sliding_attention",
101
+ "full_attention"
102
+ ],
103
+ "max_position_embeddings": 131072,
104
+ "model_type": "gemma4_text",
105
+ "moe_intermediate_size": null,
106
+ "num_attention_heads": 8,
107
+ "num_experts": null,
108
+ "num_hidden_layers": 42,
109
+ "num_key_value_heads": 2,
110
+ "num_kv_shared_layers": 18,
111
+ "pad_token_id": 0,
112
+ "per_layer_config": {
113
+ "05": {
114
+ "head_dim": 512
115
+ },
116
+ "11": {
117
+ "head_dim": 512
118
+ },
119
+ "17": {
120
+ "head_dim": 512
121
+ },
122
+ "23": {
123
+ "head_dim": 512
124
+ },
125
+ "29": {
126
+ "head_dim": 512
127
+ },
128
+ "35": {
129
+ "head_dim": 512
130
+ },
131
+ "41": {
132
+ "head_dim": 512
133
+ }
134
+ },
135
+ "rms_norm_eps": 1e-06,
136
+ "rope_parameters": {
137
+ "full_attention": {
138
+ "partial_rotary_factor": 0.25,
139
+ "rope_theta": 1000000.0,
140
+ "rope_type": "proportional"
141
+ },
142
+ "sliding_attention": {
143
+ "rope_theta": 10000.0,
144
+ "rope_type": "default"
145
+ }
146
+ },
147
+ "sliding_window": 512,
148
+ "tie_word_embeddings": true,
149
+ "top_k_experts": null,
150
+ "use_bidirectional_attention": null,
151
+ "use_cache": true,
152
+ "use_double_wide_mlp": false,
153
+ "vocab_size": 262144,
154
+ "vocab_size_per_layer_input": 262144
155
+ },
156
+ "tie_word_embeddings": true,
157
+ "transformers_version": "5.20.2",
158
+ "video_token_id": 258884,
159
+ "vision_config": {
160
+ "attention_bias": false,
161
+ "attention_dropout": 0.0,
162
+ "default_output_length": 280,
163
+ "dtype": "bfloat16",
164
+ "global_head_dim": 64,
165
+ "head_dim": 64,
166
+ "hidden_activation": "gelu_pytorch_tanh",
167
+ "hidden_size": 768,
168
+ "initializer_range": 0.02,
169
+ "intermediate_size": 3072,
170
+ "max_position_embeddings": 131072,
171
+ "model_type": "gemma4_vision",
172
+ "num_attention_heads": 12,
173
+ "num_hidden_layers": 16,
174
+ "num_key_value_heads": 12,
175
+ "patch_size": 16,
176
+ "pooling_kernel_size": 3,
177
+ "position_embedding_size": 10240,
178
+ "rms_norm_eps": 1e-06,
179
+ "rope_parameters": {
180
+ "rope_theta": 100.0,
181
+ "rope_type": "axial"
182
+ },
183
+ "standardize": false,
184
+ "use_clipped_linears": true
185
+ },
186
+ "vision_soft_tokens_per_image": 280
187
+ }
figures/demo.svg ADDED
figures/earshot.svg ADDED
figures/matrix.svg ADDED
figures/stats.svg ADDED
figures/text.svg ADDED
generation_config.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 2,
3
+ "do_sample": true,
4
+ "eos_token_id": [
5
+ 1,
6
+ 106,
7
+ 50
8
+ ],
9
+ "pad_token_id": 0,
10
+ "temperature": 1.0,
11
+ "top_k": 64,
12
+ "top_p": 0.95,
13
+ "transformers_version": "5.20.2"
14
+ }
head.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a6f06a9992a8cf0a33726bcf23749ab52f7c832d05af2e1348eb53c45cb13ece
3
+ size 1556
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1a7272eca31e37083c41362c5453dcb1cea6c29d4cb2af985283e3c5931c3b6e
3
+ size 17224656900
processor_config.json ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "audio_ms_per_token": 40,
3
+ "audio_seq_length": 750,
4
+ "feature_extractor": {
5
+ "dither": 0.0,
6
+ "feature_extractor_type": "Gemma4AudioFeatureExtractor",
7
+ "feature_size": 128,
8
+ "fft_length": 512,
9
+ "fft_overdrive": false,
10
+ "frame_length": 320,
11
+ "hop_length": 160,
12
+ "input_scale_factor": 1.0,
13
+ "max_frequency": 8000.0,
14
+ "mel_floor": 0.001,
15
+ "min_frequency": 0.0,
16
+ "padding_side": "right",
17
+ "padding_value": 0.0,
18
+ "per_bin_mean": null,
19
+ "per_bin_stddev": null,
20
+ "preemphasis": 0.0,
21
+ "preemphasis_htk_flavor": true,
22
+ "return_attention_mask": true,
23
+ "sampling_rate": 16000
24
+ },
25
+ "image_processor": {
26
+ "do_convert_rgb": true,
27
+ "do_normalize": false,
28
+ "do_rescale": true,
29
+ "do_resize": true,
30
+ "image_mean": [
31
+ 0.0,
32
+ 0.0,
33
+ 0.0
34
+ ],
35
+ "image_processor_type": "Gemma4ImageProcessor",
36
+ "image_seq_length": 280,
37
+ "image_std": [
38
+ 1.0,
39
+ 1.0,
40
+ 1.0
41
+ ],
42
+ "max_soft_tokens": 280,
43
+ "patch_size": 16,
44
+ "pooling_kernel_size": 3,
45
+ "resample": 3,
46
+ "rescale_factor": 0.00392156862745098
47
+ },
48
+ "image_seq_length": 280,
49
+ "processor_class": "Gemma4Processor",
50
+ "video_processor": {
51
+ "do_convert_rgb": true,
52
+ "do_normalize": true,
53
+ "do_rescale": true,
54
+ "do_resize": true,
55
+ "do_sample_frames": true,
56
+ "image_mean": [
57
+ 0.0,
58
+ 0.0,
59
+ 0.0
60
+ ],
61
+ "image_std": [
62
+ 1.0,
63
+ 1.0,
64
+ 1.0
65
+ ],
66
+ "max_soft_tokens": 70,
67
+ "num_frames": 32,
68
+ "patch_size": 16,
69
+ "pooling_kernel_size": 3,
70
+ "resample": 3,
71
+ "rescale_factor": 0.00392156862745098,
72
+ "return_metadata": false,
73
+ "video_processor_type": "Gemma4VideoProcessor"
74
+ }
75
+ }
readout.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "final_logit_softcapping": 30.0,
3
+ "multi_bias_b": 8.010554313659668,
4
+ "letters": "ABCDEFGHIJKLMNOPQRST",
5
+ "image_soft_tokens": 560
6
+ }
smaug_decide.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Calibrated typed decisions over audio, images or text by Abacus.AI: one forward pass, a probability per option, no generated text.
2
+
3
+ from smaug_decide import SmaugDecide
4
+ model = SmaugDecide.from_pretrained('abacusai/Smaug-Decisions')
5
+ model('clip.wav', 'Has the speaker finished their turn?') # -> {'Yes': 0.93, 'No': 0.07}
6
+ model('clip.wav', 'Which genre is playing?', ['rock', 'jazz', 'classical']) # -> one-answer: probabilities sum to 1
7
+ model('clip.wav', 'Which sounds are present?', ['speech', 'music', 'alarm'], multi=True) # -> select-all: one probability each
8
+ model('photo.jpg', 'Is there a person in the picture?') # images and plain text work the same way
9
+ model('The order never arrived.', 'How upset is the customer?', ['calm', 'annoyed', 'angry'])
10
+
11
+ The readout is the model's own LM-head logits for the option letters A..T at the answer position (softcapped), softmax for one-answer
12
+ questions and sigmoid(z - b) for select-all questions; `b` is the learned select-all threshold stored in readout.json / head.pt.
13
+ Runs on NVIDIA GPUs (bfloat16), Apple Silicon (MPS) and CPU; the device is picked automatically.
14
+ """
15
+ import json
16
+ import os
17
+
18
+ import numpy as np
19
+ import soundfile as sf
20
+ import torch
21
+ from huggingface_hub import snapshot_download
22
+ from PIL import Image
23
+ from transformers import AutoModelForMultimodalLM, AutoProcessor
24
+
25
+
26
+ LETTERS = 'ABCDEFGHIJKLMNOPQRST'
27
+ SAMPLE_RATE, MAX_AUDIO_SECONDS = 16000, 30.0 # the model hears 16 kHz mono; longer clips keep their last 30 s
28
+ MAX_TOKENS, AUDIO_TOKENS_PER_SECOND, IMAGE_TOKENS = 3072, 25, 560 # images at 560 soft tokens, as trained and evaluated
29
+ PREAMBLE = ('You make decisions for apps. Read the rules, the context and the input, then answer the question by choosing '
30
+ 'from the lettered options.')
31
+ IMAGE_SUFFIXES = ('.jpg', '.jpeg', '.png', '.webp', '.gif', '.bmp')
32
+ AUDIO_SUFFIXES = ('.wav', '.flac', '.ogg', '.mp3', '.m4a', '.aiff', '.aif')
33
+ WEIGHT_FILES = ['*.json', '*.jinja', 'model*.safetensors', 'head.pt'] # the checkpoint at the repo root
34
+
35
+
36
+ def trim(s, n):
37
+ if len(s) <= n:
38
+ return s
39
+ return s[:int(n * 0.7)] + ' ... ' + s[-int(n * 0.3):]
40
+
41
+
42
+ def render(question, options, descriptions, multi, media_tag, rules, context, text_input, char_budget):
43
+ """The training prompt, verbatim: preamble, optional rules / context, the input, the lettered options, the answer instruction."""
44
+ parts = [PREAMBLE]
45
+ if rules:
46
+ parts.append(f'Rules: {trim(rules, char_budget // 2)}')
47
+ if context:
48
+ parts.append(f'Context: {trim(context, char_budget)}')
49
+ if media_tag:
50
+ parts.append(f'Input: {media_tag}')
51
+ elif text_input:
52
+ parts.append(f'Input: {trim(text_input, char_budget)}')
53
+ lines = [f'Question: {question}' + (' Select all that apply.' if multi else '')]
54
+ for k, (opt, desc) in enumerate(zip(options, descriptions)):
55
+ lines.append(f'{LETTERS[k]}) {opt}' + (f' — {desc}' if desc else ''))
56
+ parts.append('\n'.join(lines))
57
+ parts.append('Answer with the letters of all options that apply.' if multi else 'Answer with the letter of the best option.')
58
+ return '<bos><|turn>user\n' + '\n'.join(parts) + '<turn|>\n<|turn>model\n'
59
+
60
+
61
+ def load_audio(x):
62
+ """A path, or a (samples, sample_rate) pair, or a 1-D float array at 16 kHz -> mono float32 at 16 kHz, last 30 s."""
63
+ if isinstance(x, str):
64
+ w, sr = sf.read(x, dtype='float32')
65
+ elif isinstance(x, tuple):
66
+ w, sr = x
67
+ else:
68
+ w, sr = x, SAMPLE_RATE
69
+ w = np.asarray(w, dtype=np.float32)
70
+ if w.ndim > 1:
71
+ w = w.mean(1)
72
+ if sr != SAMPLE_RATE: # linear resampling is enough for a reference script; use a proper resampler for production audio
73
+ n = int(round(len(w) * SAMPLE_RATE / sr))
74
+ w = np.interp(np.linspace(0.0, len(w) - 1, n), np.arange(len(w)), w).astype(np.float32)
75
+ return w[-int(MAX_AUDIO_SECONDS * SAMPLE_RATE):]
76
+
77
+
78
+ class SmaugDecide:
79
+ def __init__(self, model, processor, readout, device):
80
+ self.model, self.proc, self.device = model.eval(), processor, device
81
+ tok = processor.tokenizer
82
+ self.letter_ids = torch.tensor([tok(L, add_special_tokens=False)['input_ids'][0] for L in LETTERS], device=device)
83
+ self.cap, self.b = readout.get('final_logit_softcapping'), float(readout['multi_bias_b'])
84
+
85
+ @classmethod
86
+ def from_pretrained(cls, name_or_path, device=None):
87
+ path = name_or_path if os.path.isdir(name_or_path) else snapshot_download(name_or_path, allow_patterns=WEIGHT_FILES)
88
+ device = device or ('cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu')
89
+ model = AutoModelForMultimodalLM.from_pretrained(path, dtype=torch.bfloat16).to(device)
90
+ readout = json.load(open(os.path.join(path, 'readout.json')))
91
+ return cls(model, AutoProcessor.from_pretrained(path), readout, device)
92
+
93
+ @torch.no_grad()
94
+ def __call__(self, inp, question, options=('Yes', 'No'), descriptions=None, multi=False, rules=None, context=None):
95
+ """inp: an audio path / (samples, sr) / 16 kHz array, an image path / PIL image, or a plain string. Returns {option: probability}."""
96
+ options = list(options)
97
+ assert 2 <= len(options) <= len(LETTERS), f'2 to {len(LETTERS)} options'
98
+ descriptions = list(descriptions) if descriptions else [None] * len(options)
99
+ audio = image = text_input = None
100
+ if isinstance(inp, Image.Image) or (isinstance(inp, str) and inp.lower().endswith(IMAGE_SUFFIXES)):
101
+ image = (inp if isinstance(inp, Image.Image) else Image.open(inp)).convert('RGB')
102
+ elif isinstance(inp, str) and not inp.lower().endswith(AUDIO_SUFFIXES) and not os.path.exists(inp):
103
+ text_input = inp
104
+ else:
105
+ audio = load_audio(inp)
106
+ media_tokens = len(audio) / SAMPLE_RATE * AUDIO_TOKENS_PER_SECOND + 2 if audio is not None else (IMAGE_TOKENS + 2 if image is not None else 0)
107
+ tag = '<|audio|>' if audio is not None else '<|image|>' if image is not None else None
108
+ budget = int(max(400, (MAX_TOKENS - media_tokens - 80 - 10 * len(options)) * 3.5))
109
+ text = render(question, options, descriptions, multi, tag, rules, context, text_input, budget)
110
+ kw = {}
111
+ if audio is not None:
112
+ kw['audio'] = [audio]
113
+ if image is not None:
114
+ kw['images'] = [image]; kw['images_kwargs'] = {'max_soft_tokens': IMAGE_TOKENS}
115
+ enc = self.proc(text=[text], return_tensors='pt', add_special_tokens=False, **kw).to(self.device)
116
+ h = self.model.model(**enc, use_cache=False).last_hidden_state[0, -1].float() # hidden state at the answer position
117
+ z = h @ self.model.lm_head.weight[self.letter_ids[:len(options)]].float().T # LM-head logits of the letters only
118
+ if self.cap:
119
+ z = torch.tanh(z / self.cap) * self.cap
120
+ p = torch.sigmoid(z - self.b) if multi else torch.softmax(z, -1)
121
+ return dict(zip(options, p.tolist()))
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cc8d3a0ce36466ccc1278bf987df5f71db1719b9ca6b4118264f45cb627bfe0f
3
+ size 32169626
tokenizer_config.json ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "audio_token": "<|audio|>",
3
+ "backend": "tokenizers",
4
+ "boa_token": "<|audio>",
5
+ "boi_token": "<|image>",
6
+ "bos_token": "<bos>",
7
+ "eoa_token": "<audio|>",
8
+ "eoc_token": "<channel|>",
9
+ "eoi_token": "<image|>",
10
+ "eos_token": "<eos>",
11
+ "eot_token": "<turn|>",
12
+ "escape_token": "<|\"|>",
13
+ "etc_token": "<tool_call|>",
14
+ "etd_token": "<tool|>",
15
+ "etr_token": "<tool_response|>",
16
+ "extra_special_tokens": [
17
+ "<|video|>"
18
+ ],
19
+ "image_token": "<|image|>",
20
+ "is_local": true,
21
+ "local_files_only": false,
22
+ "mask_token": "<mask>",
23
+ "model_max_length": 1000000000000000019884624838656,
24
+ "model_specific_special_tokens": {
25
+ "audio_token": "<|audio|>",
26
+ "boa_token": "<|audio>",
27
+ "boi_token": "<|image>",
28
+ "eoa_token": "<audio|>",
29
+ "eoc_token": "<channel|>",
30
+ "eoi_token": "<image|>",
31
+ "eot_token": "<turn|>",
32
+ "escape_token": "<|\"|>",
33
+ "etc_token": "<tool_call|>",
34
+ "etd_token": "<tool|>",
35
+ "etr_token": "<tool_response|>",
36
+ "image_token": "<|image|>",
37
+ "soc_token": "<|channel>",
38
+ "sot_token": "<|turn>",
39
+ "stc_token": "<|tool_call>",
40
+ "std_token": "<|tool>",
41
+ "str_token": "<|tool_response>",
42
+ "think_token": "<|think|>"
43
+ },
44
+ "pad_token": "<pad>",
45
+ "padding_side": "left",
46
+ "processor_class": "Gemma4Processor",
47
+ "response_schema": {
48
+ "properties": {
49
+ "content": {
50
+ "type": "string"
51
+ },
52
+ "role": {
53
+ "const": "assistant"
54
+ },
55
+ "thinking": {
56
+ "type": "string"
57
+ },
58
+ "tool_calls": {
59
+ "items": {
60
+ "properties": {
61
+ "function": {
62
+ "properties": {
63
+ "arguments": {
64
+ "additionalProperties": {},
65
+ "type": "object",
66
+ "x-parser": "gemma4-tool-call"
67
+ },
68
+ "name": {
69
+ "type": "string"
70
+ }
71
+ },
72
+ "type": "object",
73
+ "x-regex": "call\\:(?P<name>\\w+)(?P<arguments>\\{.*\\})"
74
+ },
75
+ "type": {
76
+ "const": "function"
77
+ }
78
+ },
79
+ "type": "object"
80
+ },
81
+ "type": "array",
82
+ "x-regex-iterator": "<\\|tool_call>(.*?)<tool_call\\|>"
83
+ }
84
+ },
85
+ "type": "object",
86
+ "x-regex": "(\\<\\|channel\\>thought\\n(?P<thinking>.*?)\\<channel\\|\\>)?(?P<tool_calls>\\<\\|tool_call\\>.*\\<tool_call\\|\\>)?(?P<content>(?:(?!\\<turn\\|\\>)(?!\\<\\|tool_response\\>).)+)?(?:\\<turn\\|\\>|\\<\\|tool_response\\>)?"
87
+ },
88
+ "response_template": {
89
+ "defaults": {
90
+ "role": "assistant"
91
+ },
92
+ "fields": {
93
+ "content": {
94
+ "close": [
95
+ "<turn|>",
96
+ "<|tool_response>",
97
+ "<eos>"
98
+ ],
99
+ "content": "text"
100
+ },
101
+ "thinking": {
102
+ "close": "<channel|>",
103
+ "content": "text",
104
+ "open": "<|channel>thought\n"
105
+ },
106
+ "tool_calls": {
107
+ "close": "<tool_call|>",
108
+ "content": "json",
109
+ "content_args": {
110
+ "string_delims": [
111
+ [
112
+ "<|\"|>",
113
+ "<|\"|>"
114
+ ]
115
+ ],
116
+ "unquoted_keys": true
117
+ },
118
+ "open_pattern": "<\\|tool_call>call:(?P<name>\\w+)",
119
+ "repeats": true,
120
+ "transform": {
121
+ "function": {
122
+ "arguments": "{content}",
123
+ "name": "{name}"
124
+ },
125
+ "type": "function"
126
+ }
127
+ }
128
+ },
129
+ "start_anchor": [
130
+ "<|turn>model\n",
131
+ "<tool_response|>"
132
+ ]
133
+ },
134
+ "soc_token": "<|channel>",
135
+ "sot_token": "<|turn>",
136
+ "stc_token": "<|tool_call>",
137
+ "std_token": "<|tool>",
138
+ "str_token": "<|tool_response>",
139
+ "think_token": "<|think|>",
140
+ "tokenizer_class": "GemmaTokenizer",
141
+ "unk_token": "<unk>"
142
+ }