Ruiruiz30 commited on
Commit
72c6b77
·
verified ·
1 Parent(s): 7130687

Add OmniJev 4B MLX 5-bit model card, head, and inference wrapper

Browse files
LICENSE ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ OmniJev - inference code and model weights
2
+ Copyright 2026 Beijing Zhongguancun Academy, Institute of Automation of the Chinese Academy of Sciences, and Zevo
3
+ (北京中关村学院、中国科学院自动化研究所、智进化)
4
+
5
+ Licensed under the Apache License, Version 2.0 (full text below). The backbone model (Qwen3-VL-4B-Instruct) keeps its own license.
6
+
7
+
8
+ Apache License
9
+ Version 2.0, January 2004
10
+ http://www.apache.org/licenses/
11
+
12
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
13
+
14
+ 1. Definitions.
15
+
16
+ "License" shall mean the terms and conditions for use, reproduction,
17
+ and distribution as defined by Sections 1 through 9 of this document.
18
+
19
+ "Licensor" shall mean the copyright owner or entity authorized by
20
+ the copyright owner that is granting the License.
21
+
22
+ "Legal Entity" shall mean the union of the acting entity and all
23
+ other entities that control, are controlled by, or are under common
24
+ control with that entity. For the purposes of this definition,
25
+ "control" means (i) the power, direct or indirect, to cause the
26
+ direction or management of such entity, whether by contract or
27
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
28
+ outstanding shares, or (iii) beneficial ownership of such entity.
29
+
30
+ "You" (or "Your") shall mean an individual or Legal Entity
31
+ exercising permissions granted by this License.
32
+
33
+ "Source" form shall mean the preferred form for making modifications,
34
+ including but not limited to software source code, documentation
35
+ source, and configuration files.
36
+
37
+ "Object" form shall mean any form resulting from mechanical
38
+ transformation or translation of a Source form, including but
39
+ not limited to compiled object code, generated documentation,
40
+ and conversions to other media types.
41
+
42
+ "Work" shall mean the work of authorship, whether in Source or
43
+ Object form, made available under the License, as indicated by a
44
+ copyright notice that is included in or attached to the work
45
+ (an example is provided in the Appendix below).
46
+
47
+ "Derivative Works" shall mean any work, whether in Source or Object
48
+ form, that is based on (or derived from) the Work and for which the
49
+ editorial revisions, annotations, elaborations, or other modifications
50
+ represent, as a whole, an original work of authorship. For the purposes
51
+ of this License, Derivative Works shall not include works that remain
52
+ separable from, or merely link (or bind by name) to the interfaces of,
53
+ the Work and Derivative Works thereof.
54
+
55
+ "Contribution" shall mean any work of authorship, including
56
+ the original version of the Work and any modifications or additions
57
+ to that Work or Derivative Works thereof, that is intentionally
58
+ submitted to Licensor for inclusion in the Work by the copyright owner
59
+ or by an individual or Legal Entity authorized to submit on behalf of
60
+ the copyright owner. For the purposes of this definition, "submitted"
61
+ means any form of electronic, verbal, or written communication sent
62
+ to the Licensor or its representatives, including but not limited to
63
+ communication on electronic mailing lists, source code control systems,
64
+ and issue tracking systems that are managed by, or on behalf of, the
65
+ Licensor for the purpose of discussing and improving the Work, but
66
+ excluding communication that is conspicuously marked or otherwise
67
+ designated in writing by the copyright owner as "Not a Contribution."
68
+
69
+ "Contributor" shall mean Licensor and any individual or Legal Entity
70
+ on behalf of whom a Contribution has been received by Licensor and
71
+ subsequently incorporated within the Work.
72
+
73
+ 2. Grant of Copyright License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ copyright license to reproduce, prepare Derivative Works of,
77
+ publicly display, publicly perform, sublicense, and distribute the
78
+ Work and such Derivative Works in Source or Object form.
79
+
80
+ 3. Grant of Patent License. Subject to the terms and conditions of
81
+ this License, each Contributor hereby grants to You a perpetual,
82
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
83
+ (except as stated in this section) patent license to make, have made,
84
+ use, offer to sell, sell, import, and otherwise transfer the Work,
85
+ where such license applies only to those patent claims licensable
86
+ by such Contributor that are necessarily infringed by their
87
+ Contribution(s) alone or by combination of their Contribution(s)
88
+ with the Work to which such Contribution(s) was submitted. If You
89
+ institute patent litigation against any entity (including a
90
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
91
+ or a Contribution incorporated within the Work constitutes direct
92
+ or contributory patent infringement, then any patent licenses
93
+ granted to You under this License for that Work shall terminate
94
+ as of the date such litigation is filed.
95
+
96
+ 4. Redistribution. You may reproduce and distribute copies of the
97
+ Work or Derivative Works thereof in any medium, with or without
98
+ modifications, and in Source or Object form, provided that You
99
+ meet the following conditions:
100
+
101
+ (a) You must give any other recipients of the Work or
102
+ Derivative Works a copy of this License; and
103
+
104
+ (b) You must cause any modified files to carry prominent notices
105
+ stating that You changed the files; and
106
+
107
+ (c) You must retain, in the Source form of any Derivative Works
108
+ that You distribute, all copyright, patent, trademark, and
109
+ attribution notices from the Source form of the Work,
110
+ excluding those notices that do not pertain to any part of
111
+ the Derivative Works; and
112
+
113
+ (d) If the Work includes a "NOTICE" text file as part of its
114
+ distribution, then any Derivative Works that You distribute must
115
+ include a readable copy of the attribution notices contained
116
+ within such NOTICE file, excluding those notices that do not
117
+ pertain to any part of the Derivative Works, in at least one
118
+ of the following places: within a NOTICE text file distributed
119
+ as part of the Derivative Works; within the Source form or
120
+ documentation, if provided along with the Derivative Works; or,
121
+ within a display generated by the Derivative Works, if and
122
+ wherever such third-party notices normally appear. The contents
123
+ of the NOTICE file are for informational purposes only and
124
+ do not modify the License. You may add Your own attribution
125
+ notices within Derivative Works that You distribute, alongside
126
+ or as an addendum to the NOTICE text from the Work, provided
127
+ that such additional attribution notices cannot be construed
128
+ as modifying the License.
129
+
130
+ You may add Your own copyright statement to Your modifications and
131
+ may provide additional or different license terms and conditions
132
+ for use, reproduction, or distribution of Your modifications, or
133
+ for any such Derivative Works as a whole, provided Your use,
134
+ reproduction, and distribution of the Work otherwise complies with
135
+ the conditions stated in this License.
136
+
137
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
138
+ any Contribution intentionally submitted for inclusion in the Work
139
+ by You to the Licensor shall be under the terms and conditions of
140
+ this License, without any additional terms or conditions.
141
+ Notwithstanding the above, nothing herein shall supersede or modify
142
+ the terms of any separate license agreement you may have executed
143
+ with Licensor regarding such Contributions.
144
+
145
+ 6. Trademarks. This License does not grant permission to use the trade
146
+ names, trademarks, service marks, or product names of the Licensor,
147
+ except as required for reasonable and customary use in describing the
148
+ origin of the Work and reproducing the content of the NOTICE file.
149
+
150
+ 7. Disclaimer of Warranty. Unless required by applicable law or
151
+ agreed to in writing, Licensor provides the Work (and each
152
+ Contributor provides its Contributions) on an "AS IS" BASIS,
153
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
154
+ implied, including, without limitation, any warranties or conditions
155
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
156
+ PARTICULAR PURPOSE. You are solely responsible for determining the
157
+ appropriateness of using or redistributing the Work and assume any
158
+ risks associated with Your exercise of permissions under this License.
159
+
160
+ 8. Limitation of Liability. In no event and under no legal theory,
161
+ whether in tort (including negligence), contract, or otherwise,
162
+ unless required by applicable law (such as deliberate and grossly
163
+ negligent acts) or agreed to in writing, shall any Contributor be
164
+ liable to You for damages, including any direct, indirect, special,
165
+ incidental, or consequential damages of any character arising as a
166
+ result of this License or out of the use or inability to use the
167
+ Work (including but not limited to damages for loss of goodwill,
168
+ work stoppage, computer failure or malfunction, or any and all
169
+ other commercial damages or losses), even if such Contributor
170
+ has been advised of the possibility of such damages.
171
+
172
+ 9. Accepting Warranty or Additional Liability. While redistributing
173
+ the Work or Derivative Works thereof, You may choose to offer,
174
+ and charge a fee for, acceptance of support, warranty, indemnity,
175
+ or other liability obligations and/or rights consistent with this
176
+ License. However, in accepting such obligations, You may act only
177
+ on Your own behalf and on Your sole responsibility, not on behalf
178
+ of any other Contributor, and only if You agree to indemnify,
179
+ defend, and hold each Contributor harmless for any liability
180
+ incurred by, or claims asserted against, such Contributor by reason
181
+ of your accepting any such warranty or additional liability.
182
+
183
+ END OF TERMS AND CONDITIONS
184
+
185
+ APPENDIX: How to apply the Apache License to your work.
186
+
187
+ To apply the Apache License to your work, attach the following
188
+ boilerplate notice, with the fields enclosed by brackets "[]"
189
+ replaced with your own identifying information. (Don't include
190
+ the brackets!) The text should be enclosed in the appropriate
191
+ comment syntax for the file format. We also recommend that a
192
+ file or class name and description of purpose be included on the
193
+ same "printed page" as the copyright notice for easier
194
+ identification within third-party archives.
195
+
196
+ Copyright [yyyy] [name of copyright owner]
197
+
198
+ Licensed under the Apache License, Version 2.0 (the "License");
199
+ you may not use this file except in compliance with the License.
200
+ You may obtain a copy of the License at
201
+
202
+ http://www.apache.org/licenses/LICENSE-2.0
203
+
204
+ Unless required by applicable law or agreed to in writing, software
205
+ distributed under the License is distributed on an "AS IS" BASIS,
206
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
207
+ See the License for the specific language governing permissions and
208
+ limitations under the License.
NOTICE.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Attribution
2
+
3
+ This repository is an independent Apple Silicon MLX conversion of the official [OmniJev v1.1 4B](https://huggingface.co/tinnel123/OmniJev) checkpoint.
4
+
5
+ - Upstream decision model and head: Beijing Zhongguancun Academy, Institute of Automation of the Chinese Academy of Sciences, and Zevo.
6
+ - Backbone: [Qwen/Qwen3.5-4B](https://huggingface.co/Qwen/Qwen3.5-4B).
7
+ - Upstream project and license: [tinnel123666888/OmniJev](https://github.com/tinnel123666888/OmniJev), Apache-2.0. The Qwen backbone keeps its own upstream terms.
8
+ - This repository contains a fused and quantized derivative plus an MLX inference wrapper. It is not an official release of the upstream projects.
README.md ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model:
4
+ - tinnel123/OmniJev
5
+ - Qwen/Qwen3.5-4B
6
+ library_name: mlx
7
+ pipeline_tag: image-text-to-text
8
+ tags:
9
+ - mlx
10
+ - apple-silicon
11
+ - multimodal
12
+ - qwen3.5
13
+ - omnijev
14
+ - decision-making
15
+ - quantized
16
+ language:
17
+ - en
18
+ - zh
19
+ ---
20
+
21
+ # OmniJev-MLX-5bit
22
+
23
+ An independent Apple Silicon MLX conversion of the official [OmniJev v1.1 4B](https://huggingface.co/tinnel123/OmniJev) checkpoint.
24
+
25
+ The model uses the official `Qwen/Qwen3.5-4B` backbone and OmniJev decision head. The official LoRA adapter was merged into the backbone in bfloat16, and the fused backbone was then converted to **5-bit affine quantization with group size 64**. The decision head remains a separate FP32 file and is loaded at inference time.
26
+
27
+ This repository is a conversion and packaging release. **It is not a new fine-tune and does not contain additional training of the 4B model or decision head.** It is not an official release of the upstream OmniJev or Qwen projects.
28
+
29
+ ## What is included
30
+
31
+ - `model.safetensors`: fused Qwen3.5/OmniJev backbone in MLX 5-bit format.
32
+ - `decision_head/head.npz`: the official OmniJev 4B decision head exported from the released `head.pt`.
33
+ - `decision_head/head_meta.json`: upstream calibration metadata, including the choice temperature.
34
+ - `omni_mlx/classifier.py`: a small MLX inference wrapper for typed visual decisions.
35
+ - `conversion.json`: source, quantization and validation provenance.
36
+ - `head_provenance.json`: checksum and export provenance for the decision head.
37
+ - `benchmarks/`: the local fixed-subset ScienceQA measurements used for this conversion.
38
+
39
+ The head is separate from the quantized backbone. The runtime first obtains option/question representations from the backbone and then applies the decision head. This is different from merging the head into the Qwen weight tensors.
40
+
41
+ ## Conversion provenance
42
+
43
+ ```text
44
+ Qwen/Qwen3.5-4B
45
+ + official OmniJev v1.1 LoRA adapter
46
+ └─ merge in bfloat16
47
+ fused OmniJev backbone
48
+ └─ MLX affine quantization, 5 bits, group size 64
49
+ model.safetensors
50
+
51
+ official OmniJev head.pt
52
+ └─ format export only
53
+ decision_head/head.npz (float32)
54
+ ```
55
+
56
+ The source OmniJev release reports a rank-32 LoRA adapter and an independently calibrated decision head. This repository preserves those learned weights; it does not retrain them.
57
+
58
+ ## Local validation
59
+
60
+ These measurements use one fixed 50-image ScienceQA visual subset, the same subset for both resolutions. They are local conversion checks, not the official OmniJev benchmark and not a universal accuracy claim.
61
+
62
+ Hardware: Mac mini M4, 16 GB unified memory. Batch size 1.
63
+
64
+ | Input setting | Correct | Accuracy | Warm median | P95 |
65
+ |---|---:|---:|---:|---:|
66
+ | `max_pixels=87808` (112-level input) | 44/50 | 88.0% | ~737 ms | ~1,013 ms |
67
+ | `max_pixels=175616` (224-level input) | 44/50 | 88.0% | ~1,050 ms | ~1,354 ms |
68
+
69
+ The complete per-item outputs are in [`benchmarks/scienceqa-50-112.json`](benchmarks/scienceqa-50-112.json) and [`benchmarks/scienceqa-50-224.json`](benchmarks/scienceqa-50-224.json). The text-only JevBench and the upstream OmniJev score tables should not be inferred from this 50-image check.
70
+
71
+ ## Installation
72
+
73
+ This package targets Apple Silicon and MLX.
74
+
75
+ ```bash
76
+ hf download Ruiruiz30/OmniJev-MLX-5bit \
77
+ --local-dir OmniJev-MLX-5bit
78
+
79
+ cd OmniJev-MLX-5bit
80
+ python3 -m venv .venv
81
+ source .venv/bin/activate
82
+ pip install -r requirements.txt
83
+ ```
84
+
85
+ The model is about 3.3 GB. Keep the repository's directory structure intact so that `decision_head/head.npz` and `decision_head/head_meta.json` remain next to each other.
86
+
87
+ ## Image decision
88
+
89
+ The included wrapper returns probabilities for the supplied options and selects the highest-probability option. It does not generate a free-form explanation.
90
+
91
+ ```bash
92
+ python -m omni_mlx.classifier \
93
+ --model . \
94
+ --image /path/to/frame.png \
95
+ --state "A kart is approaching a right turn." \
96
+ --question "Which steering action is best?" \
97
+ --options "Turn left" "Hold center" "Turn right" \
98
+ --max-pixels 87808
99
+ ```
100
+
101
+ The output contains `prediction`, option `probabilities`, `abstain_probability`, elapsed time and the quantization setting. The supplied options must be distinct; the head supports typed choice, yes/no and score-style candidate sets through the same candidate-scoring path.
102
+
103
+ The default `max_pixels=87808` is the setting used for the faster local validation above. Increase it when small visual details matter, and validate the resulting accuracy and latency on your own frames.
104
+
105
+ ## Upstream sources and license
106
+
107
+ - [Official OmniJev repository](https://github.com/tinnel123666888/OmniJev)
108
+ - [Official OmniJev v1.1 checkpoint](https://huggingface.co/tinnel123/OmniJev)
109
+ - [Qwen3.5-4B backbone](https://huggingface.co/Qwen/Qwen3.5-4B)
110
+
111
+ The OmniJev project and this conversion wrapper are released under Apache-2.0. The Qwen backbone retains its own upstream terms. See [`LICENSE`](LICENSE) and [`NOTICE.md`](NOTICE.md).
benchmarks/scienceqa-50-112.json ADDED
@@ -0,0 +1,619 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "summary": {
3
+ "questions": 50,
4
+ "correct": 44,
5
+ "accuracy": 0.88,
6
+ "latency_ms": {
7
+ "median": 737.4855829984881,
8
+ "p95": 1012.7517079818062,
9
+ "mean": 784.4947082991712
10
+ },
11
+ "model": "third_party/OmniJev/models/Qwen3.5-4B-OmniJev-MLX-5bit",
12
+ "note": "Visual ScienceQA subset; not text-only JevBench."
13
+ },
14
+ "results": [
15
+ {
16
+ "id": "scienceqa/val/21023",
17
+ "target_index": 2,
18
+ "prediction_index": 3,
19
+ "probabilities": [
20
+ 0.0006199186900630593,
21
+ 0.0036421569529920816,
22
+ 0.16167014837265015,
23
+ 0.7949264645576477,
24
+ 0.039141345769166946
25
+ ],
26
+ "elapsed_ms": 1012.7517079818062
27
+ },
28
+ {
29
+ "id": "scienceqa/val/7180",
30
+ "target_index": 2,
31
+ "prediction_index": 2,
32
+ "probabilities": [
33
+ 0.0006342903943732381,
34
+ 0.001218338031321764,
35
+ 0.998112678527832,
36
+ 3.469285002211109e-05
37
+ ],
38
+ "elapsed_ms": 684.1524579795077
39
+ },
40
+ {
41
+ "id": "scienceqa/val/2642",
42
+ "target_index": 2,
43
+ "prediction_index": 2,
44
+ "probabilities": [
45
+ 1.4533699868479744e-05,
46
+ 0.0008359018247574568,
47
+ 0.9989796280860901,
48
+ 0.00016994107863865793
49
+ ],
50
+ "elapsed_ms": 800.3734169760719
51
+ },
52
+ {
53
+ "id": "scienceqa/val/16468",
54
+ "target_index": 0,
55
+ "prediction_index": 0,
56
+ "probabilities": [
57
+ 0.9725253582000732,
58
+ 0.027463596314191818,
59
+ 5.486343184202269e-07,
60
+ 1.6595530496488209e-06,
61
+ 8.804287972452585e-06
62
+ ],
63
+ "elapsed_ms": 699.9967499868944
64
+ },
65
+ {
66
+ "id": "scienceqa/val/19506",
67
+ "target_index": 1,
68
+ "prediction_index": 0,
69
+ "probabilities": [
70
+ 0.4955705404281616,
71
+ 0.17129716277122498,
72
+ 0.3331323564052582
73
+ ],
74
+ "elapsed_ms": 712.0736669749022
75
+ },
76
+ {
77
+ "id": "scienceqa/val/8767",
78
+ "target_index": 1,
79
+ "prediction_index": 1,
80
+ "probabilities": [
81
+ 0.005915054120123386,
82
+ 0.9934005737304688,
83
+ 0.0006844155723229051
84
+ ],
85
+ "elapsed_ms": 633.8063329458237
86
+ },
87
+ {
88
+ "id": "scienceqa/val/16515",
89
+ "target_index": 2,
90
+ "prediction_index": 2,
91
+ "probabilities": [
92
+ 2.5153735805361066e-07,
93
+ 1.2259709913919892e-09,
94
+ 0.9999985694885254,
95
+ 6.42186108734677e-08,
96
+ 1.0174338740398525e-06
97
+ ],
98
+ "elapsed_ms": 677.4182500084862
99
+ },
100
+ {
101
+ "id": "scienceqa/val/16938",
102
+ "target_index": 1,
103
+ "prediction_index": 1,
104
+ "probabilities": [
105
+ 0.20825311541557312,
106
+ 0.7906606793403625,
107
+ 0.0010861753253266215
108
+ ],
109
+ "elapsed_ms": 1000.156500027515
110
+ },
111
+ {
112
+ "id": "scienceqa/val/13212",
113
+ "target_index": 0,
114
+ "prediction_index": 0,
115
+ "probabilities": [
116
+ 0.9983437061309814,
117
+ 8.884436101652682e-05,
118
+ 0.000598268467001617,
119
+ 0.0009691402083262801
120
+ ],
121
+ "elapsed_ms": 669.4296670029871
122
+ },
123
+ {
124
+ "id": "scienceqa/val/4539",
125
+ "target_index": 3,
126
+ "prediction_index": 0,
127
+ "probabilities": [
128
+ 0.4982156753540039,
129
+ 0.328609824180603,
130
+ 0.06777261197566986,
131
+ 0.10534052550792694,
132
+ 6.127937376732007e-05
133
+ ],
134
+ "elapsed_ms": 689.8489589802921
135
+ },
136
+ {
137
+ "id": "scienceqa/val/11884",
138
+ "target_index": 1,
139
+ "prediction_index": 1,
140
+ "probabilities": [
141
+ 0.00019638118101283908,
142
+ 0.9997889399528503,
143
+ 1.4690514944959432e-05
144
+ ],
145
+ "elapsed_ms": 1089.2853750265203
146
+ },
147
+ {
148
+ "id": "scienceqa/val/15622",
149
+ "target_index": 1,
150
+ "prediction_index": 1,
151
+ "probabilities": [
152
+ 1.2257983144081663e-06,
153
+ 0.9998711347579956,
154
+ 2.1552657926804386e-05,
155
+ 0.00010605484567349777
156
+ ],
157
+ "elapsed_ms": 884.3026669928804
158
+ },
159
+ {
160
+ "id": "scienceqa/val/17192",
161
+ "target_index": 3,
162
+ "prediction_index": 3,
163
+ "probabilities": [
164
+ 3.1174602099781623e-07,
165
+ 1.1572042524221615e-07,
166
+ 3.46970040254746e-07,
167
+ 0.999992847442627,
168
+ 6.40239386484609e-06
169
+ ],
170
+ "elapsed_ms": 700.0882920110598
171
+ },
172
+ {
173
+ "id": "scienceqa/val/2461",
174
+ "target_index": 2,
175
+ "prediction_index": 2,
176
+ "probabilities": [
177
+ 0.00027162706828676164,
178
+ 1.1542095307959244e-05,
179
+ 0.9994391798973083,
180
+ 0.0002776358451228589
181
+ ],
182
+ "elapsed_ms": 689.2803750233725
183
+ },
184
+ {
185
+ "id": "scienceqa/val/8688",
186
+ "target_index": 0,
187
+ "prediction_index": 0,
188
+ "probabilities": [
189
+ 0.9999678134918213,
190
+ 5.3547882998827845e-06,
191
+ 2.685382787603885e-05
192
+ ],
193
+ "elapsed_ms": 881.5387500217184
194
+ },
195
+ {
196
+ "id": "scienceqa/val/15419",
197
+ "target_index": 2,
198
+ "prediction_index": 2,
199
+ "probabilities": [
200
+ 2.8274806496142446e-08,
201
+ 1.1287261969528117e-07,
202
+ 0.9999901056289673,
203
+ 1.562869300641978e-08,
204
+ 9.724893970997073e-06
205
+ ],
206
+ "elapsed_ms": 722.5853750132956
207
+ },
208
+ {
209
+ "id": "scienceqa/val/18512",
210
+ "target_index": 1,
211
+ "prediction_index": 1,
212
+ "probabilities": [
213
+ 3.031034534473065e-09,
214
+ 0.9999986886978149,
215
+ 1.2731197784887627e-06
216
+ ],
217
+ "elapsed_ms": 735.6334999785759
218
+ },
219
+ {
220
+ "id": "scienceqa/val/921",
221
+ "target_index": 1,
222
+ "prediction_index": 1,
223
+ "probabilities": [
224
+ 0.0015609971014782786,
225
+ 0.994932234287262,
226
+ 0.003506765468046069
227
+ ],
228
+ "elapsed_ms": 723.512375028804
229
+ },
230
+ {
231
+ "id": "scienceqa/val/17574",
232
+ "target_index": 1,
233
+ "prediction_index": 1,
234
+ "probabilities": [
235
+ 4.925988469040021e-05,
236
+ 0.9972556233406067,
237
+ 0.00015376514056697488,
238
+ 0.0025415101554244757
239
+ ],
240
+ "elapsed_ms": 738.4067500242963
241
+ },
242
+ {
243
+ "id": "scienceqa/val/4517",
244
+ "target_index": 1,
245
+ "prediction_index": 0,
246
+ "probabilities": [
247
+ 0.8720545768737793,
248
+ 0.1277339905500412,
249
+ 0.00021148081577848643
250
+ ],
251
+ "elapsed_ms": 1234.5357919693924
252
+ },
253
+ {
254
+ "id": "scienceqa/val/12959",
255
+ "target_index": 0,
256
+ "prediction_index": 0,
257
+ "probabilities": [
258
+ 0.999830961227417,
259
+ 3.3016458473866805e-05,
260
+ 1.574484258526354e-06,
261
+ 0.00013444400974549353
262
+ ],
263
+ "elapsed_ms": 897.1697079832666
264
+ },
265
+ {
266
+ "id": "scienceqa/val/4018",
267
+ "target_index": 3,
268
+ "prediction_index": 3,
269
+ "probabilities": [
270
+ 0.0005697154556401074,
271
+ 0.0002200113667640835,
272
+ 0.0010174753842875361,
273
+ 0.9911803603172302,
274
+ 0.007012455724179745
275
+ ],
276
+ "elapsed_ms": 730.3262079949491
277
+ },
278
+ {
279
+ "id": "scienceqa/val/17681",
280
+ "target_index": 2,
281
+ "prediction_index": 2,
282
+ "probabilities": [
283
+ 1.1745694417086838e-09,
284
+ 1.627603296583402e-07,
285
+ 0.9999995231628418,
286
+ 3.7544154452007206e-07
287
+ ],
288
+ "elapsed_ms": 725.4358750069514
289
+ },
290
+ {
291
+ "id": "scienceqa/val/9964",
292
+ "target_index": 2,
293
+ "prediction_index": 2,
294
+ "probabilities": [
295
+ 0.00019135519687552005,
296
+ 0.00010769777145469561,
297
+ 0.9994826316833496,
298
+ 0.00021833789651282132
299
+ ],
300
+ "elapsed_ms": 928.818374988623
301
+ },
302
+ {
303
+ "id": "scienceqa/val/340",
304
+ "target_index": 1,
305
+ "prediction_index": 1,
306
+ "probabilities": [
307
+ 0.010052929632365704,
308
+ 0.9549948573112488,
309
+ 0.0005331069114618003,
310
+ 0.03441905975341797
311
+ ],
312
+ "elapsed_ms": 736.3460840424523
313
+ },
314
+ {
315
+ "id": "scienceqa/val/20723",
316
+ "target_index": 0,
317
+ "prediction_index": 0,
318
+ "probabilities": [
319
+ 0.9954797029495239,
320
+ 0.0012700710212811828,
321
+ 0.0032501465175300837
322
+ ],
323
+ "elapsed_ms": 839.5821249578148
324
+ },
325
+ {
326
+ "id": "scienceqa/val/13835",
327
+ "target_index": 0,
328
+ "prediction_index": 0,
329
+ "probabilities": [
330
+ 0.9985985159873962,
331
+ 0.00014829420251771808,
332
+ 7.677712710574269e-05,
333
+ 0.0011763935908675194
334
+ ],
335
+ "elapsed_ms": 684.5203749835491
336
+ },
337
+ {
338
+ "id": "scienceqa/val/8404",
339
+ "target_index": 3,
340
+ "prediction_index": 3,
341
+ "probabilities": [
342
+ 0.0001755337871145457,
343
+ 0.0001640830741962418,
344
+ 0.0021861197892576456,
345
+ 0.9700518846511841,
346
+ 0.027422383427619934
347
+ ],
348
+ "elapsed_ms": 744.3796250154264
349
+ },
350
+ {
351
+ "id": "scienceqa/val/326",
352
+ "target_index": 1,
353
+ "prediction_index": 1,
354
+ "probabilities": [
355
+ 0.00031515376758761704,
356
+ 0.9986709356307983,
357
+ 0.0010140076046809554
358
+ ],
359
+ "elapsed_ms": 855.3466669982299
360
+ },
361
+ {
362
+ "id": "scienceqa/val/7684",
363
+ "target_index": 2,
364
+ "prediction_index": 2,
365
+ "probabilities": [
366
+ 0.261148601770401,
367
+ 0.06522262096405029,
368
+ 0.67287677526474,
369
+ 0.0007520208018831909
370
+ ],
371
+ "elapsed_ms": 939.7157080238685
372
+ },
373
+ {
374
+ "id": "scienceqa/val/6621",
375
+ "target_index": 1,
376
+ "prediction_index": 1,
377
+ "probabilities": [
378
+ 9.295739289427729e-09,
379
+ 0.9999979734420776,
380
+ 5.027599669915617e-08,
381
+ 1.4151556797514786e-06,
382
+ 5.762834689448937e-07
383
+ ],
384
+ "elapsed_ms": 737.8222920233384
385
+ },
386
+ {
387
+ "id": "scienceqa/val/11466",
388
+ "target_index": 0,
389
+ "prediction_index": 0,
390
+ "probabilities": [
391
+ 0.4861493408679962,
392
+ 0.045885149389505386,
393
+ 0.43684297800064087,
394
+ 0.031122520565986633
395
+ ],
396
+ "elapsed_ms": 733.1671669962816
397
+ },
398
+ {
399
+ "id": "scienceqa/val/4791",
400
+ "target_index": 0,
401
+ "prediction_index": 1,
402
+ "probabilities": [
403
+ 0.4698958396911621,
404
+ 0.5242437720298767,
405
+ 0.005860346369445324
406
+ ],
407
+ "elapsed_ms": 772.0198750030249
408
+ },
409
+ {
410
+ "id": "scienceqa/val/4550",
411
+ "target_index": 0,
412
+ "prediction_index": 0,
413
+ "probabilities": [
414
+ 0.9999977350234985,
415
+ 1.7362581274937838e-06,
416
+ 3.809745052762992e-08,
417
+ 1.2352370237778132e-09,
418
+ 5.158440217201132e-07
419
+ ],
420
+ "elapsed_ms": 743.6611659941263
421
+ },
422
+ {
423
+ "id": "scienceqa/val/8558",
424
+ "target_index": 0,
425
+ "prediction_index": 0,
426
+ "probabilities": [
427
+ 0.9053918123245239,
428
+ 0.07601229846477509,
429
+ 0.017282212153077126,
430
+ 0.0013136324705556035
431
+ ],
432
+ "elapsed_ms": 716.0367500036955
433
+ },
434
+ {
435
+ "id": "scienceqa/val/19945",
436
+ "target_index": 0,
437
+ "prediction_index": 0,
438
+ "probabilities": [
439
+ 0.7528671622276306,
440
+ 0.24187956750392914,
441
+ 0.005253252573311329
442
+ ],
443
+ "elapsed_ms": 864.9832080118358
444
+ },
445
+ {
446
+ "id": "scienceqa/val/8871",
447
+ "target_index": 0,
448
+ "prediction_index": 0,
449
+ "probabilities": [
450
+ 0.9999978542327881,
451
+ 1.39499331908155e-06,
452
+ 7.841769900096551e-08,
453
+ 7.269268298415454e-09,
454
+ 5.693436264664342e-07
455
+ ],
456
+ "elapsed_ms": 739.8256249725819
457
+ },
458
+ {
459
+ "id": "scienceqa/val/4884",
460
+ "target_index": 0,
461
+ "prediction_index": 0,
462
+ "probabilities": [
463
+ 0.9666830897331238,
464
+ 0.0034012277610599995,
465
+ 0.029622506350278854,
466
+ 0.0002932194038294256
467
+ ],
468
+ "elapsed_ms": 713.5235409950837
469
+ },
470
+ {
471
+ "id": "scienceqa/val/8378",
472
+ "target_index": 1,
473
+ "prediction_index": 1,
474
+ "probabilities": [
475
+ 0.0013747070915997028,
476
+ 0.9961742758750916,
477
+ 4.492511652642861e-05,
478
+ 0.002406216226518154
479
+ ],
480
+ "elapsed_ms": 737.4855829984881
481
+ },
482
+ {
483
+ "id": "scienceqa/val/20597",
484
+ "target_index": 0,
485
+ "prediction_index": 0,
486
+ "probabilities": [
487
+ 0.997296154499054,
488
+ 0.002703010104596615,
489
+ 1.2892381562323862e-07,
490
+ 5.3921453968541755e-08,
491
+ 7.135407713576569e-07
492
+ ],
493
+ "elapsed_ms": 749.1085410001688
494
+ },
495
+ {
496
+ "id": "scienceqa/val/20663",
497
+ "target_index": 2,
498
+ "prediction_index": 2,
499
+ "probabilities": [
500
+ 0.0019003677880391479,
501
+ 0.0003613665176089853,
502
+ 0.9974960684776306,
503
+ 0.00024219938495662063
504
+ ],
505
+ "elapsed_ms": 714.918542013038
506
+ },
507
+ {
508
+ "id": "scienceqa/val/8601",
509
+ "target_index": 0,
510
+ "prediction_index": 0,
511
+ "probabilities": [
512
+ 0.9890605211257935,
513
+ 0.0009218206396326423,
514
+ 0.0004352020041551441,
515
+ 0.0007956480840221047,
516
+ 0.008786870166659355
517
+ ],
518
+ "elapsed_ms": 809.6686659846455
519
+ },
520
+ {
521
+ "id": "scienceqa/val/15468",
522
+ "target_index": 0,
523
+ "prediction_index": 0,
524
+ "probabilities": [
525
+ 0.9999960660934448,
526
+ 1.3521396340365754e-06,
527
+ 5.3496968632771313e-08,
528
+ 4.779113851327565e-07,
529
+ 2.1499056401808048e-06
530
+ ],
531
+ "elapsed_ms": 745.8568339934573
532
+ },
533
+ {
534
+ "id": "scienceqa/val/10026",
535
+ "target_index": 1,
536
+ "prediction_index": 1,
537
+ "probabilities": [
538
+ 1.3849937658960698e-06,
539
+ 0.9994989633560181,
540
+ 0.0004951194860041142,
541
+ 4.56709494756069e-06
542
+ ],
543
+ "elapsed_ms": 742.6960830343887
544
+ },
545
+ {
546
+ "id": "scienceqa/val/626",
547
+ "target_index": 0,
548
+ "prediction_index": 0,
549
+ "probabilities": [
550
+ 0.9972666501998901,
551
+ 0.0027228447142988443,
552
+ 1.0538949936744757e-05
553
+ ],
554
+ "elapsed_ms": 837.4422079650685
555
+ },
556
+ {
557
+ "id": "scienceqa/val/8306",
558
+ "target_index": 2,
559
+ "prediction_index": 1,
560
+ "probabilities": [
561
+ 8.581038855481893e-06,
562
+ 0.9967631101608276,
563
+ 0.002022934379056096,
564
+ 0.0011565418681129813,
565
+ 4.877926767221652e-05
566
+ ],
567
+ "elapsed_ms": 718.9321659971029
568
+ },
569
+ {
570
+ "id": "scienceqa/val/11428",
571
+ "target_index": 1,
572
+ "prediction_index": 1,
573
+ "probabilities": [
574
+ 0.25946858525276184,
575
+ 0.6668545007705688,
576
+ 0.030808407813310623,
577
+ 0.04286855459213257
578
+ ],
579
+ "elapsed_ms": 725.4270830308087
580
+ },
581
+ {
582
+ "id": "scienceqa/val/4036",
583
+ "target_index": 1,
584
+ "prediction_index": 1,
585
+ "probabilities": [
586
+ 0.01569034904241562,
587
+ 0.9813077449798584,
588
+ 0.0019826041534543037,
589
+ 0.0010193256894126534
590
+ ],
591
+ "elapsed_ms": 918.4377079945989
592
+ },
593
+ {
594
+ "id": "scienceqa/val/21080",
595
+ "target_index": 1,
596
+ "prediction_index": 1,
597
+ "probabilities": [
598
+ 0.00036287258262746036,
599
+ 0.8422839045524597,
600
+ 0.15620771050453186,
601
+ 9.737018990563229e-05,
602
+ 0.0010480741038918495
603
+ ],
604
+ "elapsed_ms": 727.5516249937937
605
+ },
606
+ {
607
+ "id": "scienceqa/val/15237",
608
+ "target_index": 1,
609
+ "prediction_index": 1,
610
+ "probabilities": [
611
+ 0.00011872701725224033,
612
+ 0.9992451667785645,
613
+ 0.0004771235981024802,
614
+ 0.000158965282025747
615
+ ],
616
+ "elapsed_ms": 715.3530420036986
617
+ }
618
+ ]
619
+ }
benchmarks/scienceqa-50-224.json ADDED
@@ -0,0 +1,619 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "summary": {
3
+ "questions": 50,
4
+ "correct": 44,
5
+ "accuracy": 0.88,
6
+ "latency_ms": {
7
+ "median": 1050.1905410201289,
8
+ "p95": 1353.7280409946106,
9
+ "mean": 1018.8930649985559
10
+ },
11
+ "model": "third_party/OmniJev/models/Qwen3.5-4B-OmniJev-MLX-5bit",
12
+ "note": "Visual ScienceQA subset; not text-only JevBench."
13
+ },
14
+ "results": [
15
+ {
16
+ "id": "scienceqa/val/21023",
17
+ "target_index": 2,
18
+ "prediction_index": 3,
19
+ "probabilities": [
20
+ 9.572258022672031e-06,
21
+ 8.922968117985874e-05,
22
+ 0.011354859918355942,
23
+ 0.9875626564025879,
24
+ 0.000983729842118919
25
+ ],
26
+ "elapsed_ms": 1216.320250008721
27
+ },
28
+ {
29
+ "id": "scienceqa/val/7180",
30
+ "target_index": 2,
31
+ "prediction_index": 2,
32
+ "probabilities": [
33
+ 0.0029119839891791344,
34
+ 0.006107375491410494,
35
+ 0.9909207820892334,
36
+ 5.9882444475078955e-05
37
+ ],
38
+ "elapsed_ms": 1024.4643749902025
39
+ },
40
+ {
41
+ "id": "scienceqa/val/2642",
42
+ "target_index": 2,
43
+ "prediction_index": 2,
44
+ "probabilities": [
45
+ 1.4533699868479744e-05,
46
+ 0.0008359018247574568,
47
+ 0.9989796280860901,
48
+ 0.00016994107863865793
49
+ ],
50
+ "elapsed_ms": 801.7690839478746
51
+ },
52
+ {
53
+ "id": "scienceqa/val/16468",
54
+ "target_index": 0,
55
+ "prediction_index": 0,
56
+ "probabilities": [
57
+ 0.9368453621864319,
58
+ 0.06314510107040405,
59
+ 3.946696836010233e-07,
60
+ 1.953322907866095e-06,
61
+ 7.181197815953055e-06
62
+ ],
63
+ "elapsed_ms": 1021.7106660129502
64
+ },
65
+ {
66
+ "id": "scienceqa/val/19506",
67
+ "target_index": 1,
68
+ "prediction_index": 1,
69
+ "probabilities": [
70
+ 0.09320443868637085,
71
+ 0.3865593373775482,
72
+ 0.5202361941337585
73
+ ],
74
+ "elapsed_ms": 1179.1406670236029
75
+ },
76
+ {
77
+ "id": "scienceqa/val/8767",
78
+ "target_index": 1,
79
+ "prediction_index": 1,
80
+ "probabilities": [
81
+ 0.005915054120123386,
82
+ 0.9934005737304688,
83
+ 0.0006844155723229051
84
+ ],
85
+ "elapsed_ms": 656.6533750155941
86
+ },
87
+ {
88
+ "id": "scienceqa/val/16515",
89
+ "target_index": 2,
90
+ "prediction_index": 2,
91
+ "probabilities": [
92
+ 1.431024969633654e-07,
93
+ 1.834305263237468e-09,
94
+ 0.999997615814209,
95
+ 9.705598813525285e-07,
96
+ 1.2522122005975689e-06
97
+ ],
98
+ "elapsed_ms": 1056.747082970105
99
+ },
100
+ {
101
+ "id": "scienceqa/val/16938",
102
+ "target_index": 1,
103
+ "prediction_index": 0,
104
+ "probabilities": [
105
+ 0.7385404706001282,
106
+ 0.2605304718017578,
107
+ 0.0009290423477068543
108
+ ],
109
+ "elapsed_ms": 1102.3421249701641
110
+ },
111
+ {
112
+ "id": "scienceqa/val/13212",
113
+ "target_index": 0,
114
+ "prediction_index": 0,
115
+ "probabilities": [
116
+ 0.9983437061309814,
117
+ 8.884436101652682e-05,
118
+ 0.000598268467001617,
119
+ 0.0009691402083262801
120
+ ],
121
+ "elapsed_ms": 675.5916670081206
122
+ },
123
+ {
124
+ "id": "scienceqa/val/4539",
125
+ "target_index": 3,
126
+ "prediction_index": 1,
127
+ "probabilities": [
128
+ 0.26230472326278687,
129
+ 0.3358997404575348,
130
+ 0.115623340010643,
131
+ 0.2861471474170685,
132
+ 2.5058159735635854e-05
133
+ ],
134
+ "elapsed_ms": 1027.891166973859
135
+ },
136
+ {
137
+ "id": "scienceqa/val/11884",
138
+ "target_index": 1,
139
+ "prediction_index": 1,
140
+ "probabilities": [
141
+ 9.703077375888824e-05,
142
+ 0.9998834133148193,
143
+ 1.9517850887496024e-05
144
+ ],
145
+ "elapsed_ms": 1107.7883340185508
146
+ },
147
+ {
148
+ "id": "scienceqa/val/15622",
149
+ "target_index": 1,
150
+ "prediction_index": 1,
151
+ "probabilities": [
152
+ 1.4583752090402413e-06,
153
+ 0.9997345805168152,
154
+ 5.991348734823987e-05,
155
+ 0.00020402560767251998
156
+ ],
157
+ "elapsed_ms": 1318.7873339629732
158
+ },
159
+ {
160
+ "id": "scienceqa/val/17192",
161
+ "target_index": 3,
162
+ "prediction_index": 3,
163
+ "probabilities": [
164
+ 2.8217283443154884e-07,
165
+ 1.4603470788188133e-07,
166
+ 1.4119949298674328e-07,
167
+ 0.9999963045120239,
168
+ 3.146950348309474e-06
169
+ ],
170
+ "elapsed_ms": 1033.0449999892153
171
+ },
172
+ {
173
+ "id": "scienceqa/val/2461",
174
+ "target_index": 2,
175
+ "prediction_index": 2,
176
+ "probabilities": [
177
+ 9.025831968756393e-05,
178
+ 2.9825587262166664e-06,
179
+ 0.999823272228241,
180
+ 8.357201295439154e-05
181
+ ],
182
+ "elapsed_ms": 824.592458026018
183
+ },
184
+ {
185
+ "id": "scienceqa/val/8688",
186
+ "target_index": 0,
187
+ "prediction_index": 0,
188
+ "probabilities": [
189
+ 0.9999678134918213,
190
+ 5.3547882998827845e-06,
191
+ 2.685382787603885e-05
192
+ ],
193
+ "elapsed_ms": 859.0977909625508
194
+ },
195
+ {
196
+ "id": "scienceqa/val/15419",
197
+ "target_index": 2,
198
+ "prediction_index": 2,
199
+ "probabilities": [
200
+ 7.925441991574189e-08,
201
+ 2.789672919334407e-07,
202
+ 0.9999805688858032,
203
+ 3.70468811183855e-08,
204
+ 1.913079722726252e-05
205
+ ],
206
+ "elapsed_ms": 1026.9342919928022
207
+ },
208
+ {
209
+ "id": "scienceqa/val/18512",
210
+ "target_index": 1,
211
+ "prediction_index": 1,
212
+ "probabilities": [
213
+ 3.031034534473065e-09,
214
+ 0.9999986886978149,
215
+ 1.2731197784887627e-06
216
+ ],
217
+ "elapsed_ms": 714.639707992319
218
+ },
219
+ {
220
+ "id": "scienceqa/val/921",
221
+ "target_index": 1,
222
+ "prediction_index": 1,
223
+ "probabilities": [
224
+ 0.0015609971014782786,
225
+ 0.994932234287262,
226
+ 0.003506765468046069
227
+ ],
228
+ "elapsed_ms": 714.470416016411
229
+ },
230
+ {
231
+ "id": "scienceqa/val/17574",
232
+ "target_index": 1,
233
+ "prediction_index": 1,
234
+ "probabilities": [
235
+ 4.704803723143414e-05,
236
+ 0.9971519708633423,
237
+ 4.187240483588539e-05,
238
+ 0.002759092953056097
239
+ ],
240
+ "elapsed_ms": 1056.6815420170315
241
+ },
242
+ {
243
+ "id": "scienceqa/val/4517",
244
+ "target_index": 1,
245
+ "prediction_index": 0,
246
+ "probabilities": [
247
+ 0.817062258720398,
248
+ 0.1827545017004013,
249
+ 0.00018327795260120183
250
+ ],
251
+ "elapsed_ms": 1234.0599590097554
252
+ },
253
+ {
254
+ "id": "scienceqa/val/12959",
255
+ "target_index": 0,
256
+ "prediction_index": 0,
257
+ "probabilities": [
258
+ 0.9998112320899963,
259
+ 5.039972165832296e-05,
260
+ 1.4609129266318632e-06,
261
+ 0.00013698486145585775
262
+ ],
263
+ "elapsed_ms": 1353.7280409946106
264
+ },
265
+ {
266
+ "id": "scienceqa/val/4018",
267
+ "target_index": 3,
268
+ "prediction_index": 3,
269
+ "probabilities": [
270
+ 0.0001855503796832636,
271
+ 9.175106970360503e-05,
272
+ 0.0003109597892034799,
273
+ 0.9957041144371033,
274
+ 0.0037075893487781286
275
+ ],
276
+ "elapsed_ms": 1039.2040419974364
277
+ },
278
+ {
279
+ "id": "scienceqa/val/17681",
280
+ "target_index": 2,
281
+ "prediction_index": 2,
282
+ "probabilities": [
283
+ 4.3628803347850464e-10,
284
+ 3.0636066128408856e-08,
285
+ 0.9999998807907104,
286
+ 1.403442695391277e-07
287
+ ],
288
+ "elapsed_ms": 738.9204169739969
289
+ },
290
+ {
291
+ "id": "scienceqa/val/9964",
292
+ "target_index": 2,
293
+ "prediction_index": 2,
294
+ "probabilities": [
295
+ 1.625367258384358e-05,
296
+ 7.471736807929119e-06,
297
+ 0.9999535083770752,
298
+ 2.2715945306117646e-05
299
+ ],
300
+ "elapsed_ms": 1065.4092500335537
301
+ },
302
+ {
303
+ "id": "scienceqa/val/340",
304
+ "target_index": 1,
305
+ "prediction_index": 1,
306
+ "probabilities": [
307
+ 0.23235492408275604,
308
+ 0.7047974467277527,
309
+ 0.0010436835000291467,
310
+ 0.0618039146065712
311
+ ],
312
+ "elapsed_ms": 1027.7538750087842
313
+ },
314
+ {
315
+ "id": "scienceqa/val/20723",
316
+ "target_index": 0,
317
+ "prediction_index": 0,
318
+ "probabilities": [
319
+ 0.9699394702911377,
320
+ 0.02400338463485241,
321
+ 0.006057215388864279
322
+ ],
323
+ "elapsed_ms": 1119.317915989086
324
+ },
325
+ {
326
+ "id": "scienceqa/val/13835",
327
+ "target_index": 0,
328
+ "prediction_index": 0,
329
+ "probabilities": [
330
+ 0.9985985159873962,
331
+ 0.00014829420251771808,
332
+ 7.677712710574269e-05,
333
+ 0.0011763935908675194
334
+ ],
335
+ "elapsed_ms": 662.2005829703994
336
+ },
337
+ {
338
+ "id": "scienceqa/val/8404",
339
+ "target_index": 3,
340
+ "prediction_index": 3,
341
+ "probabilities": [
342
+ 2.1427009414765052e-05,
343
+ 1.6831480024848133e-05,
344
+ 5.751501157646999e-05,
345
+ 0.9970983266830444,
346
+ 0.0028059149626642466
347
+ ],
348
+ "elapsed_ms": 1038.3789160405286
349
+ },
350
+ {
351
+ "id": "scienceqa/val/326",
352
+ "target_index": 1,
353
+ "prediction_index": 1,
354
+ "probabilities": [
355
+ 0.002556850202381611,
356
+ 0.9972189664840698,
357
+ 0.00022422110487241298
358
+ ],
359
+ "elapsed_ms": 1279.2820409522392
360
+ },
361
+ {
362
+ "id": "scienceqa/val/7684",
363
+ "target_index": 2,
364
+ "prediction_index": 2,
365
+ "probabilities": [
366
+ 0.0012439613929018378,
367
+ 0.0003342817071825266,
368
+ 0.995692789554596,
369
+ 0.002728895051404834
370
+ ],
371
+ "elapsed_ms": 1391.0568749997765
372
+ },
373
+ {
374
+ "id": "scienceqa/val/6621",
375
+ "target_index": 1,
376
+ "prediction_index": 1,
377
+ "probabilities": [
378
+ 5.970364647112092e-09,
379
+ 0.999998927116394,
380
+ 1.8963916659231472e-08,
381
+ 6.708435762448062e-07,
382
+ 3.7174092426539573e-07
383
+ ],
384
+ "elapsed_ms": 1050.1905410201289
385
+ },
386
+ {
387
+ "id": "scienceqa/val/11466",
388
+ "target_index": 0,
389
+ "prediction_index": 2,
390
+ "probabilities": [
391
+ 0.3485657870769501,
392
+ 0.08763457834720612,
393
+ 0.5546107888221741,
394
+ 0.009188840165734291
395
+ ],
396
+ "elapsed_ms": 1019.3432919913903
397
+ },
398
+ {
399
+ "id": "scienceqa/val/4791",
400
+ "target_index": 0,
401
+ "prediction_index": 1,
402
+ "probabilities": [
403
+ 0.4698958396911621,
404
+ 0.5242437720298767,
405
+ 0.005860346369445324
406
+ ],
407
+ "elapsed_ms": 752.7294590254314
408
+ },
409
+ {
410
+ "id": "scienceqa/val/4550",
411
+ "target_index": 0,
412
+ "prediction_index": 0,
413
+ "probabilities": [
414
+ 0.9999986886978149,
415
+ 6.811756634306221e-07,
416
+ 8.064888135095316e-08,
417
+ 1.194044196850541e-09,
418
+ 4.1733542843758187e-07
419
+ ],
420
+ "elapsed_ms": 1049.7832499677315
421
+ },
422
+ {
423
+ "id": "scienceqa/val/8558",
424
+ "target_index": 0,
425
+ "prediction_index": 0,
426
+ "probabilities": [
427
+ 0.8947974443435669,
428
+ 0.04916587099432945,
429
+ 0.05512939393520355,
430
+ 0.0009072012035176158
431
+ ],
432
+ "elapsed_ms": 1072.1199999679811
433
+ },
434
+ {
435
+ "id": "scienceqa/val/19945",
436
+ "target_index": 0,
437
+ "prediction_index": 0,
438
+ "probabilities": [
439
+ 0.7528671622276306,
440
+ 0.24187956750392914,
441
+ 0.005253252573311329
442
+ ],
443
+ "elapsed_ms": 838.6542919906788
444
+ },
445
+ {
446
+ "id": "scienceqa/val/8871",
447
+ "target_index": 0,
448
+ "prediction_index": 0,
449
+ "probabilities": [
450
+ 0.9999986886978149,
451
+ 7.551004159722652e-07,
452
+ 8.145114094304517e-08,
453
+ 7.321462991427552e-09,
454
+ 4.373882518393657e-07
455
+ ],
456
+ "elapsed_ms": 1065.9168339916505
457
+ },
458
+ {
459
+ "id": "scienceqa/val/4884",
460
+ "target_index": 0,
461
+ "prediction_index": 0,
462
+ "probabilities": [
463
+ 0.9833201766014099,
464
+ 0.0013428564416244626,
465
+ 0.015262079425156116,
466
+ 7.485473179258406e-05
467
+ ],
468
+ "elapsed_ms": 1076.3937499723397
469
+ },
470
+ {
471
+ "id": "scienceqa/val/8378",
472
+ "target_index": 1,
473
+ "prediction_index": 1,
474
+ "probabilities": [
475
+ 0.00018541481404099613,
476
+ 0.9995972514152527,
477
+ 1.6776668417151086e-05,
478
+ 0.0002005332353292033
479
+ ],
480
+ "elapsed_ms": 878.3530420041643
481
+ },
482
+ {
483
+ "id": "scienceqa/val/20597",
484
+ "target_index": 0,
485
+ "prediction_index": 0,
486
+ "probabilities": [
487
+ 0.9999960660934448,
488
+ 3.515009439070127e-06,
489
+ 6.72070328278096e-08,
490
+ 4.936427799862031e-08,
491
+ 3.3825261880338076e-07
492
+ ],
493
+ "elapsed_ms": 1068.625667016022
494
+ },
495
+ {
496
+ "id": "scienceqa/val/20663",
497
+ "target_index": 2,
498
+ "prediction_index": 2,
499
+ "probabilities": [
500
+ 0.006027692463248968,
501
+ 0.00041820149635896087,
502
+ 0.993385374546051,
503
+ 0.00016875665460247546
504
+ ],
505
+ "elapsed_ms": 1086.184083018452
506
+ },
507
+ {
508
+ "id": "scienceqa/val/8601",
509
+ "target_index": 0,
510
+ "prediction_index": 0,
511
+ "probabilities": [
512
+ 0.9890605211257935,
513
+ 0.0009218206396326423,
514
+ 0.0004352020041551441,
515
+ 0.0007956480840221047,
516
+ 0.008786870166659355
517
+ ],
518
+ "elapsed_ms": 803.3093330450356
519
+ },
520
+ {
521
+ "id": "scienceqa/val/15468",
522
+ "target_index": 0,
523
+ "prediction_index": 0,
524
+ "probabilities": [
525
+ 0.999998927116394,
526
+ 4.696783548752137e-07,
527
+ 1.6910020050886487e-08,
528
+ 8.057025269181395e-08,
529
+ 5.363776836020406e-07
530
+ ],
531
+ "elapsed_ms": 1068.2248329976574
532
+ },
533
+ {
534
+ "id": "scienceqa/val/10026",
535
+ "target_index": 1,
536
+ "prediction_index": 1,
537
+ "probabilities": [
538
+ 5.717474209632201e-07,
539
+ 0.9995086193084717,
540
+ 0.00048735918244346976,
541
+ 3.4935785606649006e-06
542
+ ],
543
+ "elapsed_ms": 1082.4098750017583
544
+ },
545
+ {
546
+ "id": "scienceqa/val/626",
547
+ "target_index": 0,
548
+ "prediction_index": 0,
549
+ "probabilities": [
550
+ 0.9972666501998901,
551
+ 0.0027228447142988443,
552
+ 1.0538949936744757e-05
553
+ ],
554
+ "elapsed_ms": 842.4672919791192
555
+ },
556
+ {
557
+ "id": "scienceqa/val/8306",
558
+ "target_index": 2,
559
+ "prediction_index": 2,
560
+ "probabilities": [
561
+ 0.003358687274158001,
562
+ 0.00698996102437377,
563
+ 0.951853334903717,
564
+ 0.006501566618680954,
565
+ 0.03129644691944122
566
+ ],
567
+ "elapsed_ms": 1093.388750043232
568
+ },
569
+ {
570
+ "id": "scienceqa/val/11428",
571
+ "target_index": 1,
572
+ "prediction_index": 1,
573
+ "probabilities": [
574
+ 0.2032264918088913,
575
+ 0.716314971446991,
576
+ 0.025267310440540314,
577
+ 0.05519119277596474
578
+ ],
579
+ "elapsed_ms": 1104.4623340130784
580
+ },
581
+ {
582
+ "id": "scienceqa/val/4036",
583
+ "target_index": 1,
584
+ "prediction_index": 1,
585
+ "probabilities": [
586
+ 0.0006258749053813517,
587
+ 0.9989481568336487,
588
+ 0.00010744511382654309,
589
+ 0.0003185884852427989
590
+ ],
591
+ "elapsed_ms": 1434.7477499977686
592
+ },
593
+ {
594
+ "id": "scienceqa/val/21080",
595
+ "target_index": 1,
596
+ "prediction_index": 1,
597
+ "probabilities": [
598
+ 6.803419978496095e-07,
599
+ 0.9944728016853333,
600
+ 0.005440711509436369,
601
+ 1.4968701407269691e-06,
602
+ 8.4117149526719e-05
603
+ ],
604
+ "elapsed_ms": 1093.0374580202624
605
+ },
606
+ {
607
+ "id": "scienceqa/val/15237",
608
+ "target_index": 1,
609
+ "prediction_index": 1,
610
+ "probabilities": [
611
+ 3.9620841562282294e-05,
612
+ 0.9990529417991638,
613
+ 0.0008513267966918647,
614
+ 5.614504334516823e-05
615
+ ],
616
+ "elapsed_ms": 1096.3321659946814
617
+ }
618
+ ]
619
+ }
conversion.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_model": "tinnel123/OmniJev",
3
+ "source_revision": "v1.1",
4
+ "source_release": "OmniJev-4B-ckpt",
5
+ "backbone": "Qwen/Qwen3.5-4B",
6
+ "operation": "merge official LoRA adapter into the backbone in bfloat16, then convert the fused backbone to MLX affine quantization",
7
+ "bits": 5,
8
+ "group_size": 64,
9
+ "quantization_mode": "affine",
10
+ "vision_precision": "bfloat16",
11
+ "decision_head": "official head.pt exported to decision_head/head.npz",
12
+ "decision_head_precision": "float32",
13
+ "new_training": false,
14
+ "local_validation": {
15
+ "benchmark": "ScienceQA visual subset",
16
+ "questions": 50,
17
+ "max_pixels": 87808,
18
+ "correct": 44,
19
+ "accuracy": 0.88,
20
+ "warm_median_ms": 737.4855829984881,
21
+ "warm_p95_ms": 1012.7517079818062,
22
+ "hardware": "Mac mini M4, 16 GB unified memory"
23
+ }
24
+ }
decision_head/head.npz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4de95c6c6efa73243af8b220003ebda14e252892b6273fa25f6dec362e5f7b42
3
+ size 29417820
decision_head/head_meta.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"norm": "softmax", "lm_feats": true, "ordinal": true, "packed_train": true, "rlcd": false, "branch": true, "base_model": "Qwen3.5-4B", "lora_targets": ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj", "in_proj_qkv", "in_proj_z", "out_proj"], "temperatures": {"noul": 1.1991, "choice": 1.1199, "score": 1.1909}, "calibration": {"n_dev": 7767, "n_test": 17754, "raw": {"noul": {"n": 5566, "acc": 0.8917, "ece": 0.0235, "brier": 0.1545, "nll": 0.2524, "e_aurc": 0.0171}, "choice": {"n": 9226, "acc": 0.5633, "ece": 0.022, "brier": 0.5155, "nll": 1.2547, "e_aurc": 0.0557}, "score": {"n": 2962, "acc": 0.6691, "ece": 0.0524, "brier": 0.426, "nll": 0.7504, "e_aurc": 0.0842}}, "calibrated": {"noul": {"n": 5566, "acc": 0.8917, "ece": 0.01, "brier": 0.153, "nll": 0.2484, "e_aurc": 0.0171}, "choice": {"n": 9226, "acc": 0.5633, "ece": 0.0144, "brier": 0.5153, "nll": 1.2517, "e_aurc": 0.0557}, "score": {"n": 2962, "acc": 0.6691, "ece": 0.0342, "brier": 0.4221, "nll": 0.7445, "e_aurc": 0.0837}}}, "biases": {"noul": 0.05310856608843584}}
head_provenance.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_file": "tinnel123/OmniJev@v1.1:head.pt",
3
+ "source_sha256": "7b801a1901040e70559deb74eadb11709540ff65ef926213ecf881e4f4070320",
4
+ "export_file": "decision_head/head.npz",
5
+ "export_script": "training/export_omnijev_head.py",
6
+ "note": "The decision head was not retrained for this repository; it was converted from the released official checkpoint."
7
+ }
omni_mlx/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """MLX inference wrapper for the OmniJev 5-bit decision model."""
omni_mlx/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (248 Bytes). View file
 
omni_mlx/__pycache__/classifier.cpython-310.pyc ADDED
Binary file (12.1 kB). View file
 
omni_mlx/__pycache__/classifier.cpython-313.pyc ADDED
Binary file (20.6 kB). View file
 
omni_mlx/classifier.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Run the fused Qwen3.5/OmniJev 5-bit model with its decision head."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import statistics
7
+ import time
8
+ from pathlib import Path
9
+
10
+ import mlx.core as mx
11
+ import numpy as np
12
+ from PIL import Image
13
+
14
+
15
+ def _load_runtime(model_path: Path):
16
+ from mlx_vlm import load
17
+
18
+ mx.set_cache_limit(256 * 1024**2)
19
+ model, processor = load(str(model_path))
20
+ model.set_dtype(mx.float32)
21
+ if model.config.model_type != "qwen3_5":
22
+ raise ValueError(f"Expected qwen3_5 model, got {model.config.model_type}")
23
+ return Qwen35Adapter(model, processor)
24
+
25
+
26
+ class Qwen35Adapter:
27
+ def __init__(self, model, processor):
28
+ self.model = model
29
+ self.processor = processor
30
+ self.tokenizer = processor.tokenizer
31
+
32
+ def execution_context(self):
33
+ from mlx_vlm.generate.common import wired_limit
34
+
35
+ return wired_limit(self.model)
36
+
37
+ def prepare(self, prompt: str, image: Image.Image):
38
+ from mlx_vlm.utils import prepare_inputs
39
+
40
+ inputs = prepare_inputs(self.processor, images=[image], prompts=prompt)
41
+ if inputs["input_ids"].shape[-1] > 6000:
42
+ raise ValueError("image and prompt exceed 6000 input tokens")
43
+ return inputs
44
+
45
+ def prefill(self, inputs):
46
+ ids = inputs["input_ids"]
47
+ features = self.model.get_input_embeddings(
48
+ ids,
49
+ pixel_values=inputs.get("pixel_values"),
50
+ image_grid_thw=inputs.get("image_grid_thw"),
51
+ mask=inputs.get("attention_mask"),
52
+ )
53
+ mx.eval(features.inputs_embeds, features.position_ids)
54
+ cache = self.model.language_model.make_cache()
55
+ out = self.model.language_model(
56
+ ids,
57
+ inputs_embeds=features.inputs_embeds,
58
+ cache=cache,
59
+ position_ids=features.position_ids,
60
+ rope_deltas=features.rope_deltas,
61
+ skip_logits=True,
62
+ return_hidden=True,
63
+ )
64
+ mx.eval(out.hidden_states[-1], *[v for c in cache for v in c.state if v is not None])
65
+ return cache, int(features.position_ids.max().item()) + 1
66
+
67
+ def fork(self, cache, count):
68
+ from mlx_vlm.models.cache import ArraysCache, KVCache
69
+
70
+ result = []
71
+ for entry in cache:
72
+ if type(entry) not in (ArraysCache, KVCache):
73
+ raise TypeError(f"unsupported cache: {type(entry).__name__}")
74
+ state = [None if x is None else mx.repeat(x, count, axis=0) for x in entry.state]
75
+ result.append(type(entry).from_state(state, entry.meta_state))
76
+ mx.eval(*[v for c in result for v in c.state if v is not None])
77
+ return result
78
+
79
+ def suffix_hidden(self, cache, next_position, rows, picks):
80
+ branches = self.fork(cache, len(rows))
81
+ length = max(map(len, rows))
82
+ pad = self.tokenizer.pad_token_id or self.tokenizer.eos_token_id
83
+ ids = mx.array([row + [pad] * (length - len(row)) for row in rows])
84
+ positions = mx.broadcast_to(
85
+ (mx.arange(length) + next_position)[None, None, :],
86
+ (3, len(rows), length),
87
+ )
88
+ out = self.model.language_model(
89
+ ids,
90
+ cache=branches,
91
+ position_ids=positions,
92
+ skip_logits=True,
93
+ return_hidden=True,
94
+ )
95
+ hidden = out.hidden_states[-1]
96
+ return [hidden[i, mx.array(row)] for i, row in enumerate(picks)]
97
+
98
+
99
+ class OmniHead:
100
+ def __init__(self, path: Path):
101
+ with np.load(path) as values:
102
+ self.weights = {key: value for key, value in values.items()}
103
+ metadata_path = path.with_name("head_meta.json")
104
+ metadata = json.loads(metadata_path.read_text()) if metadata_path.exists() else {}
105
+ self.choice_temperature = float(metadata.get("temperatures", {}).get("choice", 1.0))
106
+
107
+ @staticmethod
108
+ def _linear(x, weight, bias):
109
+ return x @ mx.array(weight.T) + mx.array(bias)
110
+
111
+ @staticmethod
112
+ def _gelu(x):
113
+ return 0.5 * x * (1 + mx.tanh(0.7978845608 * (x + 0.044715 * x * x * x)))
114
+
115
+ def logits(self, option_hidden, question_hidden, features):
116
+ w = self.weights
117
+ option = self._linear(
118
+ self._gelu(self._linear(option_hidden, w["opt__0__weight"], w["opt__0__bias"])),
119
+ w["opt__2__weight"], w["opt__2__bias"],
120
+ )
121
+ question = self._linear(
122
+ self._gelu(self._linear(question_hidden, w["que__0__weight"], w["que__0__bias"])),
123
+ w["que__2__weight"], w["que__2__bias"],
124
+ )
125
+ gate = mx.tanh(question)
126
+ fused = option * gate[None, :] + self._linear(
127
+ features, w["feat__weight"], w["feat__bias"]
128
+ )
129
+ tau = mx.exp(mx.array(w["log_tau"])[1])
130
+ score = self._linear(fused, w["score__weight"], w["score__bias"]).squeeze(-1)
131
+ score = score + self._linear(
132
+ features, w["feat_lin__weight"], w["feat_lin__bias"]
133
+ ).squeeze(-1)
134
+ score = score / tau
135
+ abstain = self._linear(
136
+ gate, w["abstain__weight"], w["abstain__bias"]
137
+ ).squeeze(-1) / tau
138
+ return mx.concatenate([score, mx.reshape(abstain, (1,))])
139
+
140
+
141
+ def _marker_positions(row, opening, closing):
142
+ def find(pattern):
143
+ width = len(pattern)
144
+ return [i for i in range(len(row) - width + 1) if row[i : i + width] == pattern]
145
+
146
+ opens, closes = find(opening), find(closing)
147
+ if len(opens) != 1 or len(closes) != 1:
148
+ raise ValueError(f"option marker count mismatch: opens={opens}, closes={closes}")
149
+ option_start, close_start = opens[0], closes[0]
150
+ close_end = close_start + len(closing) - 1
151
+ inner = list(range(option_start + len(opening), close_start))
152
+ return option_start, close_end, inner
153
+
154
+
155
+ def predict_image(adapter, head, image: Image.Image, question: str, options: list[str]):
156
+ if not 2 <= len(options) <= 256 or len(set(options)) != len(options):
157
+ raise ValueError("supply 2–256 distinct options")
158
+ started = time.perf_counter()
159
+ tokenizer = adapter.tokenizer
160
+ opening = tokenizer("<|opt|>", add_special_tokens=False)["input_ids"]
161
+ closing = tokenizer("<|/opt|>", add_special_tokens=False)["input_ids"]
162
+ prompt = adapter.processor.apply_chat_template(
163
+ [{"role": "user", "content": [{"type": "image"}, {"type": "text", "text": question}]}],
164
+ tokenize=False,
165
+ add_generation_prompt=True,
166
+ )
167
+ full_prompt = prompt + "".join(f"<|opt|>{option}<|/opt|>" for option in options)
168
+ inputs = adapter.prepare(full_prompt, image)
169
+ full_ids = np.asarray(inputs["input_ids"])[0].tolist()
170
+ open_at = [
171
+ i for i in range(len(full_ids) - len(opening) + 1)
172
+ if full_ids[i : i + len(opening)] == opening
173
+ ]
174
+ if len(open_at) != len(options):
175
+ raise ValueError(f"expanded option markers not found: {open_at}")
176
+ prefix_end = open_at[0]
177
+ prefix = dict(inputs)
178
+ prefix["input_ids"] = inputs["input_ids"][:, :prefix_end]
179
+ prefix["attention_mask"] = mx.ones_like(prefix["input_ids"])
180
+ cache, next_position = adapter.prefill(prefix)
181
+
182
+ all_closes = [
183
+ i for i in range(len(full_ids) - len(closing) + 1)
184
+ if full_ids[i : i + len(closing)] == closing
185
+ ]
186
+ rows, picks, option_inner = [], [], []
187
+ for index, option_start in enumerate(open_at):
188
+ close_start = all_closes[index]
189
+ close_end = close_start + len(closing) - 1
190
+ row = full_ids[prefix_end:open_at[0]] + full_ids[option_start : close_end + 1]
191
+ marker_start, close_pos, inner = _marker_positions(row, opening, closing)
192
+ rows.append(row)
193
+ picks.append([close_pos, max(0, marker_start - 1)] + [position - 1 for position in inner])
194
+ option_inner.append(inner)
195
+
196
+ hidden_rows = adapter.suffix_hidden(cache, next_position, rows, picks)
197
+ all_hidden = mx.concatenate(hidden_rows, axis=0)
198
+ language_model = adapter.model.language_model
199
+ logits = (
200
+ language_model.model.embed_tokens.as_linear(all_hidden)
201
+ if language_model.args.tie_word_embeddings
202
+ else language_model.lm_head(all_hidden)
203
+ ).astype(mx.float32)
204
+ scored, offset = [], 0
205
+ for row_tokens, row_hidden, inner in zip(rows, hidden_rows, option_inner):
206
+ count = len(inner)
207
+ token_logits = logits[offset + 2 : offset + 2 + count]
208
+ targets = mx.array([row_tokens[position] for position in inner])
209
+ log_probs = token_logits - mx.logsumexp(token_logits, axis=-1, keepdims=True)
210
+ values = log_probs[mx.arange(count), targets] if count else mx.array([])
211
+ scored.append((row_hidden[0], row_hidden[1], values, count))
212
+ offset += len(row_hidden)
213
+ sums = mx.array([float(mx.sum(row[2]).item()) for row in scored])
214
+ counts = mx.array([row[3] for row in scored])
215
+ first = mx.array([float((row[2][0] if row[3] else 0).item()) for row in scored])
216
+ normalized = sums - mx.logsumexp(sums)
217
+ features = mx.stack(
218
+ [sums / 10, sums / mx.maximum(counts, 1), counts / 10, normalized, first, mx.ones_like(sums)],
219
+ axis=1,
220
+ )
221
+ option_hidden = mx.stack([row[0] for row in scored]).astype(mx.float32)
222
+ question_hidden = scored[0][1].astype(mx.float32)
223
+ scores = head.logits(option_hidden, question_hidden, features)
224
+ probabilities = mx.softmax(scores / head.choice_temperature)
225
+ mx.eval(probabilities)
226
+ values = probabilities.tolist()
227
+ choice_index = int(mx.argmax(probabilities[:-1]).item())
228
+ return {
229
+ "prediction": options[choice_index],
230
+ "prediction_index": choice_index,
231
+ "probabilities": values[:-1],
232
+ "abstain_probability": values[-1],
233
+ "elapsed_ms": (time.perf_counter() - started) * 1000,
234
+ "quantization_bits": 5,
235
+ }
236
+
237
+
238
+ def main():
239
+ parser = argparse.ArgumentParser(description=__doc__)
240
+ parser.add_argument("--model", type=Path, default=Path("."))
241
+ parser.add_argument("--head", type=Path, default=Path("decision_head/head.npz"))
242
+ parser.add_argument("--image", type=Path, required=True)
243
+ parser.add_argument("--state", default="")
244
+ parser.add_argument("--question", required=True)
245
+ parser.add_argument("--options", nargs="+", required=True)
246
+ parser.add_argument("--max-pixels", type=int, default=87808)
247
+ parser.add_argument("--repeat", type=int, default=1)
248
+ args = parser.parse_args()
249
+ if args.repeat < 1:
250
+ parser.error("repeat must be positive")
251
+ model_path = args.model.resolve()
252
+ head_path = args.head if args.head.is_absolute() else model_path / args.head
253
+ adapter = _load_runtime(model_path)
254
+ adapter.processor.image_processor.max_pixels = args.max_pixels
255
+ head = OmniHead(head_path)
256
+ with Image.open(args.image) as opened:
257
+ image = opened.convert("RGB")
258
+ question = args.question if not args.state else f"{args.question}\nContext: {args.state}"
259
+ results = []
260
+ with adapter.execution_context():
261
+ for _ in range(args.repeat):
262
+ results.append(predict_image(adapter, head, image, question, args.options))
263
+ output = {"model": str(model_path), "requests": results}
264
+ if len(results) > 1:
265
+ output["warm_median_ms"] = statistics.median(result["elapsed_ms"] for result in results[1:])
266
+ print(json.dumps(output, ensure_ascii=False, indent=2))
267
+
268
+
269
+ if __name__ == "__main__":
270
+ main()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ mlx==0.32.2
2
+ mlx-vlm==0.7.1
3
+ numpy>=2.0
4
+ Pillow>=10.0