lukbit commited on
Commit
1681a40
·
verified ·
1 Parent(s): 4abb5e3

Add V11 model card and updated Python image API examples

Browse files
Files changed (1) hide show
  1. README.md +228 -0
README.md ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ library_name: devision
5
+ pipeline_tag: visual-question-answering
6
+ base_model:
7
+ - convaiinnovations/laya
8
+ - google/siglip2-base-patch16-256
9
+ tags:
10
+ - devision
11
+ - system-one
12
+ - calibrated-decisions
13
+ - rlcd
14
+ - vision
15
+ - jev
16
+ ---
17
+
18
+ # deVision V11
19
+
20
+ **Image + typed questions → structured answers and calibrated probabilities.** deVision is a non-autoregressive visual decision model built from Laya's ModernBERT-large decision model and a SigLIP2 vision encoder. It scores the supplied options without generating text. Multiple questions about one image share a single image encoding.
21
+
22
+ This card describes **V11 (`v11-v9b-recovery`)**, selected by the project owner on October 6, 2026. It supports English, one image per request, yes/no decisions (`noul`) and multiple-choice decisions (`choice`).
23
+
24
+ **Repository status, October 6, 2026:** this repository currently contains the model card; the V11 weights and configuration files have not yet been uploaded. Loading `lukbit/devision` will work after those files are added. With a local checkout and checkpoint, use `runs/v11-v9b-recovery/stage2` instead.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install "devision @ git+https://github.com/byebyebruce/devision"
30
+ ```
31
+
32
+ Python 3.11 or newer is required. For HTTP serving and the browser demo, install `devision[serve]` instead. If the model repository is private, authenticate with `hf auth login` using an account with access.
33
+
34
+ The Python examples below require the new `image=` API (code commit `f34e81a` or later). As of October 6, the GitHub default branch has not yet received this change. Until it does, install from an updated local deVision checkout with `pip install .`; installing from GitHub currently provides the legacy `state` image-part API.
35
+
36
+ ## Python quickstart
37
+
38
+ The following Hub example applies once the weights are uploaded:
39
+
40
+ ```python
41
+ import devision
42
+
43
+ model = devision.load("lukbit/devision", device="cpu")
44
+ result = model.predict(
45
+ image="photo.jpg", # replace with your image path or an HTTP(S) image URL
46
+ state="", # required; empty when there is no additional context
47
+ questions={
48
+ "has_fork": {
49
+ "type": "noul",
50
+ "instructions": "Is there a fork in the image?",
51
+ },
52
+ "room": {
53
+ "type": "choice",
54
+ "instructions": "Which room is this?",
55
+ "criteria": {"kitchen": None, "bathroom": None, "bedroom": None},
56
+ },
57
+ },
58
+ )
59
+ print(result["answers"]["has_fork"]["noul"]) # probability of yes
60
+ print(result["answers"]["room"]["choice"]) # selected option
61
+ print(result["answers"]["room"]["probabilities"]) # probability for each option
62
+ ```
63
+
64
+ `model.decide(...)` accepts the same arguments. The default device is `auto` (CUDA, then MPS, then CPU); pass `device="cpu"`, `"mps"` or `"cuda"` to choose explicitly.
65
+
66
+ ### Image input
67
+
68
+ Use the separate Python `image=` argument. It automatically accepts:
69
+
70
+ | Input | Example |
71
+ |---|---|
72
+ | HTTP(S) URL | `image="https://example.com/photo.jpg"` — replace with a real image URL |
73
+ | Local path | `image="photo.jpg"` or `image=Path("photo.jpg")` with `from pathlib import Path` |
74
+ | Base64 data URI | `image="data:image/png;base64,..."` — supply the complete encoding |
75
+ | Plain Base64 | `image=base64_string` |
76
+ | Encoded image bytes | `image=image_bytes` — PNG/JPEG file contents, for example |
77
+ | PIL image | `image=pil_image` |
78
+
79
+ ### Context and notes
80
+
81
+ `state` is required and accepts a string, object or array. For image-only questions, pass `state=""`; do not omit it or pass `None`. To supply additional context:
82
+
83
+ ```python
84
+ result = model.decide(
85
+ image="photo.jpg",
86
+ state={"note": "The customer says this item arrived damaged."},
87
+ questions={
88
+ "damaged": {
89
+ "type": "noul",
90
+ "instructions": "Is the item visibly damaged?",
91
+ },
92
+ },
93
+ )
94
+ ```
95
+
96
+ `note` is an ordinary context field, not a special parameter. An `image` key inside an object state also stays text: `state={"image": "photo.jpg"}` does not load the file. The legacy `state=[{"type": "image", "url": "https://..."}]` form remains supported, but do not combine it with `image=`.
97
+
98
+ ### Output
99
+
100
+ - `noul` is the probability that the statement holds, between 0 and 1.
101
+ - `choice` is the highest-probability option; `probabilities` contains every option and sums to 1.
102
+ - Choice `confidence` follows Jev: `(n * p_max - 1) / (n - 1)`.
103
+ - Invalid request formats or image encodings raise `devision.InvalidRequest`. Local file reads can also raise `OSError`.
104
+
105
+ ## HTTP API and browser demo
106
+
107
+ Once the weights are uploaded:
108
+
109
+ ```bash
110
+ pip install "devision[serve] @ git+https://github.com/byebyebruce/devision"
111
+ devision-serve --checkpoint lukbit/devision --device cpu --port 8000
112
+ ```
113
+
114
+ Open `http://127.0.0.1:8000` for the demo. To use a local V11 checkpoint now, replace `lukbit/devision` with `runs/v11-v9b-recovery/stage2`.
115
+
116
+ HTTP keeps the Jev-compatible `/v1/systemone` format. The following example uploads a local image as Base64:
117
+
118
+ ```python
119
+ import base64
120
+ import json
121
+ from pathlib import Path
122
+ from urllib.request import Request, urlopen
123
+
124
+ body = {
125
+ "state": [{
126
+ "type": "image",
127
+ "base64": base64.b64encode(Path("photo.jpg").read_bytes()).decode("ascii"),
128
+ }],
129
+ "questions": {
130
+ "has_fork": {"type": "noul", "instructions": "Is there a fork in the image?"},
131
+ },
132
+ }
133
+ request = Request(
134
+ "http://127.0.0.1:8000/v1/systemone",
135
+ data=json.dumps(body).encode("utf-8"),
136
+ headers={"Content-Type": "application/json"},
137
+ )
138
+ with urlopen(request, timeout=30) as response:
139
+ print(json.load(response))
140
+ ```
141
+
142
+ For a remote image, use `{"type": "image", "url": "https://..."}` instead. HTTP does not load images from a top-level `image` field or from server-local paths. An image part's `url` accepts HTTP(S); its `base64` accepts plain Base64 without a Data URI prefix. Invalid requests and unsupported `score` questions return HTTP 422.
143
+
144
+ ## Architecture
145
+
146
+ | Component | V11 |
147
+ |---|---|
148
+ | Vision encoder | Frozen SigLIP2-B/16, 256 × 256 input, about 93M parameters |
149
+ | Image preprocessing | Aspect-preserving resize and letterbox padding |
150
+ | Connector | 2 × 2 patch grouping by channel concatenation, then LayerNorm → Linear → GELU → Linear |
151
+ | Visual sequence | 256 patch features become 64 visual tokens, inserted after `[CLS]` |
152
+ | Text encoder | Laya-initialized ModernBERT-large, bidirectional, about 395M parameters |
153
+ | Decision head | Laya's two Transformer layers and option scorer, about 27M parameters |
154
+ | Checkpoint | About 518M parameters, FP32, about 2.07 GB of weights |
155
+
156
+ Each option is scored at its `[MASK]` position. Calibrated softmax converts option scores into probabilities. The checkpoint contains merged LoRA weights; a separate adapter is not required for inference. Load it with `devision.load`, which understands the custom checkpoint layout.
157
+
158
+ ## Training and calibration
159
+
160
+ V11 continues from V9B, following earlier image-caption alignment and RLCD decision training. The final round used **9,988 distinct questions for one epoch, 1,249 optimizer steps**, on Apple MPS in FP32:
161
+
162
+ - 3,000 counting questions;
163
+ - 4,500 replay questions, including ScienceQA, VSR and Visual7W;
164
+ - 2,488 left/right questions retained from V9B.
165
+
166
+ Learning rates were `5e-5` for the projector and decision head and `1e-4` for LoRA, with 125 warmup steps. See the [code and training log](https://github.com/byebyebruce/devision) for the full training lineage and configurations.
167
+
168
+ Temperature scaling was fitted on the project's development/calibration mixture. Inference first uses the matching question-type/option-count bucket and otherwise falls back to the question-type temperature:
169
+
170
+ | Temperature | Value |
171
+ |---|---|
172
+ | Choice, 2 options | 2.1514 |
173
+ | Choice, 3–5 options | 1.9454 |
174
+ | Choice fallback | 1.9879 |
175
+ | Noul | 1.8161 |
176
+
177
+ Calibration changes probabilities, not the model's underlying visual ability. Validate confidence thresholds on your own distribution.
178
+
179
+ ## Evaluation
180
+
181
+ These are saved results from the V11 checkpoint, evaluated through `decide` on **MPS** with fitted temperatures. ECE uses 15 bins. The project test sets use held-out images; they are project-specific subsets or generated questions, not official leaderboard scores. Several benchmarks have also informed decisions across training rounds, so they should not be interpreted as untouched final tests throughout development.
182
+
183
+ | Set | Questions | Accuracy | ECE |
184
+ |---|---:|---:|---:|
185
+ | COCO object presence | 1,120 | 0.955 | 0.022 |
186
+ | VQAv2 multiple choice | 1,420 | 0.891 | 0.038 |
187
+ | COCO size | 1,100 | 0.857 | 0.021 |
188
+ | POPE, project filtered set | 8,676 | 0.844 | 0.072 |
189
+ | GQA val subset | 992 | 0.745 | 0.085 |
190
+ | COCO position | 1,274 | 0.850 | 0.013 |
191
+ | VQAv2 yes/no subset | 1,000 | 0.716 | 0.043 |
192
+ | COCO relative position | 1,950 | 0.651 | 0.033 |
193
+ | VSR, project held-out split | 904 | 0.653 | 0.033 |
194
+ | Visual7W, project held-out split | 1,000 | 0.712 | 0.040 |
195
+ | Fresh counting test | 600 | 0.723 | 0.043 |
196
+
197
+ ### Comparison with Laya Vision 201M
198
+
199
+ The following comparisons use Laya Vision's published per-question predictions on the same questions. Differences are percentage points, with 95% intervals from paired resampling by image. We did not rerun Laya Vision on our hardware.
200
+
201
+ | Set | Questions | Laya Vision | deVision V11 | Difference, percentage points |
202
+ |---|---:|---:|---:|---|
203
+ | VQAv2 yes/no | 4,887 | 0.717 | 0.729 | +1.2 [−0.4, +2.7] |
204
+ | A-OKVQA | 1,138 | 0.598 | 0.603 | +0.4 [−2.9, +3.7] |
205
+ | ScienceQA with images | 2,097 | 0.824 | 0.747 | −7.7 [−9.8, −5.6] |
206
+
207
+ The first two intervals include zero; these results do not establish superiority or equivalence. The full VQAv2 and A-OKVQA comparison sets include some images used in deVision training; the training log also reports subsets excluding those images. ScienceQA's compared images are unseen in training.
208
+
209
+ On the full POPE random/popular/adversarial sets (3,000 questions each), V11 scores **0.863 / 0.849 / 0.813**, versus Laya Vision's published **0.836 / 0.819 / 0.777**. Only aggregate baseline scores are available for this comparison; it is not paired. These full sets differ from the 8,676-question filtered set above.
210
+
211
+ ## Limitations and model selection
212
+
213
+ - **Counting recovery was not demonstrated.** On the fresh 600-question test, V11 differs from V9B by −0.3 percentage points [−2.7, +1.8], missing the predefined improvement target. The owner selected V11 as a tradeoff, particularly for improved left/right position consistency; this is not a claim that every acceptance target passed.
214
+ - **Spatial reasoning is incomplete.** Correct answers on both an original image and its mirror occur for about 61% of left/right position pairs and 39% of relative-position choice pairs, but only 10% of relative-position yes/no pairs.
215
+ - **Scientific diagrams remain difficult.** On 323 natural-science questions judged to require the image, V11 scores 0.467 versus Laya Vision's 0.700. On the full ScienceQA set, swapping in unrelated images still yields 0.665 accuracy, compared with 0.747 for the correct images; text and answer priors contribute substantially.
216
+ - **Old-task protection is uncertain in two comparisons.** VSR and A-OKVQA did not establish the predefined lower bound of −2 percentage points relative to V9B. This is uncertainty about protection, not proof of a significant decline.
217
+ - **Small text and fine detail are limited by 256 × 256 input.** The model is not a general-purpose OCR or text-generation system.
218
+ - **English, single image, `noul` and `choice` only.** Other languages, multi-image input and `score` questions are not supported.
219
+ - **Probabilities can be miscalibrated out of domain.** A low ECE on one benchmark does not guarantee reliable confidence elsewhere.
220
+
221
+ ## Links and intended use
222
+
223
+ - [Code, training configurations and experiment records](https://github.com/byebyebruce/devision)
224
+ - [Laya decision model](https://huggingface.co/convaiinnovations/laya)
225
+ - [SigLIP2 vision encoder](https://huggingface.co/google/siglip2-base-patch16-256)
226
+ - [Laya Vision reference implementation and published evaluations](https://github.com/r33drichards/laya-vision)
227
+
228
+ The project is intended for non-commercial research. This card does not assign a new license to upstream models or datasets; their respective terms remain applicable.