marcodsn commited on
Commit
231d7d3
·
verified ·
1 Parent(s): b933b9d

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +289 -0
README.md CHANGED
@@ -2,4 +2,293 @@
2
  license: other
3
  license_name: lfm1.0
4
  license_link: LICENSE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  license: other
3
  license_name: lfm1.0
4
  license_link: LICENSE
5
+ base_model:
6
+ - LiquidAI/LFM2.5-VL-450M
7
+ base_model_relation: finetune
8
+ pipeline_tag: image-text-to-text
9
+ library_name: transformers
10
+ language:
11
+ - en
12
+ tags:
13
+ - calibration
14
+ - classification
15
+ - system-one
16
+ - jev-compatible
17
+ datasets:
18
+ - allenai/ai2_arc
19
+ - allenai/sciq
20
+ - allenai/openbookqa
21
+ - tau/commonsense_qa
22
+ - uoft-cs/cifar10
23
+ - mteb/stsbenchmark-sts
24
  ---
25
+
26
+ <div align="center">
27
+ <img
28
+ src="https://huggingface.co/nullsilver/alpha-sys-1-scratch/resolve/main/alpha-sys-1-banner-light.png"
29
+ alt="alpha-sys-1 banner"
30
+ style="width: 100%; max-width: 100%; height: auto; display: inline-block; margin-bottom: 0.5em; margin-top: 0.5em;"
31
+ />
32
+ <div style="display: flex; justify-content: center; gap: 0.5em; margin-bottom: 1em;">
33
+ <a href="https://docs.liquid.ai/lfm/getting-started/welcome"><strong>docs</strong></a> •
34
+ <a href="https://nullsilver.com"><strong>nullsilver.com</strong></a>
35
+ </div>
36
+ </div>
37
+
38
+ # alpha-sys-1-450M
39
+
40
+ alpha-sys-1 is a multimodal, Jev-compatible **System One model**. It takes a state, which
41
+ may contain text, an image, or both, together with a question that has a fixed set of
42
+ answers, and returns a probability distribution over those answers in one forward pass. It
43
+ generates no text.
44
+
45
+ The model is trained for calibrated probabilities: across a large group of similar
46
+ examples where it assigns an answer a probability near 80%, that answer should be correct
47
+ in roughly 80% of cases. Calibration degrades when the input differs substantially from
48
+ the training data, so check the probabilities on data from the intended application.
49
+
50
+ | | |
51
+ |---|---|
52
+ | Base | [LiquidAI/LFM2.5-VL-450M](https://huggingface.co/LiquidAI/LFM2.5-VL-450M) |
53
+ | Tuning | LoRA rank 32, lr 1e-4, merged into the base weights |
54
+ | Checkpoint | `alpha-sys-1-260919`, revision `260919`, seed 1 of 3 |
55
+ | Input | text, one image, or both; English |
56
+ | Output | probabilities over the answer space |
57
+ | Sizes | [450M](https://huggingface.co/nullsilver/alpha-sys-1-450M) · [1.6B](https://huggingface.co/nullsilver/alpha-sys-1-1.6B) · [3B](https://huggingface.co/nullsilver/alpha-sys-1-3B) |
58
+
59
+ ## Question types
60
+
61
+ Questions follow TypeSafe's System One format: a request contains one `state` and any
62
+ number of `questions`, so a question written for Jev runs here as is. `images` is an extra
63
+ field for multimodal inputs.
64
+
65
+ | type | answer space | returns |
66
+ |---|---|---|
67
+ | `choice` | named options, up to 26 | `probabilities` over the options, `choice` (argmax) |
68
+ | `noul` | a statement | `noul`, P(true) |
69
+ | `score` | ordered levels, lowest first | `probabilities` over the levels, `score` (expected level index) |
70
+
71
+ The answer is read from the next-token logits for the answer labels (`A`, `B`, … or
72
+ `No`/`Yes`), renormalised over the valid labels. Each question is answered independently:
73
+ one question's answer is never context for another.
74
+
75
+ > [!NOTE]
76
+ > `confidence` is `1 - H(p)/log(n)`, computed from the distribution. It is not a separate
77
+ > prediction.
78
+
79
+ > [!TIP]
80
+ > A `noul` probability near 0.5 means the model is uncertain.
81
+
82
+ ## Usage
83
+
84
+ `alpha_sys_1.py` in this repository renders questions the way the model was trained on
85
+ them, batches the questions on one state, and returns answers in the System One shape.
86
+
87
+ ```python
88
+ from huggingface_hub import hf_hub_download
89
+ import importlib.util, sys
90
+ spec = importlib.util.spec_from_file_location("alpha_sys_1", hf_hub_download("nullsilver/alpha-sys-1-450M", "alpha_sys_1.py", revision="260919"))
91
+ alpha_sys_1 = importlib.util.module_from_spec(spec); spec.loader.exec_module(alpha_sys_1)
92
+
93
+ m = alpha_sys_1.SystemOne("nullsilver/alpha-sys-1-450M", revision="260919")
94
+ m.system_one({
95
+ "state": {"subject": "Duplicate charge on invoice #4411",
96
+ "body": "We were billed twice for March. Refund the duplicate today or we cancel our plan."},
97
+ "questions": {
98
+ "department": {"type": "choice", "instructions": "Which department should handle this email?",
99
+ "criteria": {"billing": "invoices, payments, refunds", "technical": "bugs, outages",
100
+ "sales": "pricing, new contracts", "other": "everything else"}},
101
+ "urgency": {"type": "score", "instructions": "How urgent is this request?",
102
+ "criteria": ["not urgent", "soon", "critical deadline or blocking issue"]},
103
+ "churn_risk": {"type": "noul", "instructions": "The user threatens to cancel or leave."}}})
104
+ # {"model": ..., "answers": {"department": {"choice": "billing", "probabilities": {...}, "confidence": ...},
105
+ # "urgency": {"score": 1.7, ...}, "churn_risk": {"noul": 0.83}}}
106
+ ```
107
+
108
+ Without the client, use this prompt format. A different format gives less reliable
109
+ probabilities.
110
+
111
+ ```python
112
+ import string, torch
113
+ from transformers import AutoModelForImageTextToText, AutoProcessor
114
+
115
+ repo, rev = "nullsilver/alpha-sys-1-450M", "260919"
116
+ processor = AutoProcessor.from_pretrained(repo, revision=rev)
117
+ processor.tokenizer.padding_side = "left"
118
+ model = AutoModelForImageTextToText.from_pretrained(
119
+ repo, revision=rev, dtype=torch.bfloat16, device_map="auto").eval()
120
+
121
+ def render(state, q):
122
+ parts = [state] if state else []
123
+ if q["type"] == "noul":
124
+ c = q.get("criteria") or {}
125
+ clar = "".join(f"\n{lab} means: {c[k]}" for lab, k in (("Yes", "true"), ("No", "false")) if c.get(k))
126
+ parts.append(f"Statement: {q['instructions']}{clar}\nIs the statement true? Answer with Yes or No only.")
127
+ return "\n\n".join(parts), ["No", "Yes"]
128
+ crit = q["criteria"]
129
+ items = list(crit.items()) if isinstance(crit, dict) else [(o, None) for o in crit]
130
+ labels = list(string.ascii_uppercase[:len(items)])
131
+ lines = [f"{lab}. {o}" + (f": {d}" if d else "") for lab, (o, d) in zip(labels, items)]
132
+ parts.append(q["instructions"] + "\n" + "\n".join(lines) + "\nAnswer with the letter only.")
133
+ return "\n\n".join(parts), labels
134
+
135
+ @torch.inference_mode()
136
+ def ask(q, state="", image=None):
137
+ text, labels = render(state, q)
138
+ content = ([{"type": "image", "image": image}] if image is not None else []) + [{"type": "text", "text": text}]
139
+ inputs = processor.apply_chat_template(
140
+ [[{"role": "user", "content": content}]], add_generation_prompt=True, tokenize=True,
141
+ return_dict=True, processor_kwargs={"return_tensors": "pt"}).to(model.device)
142
+ logits = model(**inputs, logits_to_keep=1).logits[0, -1].float()
143
+ ids = [processor.tokenizer.encode(lab, add_special_tokens=False)[0] for lab in labels]
144
+ return torch.softmax(logits[ids], -1).tolist()
145
+
146
+ p = ask({"type": "noul", "instructions": "The message conveys urgency"},
147
+ state="Our API integration started returning 500 errors an hour before launch.")
148
+ urgent = p[1] # P(Yes)
149
+ ```
150
+
151
+ > [!NOTE]
152
+ > - A dict `state` is rendered one field per line, as `key: value`.
153
+ > - Training images smaller than 256 px were upscaled to 256 px.
154
+ > - For several questions on one state, batch them with `padding_side="left"`.
155
+ > - In bfloat16, probabilities move by up to a few hundredths with batch composition and
156
+ > padding.
157
+
158
+ ## Training
159
+
160
+ Training uses cross-entropy between the model's distribution and a target `y_soft`. The
161
+ target is one-hot when a dataset provides one answer, and the annotator distribution when
162
+ several annotations are available. Options are shuffled on every draw, the vision tower is
163
+ frozen, and environments are sampled in proportion to the square root of their size.
164
+
165
+ | environment | modality | type | label |
166
+ |---|---|---|---|
167
+ | mcq (ARC-Easy, SciQ, OpenBookQA, CommonsenseQA) | text | choice | one-hot |
168
+ | ChaosNLI (100-annotator items) | text | choice | annotator distribution |
169
+ | CivilComments-WILDS | text | noul | annotator share |
170
+ | STS-B | text | score | annotator mean |
171
+ | Folktables (ACS income, California 2014) | tabular as text | noul | outcome |
172
+ | CIFAR-10 | image | choice | one-hot |
173
+ | Camelyon17-WILDS | image | noul | outcome |
174
+
175
+ Three random seeds were trained. The released checkpoint is the seed with the lowest mean
176
+ development loss across environments.
177
+
178
+ ## Evaluation
179
+
180
+ Each test split was read once per checkpoint. Reported intervals are 95% clustered
181
+ bootstrap intervals, clustered on the relevant dataset group: question, comment, hospital,
182
+ or state-year.
183
+
184
+ > [!IMPORTANT]
185
+ > Compare models on NLL and Brier score. ECE is reported alongside them and is misleading
186
+ > on its own: a model that always predicts the base rate can have a low ECE.
187
+
188
+ The tables carry two reference points. The **base rate** is the constant predictor: it
189
+ answers every question with the label frequencies of the training split (for example
190
+ "toxic" 14% of the time on CivilComments, whatever the comment says), or uniformly when
191
+ the options are shuffled. Any model should beat it. **Base + T** is the untuned
192
+ LFM2.5-VL-450M, read the same way as the tuned model, with its label logits divided by
193
+ one scalar temperature chosen to minimise NLL on the environment's development split.
194
+
195
+ **Trained environments.**
196
+
197
+ | environment | NLL | NLL, base + T | Brier | ECE | AUROC | acc |
198
+ |---|---|---|---|---|---|---|
199
+ | mcq | **0.727** | 0.929 | 0.380 | 0.067 | 0.816 | 0.722 |
200
+ | ChaosNLI | **0.902** | 0.941 | 0.245 | 0.079 | 0.591 | 0.575 |
201
+ | CivilComments | **0.324** | 0.581 | 0.044 | 0.073 | 0.906 | 0.940 |
202
+ | STS-B | **1.107** | 1.782 | 0.325 | 0.046 | 0.622 | 0.562 |
203
+ | Folktables | **0.436** | 0.693 | 0.286 | 0.013 | 0.763 | 0.789 |
204
+ | CIFAR-10 (+C) | **0.509** | 0.804 | 0.212 | 0.040 | 0.918 | 0.851 |
205
+ | Camelyon17 | **0.202** | 0.693 | 0.110 | 0.033 | 0.887 | 0.930 |
206
+
207
+ > [!NOTE]
208
+ > ChaosNLI, CivilComments and STS-B have soft labels from multiple annotations, so
209
+ > top-label ECE does not fully measure calibration. On these, use NLL and KL divergence to
210
+ > the annotator distribution.
211
+
212
+ **Unseen tasks.** Not in training.
213
+
214
+ | task | type | NLL | NLL, base + T | base rate |
215
+ |---|---|---|---|---|
216
+ | BoolQ | noul | **0.661** | 0.646 | 0.665 |
217
+ | Yelp review stars | score | **1.467** | 1.455 | 1.609 |
218
+
219
+ **Distribution shift.** CIFAR-10-C.
220
+
221
+ | | clean | sev. 1 | 2 | 3 | 4 | 5 |
222
+ |---|---|---|---|---|---|---|
223
+ | accuracy | 0.960 | 0.907 | 0.872 | 0.841 | 0.795 | 0.724 |
224
+ | mean confidence | 0.962 | 0.928 | 0.903 | 0.882 | 0.856 | 0.811 |
225
+
226
+ **Other System One models.** NLL on the text environments, same test splits, same
227
+ readout. The other alpha-sys-1 sizes on the table are their released seeds. `Qwen3.8-27B` is the open 27B
228
+ generalist, read at its first answer token with reasoning off, plus a dev-fitted
229
+ temperature.
230
+
231
+ | environment | alpha-sys-1-450M (this) | alpha-sys-1-1.6B | Jev 1.13.0 | Qwen3.8-27B + T | base rate |
232
+ |---|---|---|---|---|---|
233
+ | mcq | **0.727** | 0.427 | 0.129 | 0.159 | 1.439 |
234
+ | ChaosNLI | **0.902** | 0.784 | 0.929 | 0.706 | 0.938 |
235
+ | CivilComments | **0.324** | 0.323 | 0.671 | 0.473 | 0.425 |
236
+ | STS-B | **1.107** | 1.033 | 1.222 | 1.347 | 1.727 |
237
+ | Folktables | **0.436** | 0.448 | 0.534 | 0.472 | 0.683 |
238
+ | BoolQ (unseen) | **0.661** | 0.479 | 0.225 | 0.316 | 0.665 |
239
+ | Yelp review stars (unseen) | **1.467** | 1.110 | 0.900 | 0.858 | 1.609 |
240
+
241
+ Per-hospital, per-state-year and per-identity-group tables, the three-seed gate tables and
242
+ the full comparison against other System One models (hosted and open) are in the
243
+ [repository](https://github.com/nullsilver/alpha-sys-1) under `runs/`.
244
+
245
+ ## Limitations
246
+
247
+ > [!WARNING]
248
+ > On a task that differs substantially from the training environments, do not assume this
249
+ > model stays calibrated; measure it against the base model's calibration. In
250
+ > leave-one-domain-out tests at 1.6B, a model tuned on the other environments beat the
251
+ > untuned base with a transferred temperature on one held-out environment out of three,
252
+ > and on the two unseen tasks above the trained-on-all checkpoints match the base model and do not beat it.
253
+ > With a few hundred labelled examples from your own task, fit a temperature on them:
254
+ > divide the label logits by one scalar chosen to minimise NLL on those examples
255
+ > (`alpha_sys_1.fit_temperature`), then pass it as `SystemOne(..., temperature=T)`.
256
+
257
+ - Knowledge depends on model size: on MCQ, the untuned 1.6B base outperforms this tuned
258
+ model.
259
+ - When the model does not know an answer, its distribution is close to uniform.
260
+ - Under strong distribution shift, such as CIFAR-10-C at severity 5, confidence remains
261
+ higher than accuracy.
262
+ - Reversing the option order changes the top answer on 15% of MCQ items, mostly
263
+ among low-confidence examples.
264
+ - The answer space is capped at 26 options.
265
+ - Fine-tuning used English data only and at most one image per question.
266
+
267
+ ## Related work
268
+
269
+ The interface follows TypeSafe's Jev (a hosted System One model, the `state` / `questions`
270
+ request shape). Reading an answer distribution from the label-token logits of one forward
271
+ pass is the readout of Kadavath et al. (2022, *Language Models (Mostly) Know What They
272
+ Know*) and of the LLM-as-a-Verifier line of work, which scores rubric levels from the
273
+ logits of letter tokens. That calibration improves with size, and that a temperature
274
+ fitted on one domain transfers badly to another, is Jiang et al. (2021, *How Can We Know
275
+ When Language Models Know?*). Training on a proper scoring rule against annotator
276
+ distributions is why a fixed answer space and calibration are non-conflicting (Kalai and
277
+ Vempala, 2024, *Calibrated Language Models Must Hallucinate*). Base models: Liquid AI's
278
+ LFM2.5-VL.
279
+
280
+ ## License
281
+
282
+ This model is derived from LiquidAI/LFM2.5-VL-450M and is released under the [LFM Open License
283
+ v1.0](LICENSE).
284
+
285
+ ## Citation
286
+
287
+ ```bibtex
288
+ @misc{alphasys1,
289
+ title = {alpha-sys-1: a small calibrated System One model},
290
+ author = {Nullsilver},
291
+ year = {2026},
292
+ url = {https://huggingface.co/collections/nullsilver/alpha-sys-1}
293
+ }
294
+ ```