File size: 24,889 Bytes
cd02163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
"""Decider 2B: a decision model for Jev/SystemOne requests. One file, as released on Hugging Face.

Reads a state and a schema of typed questions (choice, score, noul) and returns a probability for
every allowed option of every question in one forward pass: no text generation, no parsing.

  from decider_model import load_release_model, systemone
  model = load_release_model(path, device="cuda")
  systemone(model, {"state": "...", "questions": {...}})

Sections: the Jev/SystemOne request and response format, the token layout of a model pass, and the
model with its loader. The training code in training/ uses the same format and layout.
"""
import json
import math
import os
import re


# ================================================================================================
# Jev / SystemOne format
# ================================================================================================

QUESTION_TYPES = ("choice", "score", "noul")
MAX_REQUEST_TOKENS = 65536            # Jev: whole request
MAX_STATE_PLUS_QUESTION_TOKENS = 32768  # Jev: state plus the longest single question
MAX_QUESTIONS = 128                 # as pplx-decider; Cloudflare allows 64
MAX_OPTIONS = 512
MAX_KEY_CHARS = 128
NOUL_OPTIONS = ("true", "false")
# Selective answering: when a choice offers "I don't know" and no answer reaches this probability,
# the model abstains. A wrong answer costs more than an abstention wherever hallucination is
# counted (AA-Omniscience-Decision: answering pays only when p > 1 / (2 - accuracy), about 0.55).
# 0 turns it off. Tuned with aa_eval/run_aa.py --evals omniscience_proxy.
ABSTAIN_THRESHOLD = float(os.environ.get("DECIDER_ABSTAIN_THRESHOLD", "0.55"))
ABSTAIN_TEXT = re.compile(r"^\s*(i\s*do\s*n'?\s*t\s*know|i\s*do\s*not\s*know)\s*[.!]?\s*$", re.I)


class SchemaError(ValueError):
    """The request or record does not follow the format; the message says where."""


def _text(value):
    return value if isinstance(value, str) else json.dumps(value, ensure_ascii=False, sort_keys=True)


def state_text(state):
    """One canonical text for a state, used in training and serving alike."""
    if isinstance(state, str):
        return state if state.strip() else "(empty)"
    if isinstance(state, list) and all(isinstance(item, str) for item in state):
        return "\n\n".join(state) if state else "(empty)"
    return json.dumps(state, ensure_ascii=False, indent=2)


def is_empty_state(state):
    return (isinstance(state, str) and not state.strip()) or (isinstance(state, (dict, list)) and not state)


def request_state_text(state, questions):
    """The state text a request is served with. When the state is empty, the content is in the
    question instructions (as in some Jev benchmark requests), so those are shown as the state:
    the model learned to read content from the state."""
    if is_empty_state(state):
        texts = list(dict.fromkeys(_text(q.get("instructions")).strip() for q in questions.values()
                                   if q.get("instructions") is not None))
        texts = [t for t in texts if t]
        if texts:
            return "\n\n".join(texts)
    return state_text(state)


def level_text(level):
    if isinstance(level, dict):
        label = level.get("label")
        extra = {k: v for k, v in level.items() if k != "label"}
        return f"{label} ({_text(extra)})" if extra else str(label)
    return str(level)


def validate_request(body):
    """Raise SchemaError unless body is a valid SystemOne request."""
    if not isinstance(body, dict):
        raise SchemaError("request must be a JSON object")
    if "state" not in body:
        raise SchemaError("missing 'state'")
    state = body["state"]
    if not isinstance(state, (str, dict, list)):
        raise SchemaError("'state' must be a string, an object or a list of strings")
    if isinstance(state, list) and not all(isinstance(item, (str, dict)) for item in state):
        raise SchemaError("'state' list items must be strings or objects")
    questions = body.get("questions")
    if not isinstance(questions, dict) or not questions:
        raise SchemaError("'questions' must be a non-empty object")
    if len(questions) > MAX_QUESTIONS:
        raise SchemaError(f"at most {MAX_QUESTIONS} questions per request")
    for qid, question in questions.items():
        where = f"questions.{qid}"
        if not qid or len(qid) > MAX_KEY_CHARS:
            raise SchemaError(f"{where}: question ids must be 1-{MAX_KEY_CHARS} characters")
        if not isinstance(question, dict):
            raise SchemaError(f"{where}: must be an object")
        kind = question.get("type")
        if kind not in QUESTION_TYPES:
            raise SchemaError(f"{where}.type: must be one of {', '.join(QUESTION_TYPES)}")
        # Jev requests may carry structured instructions (an object, e.g. a candidate document); any
        # JSON value is read as its canonical text.
        instructions = question.get("instructions")
        criteria = question.get("criteria")
        if kind == "choice":
            if not isinstance(criteria, dict) or len(criteria) < 2:
                raise SchemaError(f"{where}.criteria: a choice needs an object with at least 2 answers")
            if len(criteria) > MAX_OPTIONS:
                raise SchemaError(f"{where}.criteria: at most {MAX_OPTIONS} answers")
            for key, description in criteria.items():
                if not key or len(key) > MAX_KEY_CHARS:
                    raise SchemaError(f"{where}.criteria: answer keys must be 1-{MAX_KEY_CHARS} characters")
                # A description may be structured too (a chord's pitch classes, a palette, a move in two
                # notations); it is read as its canonical text.
        elif kind == "score":
            if not isinstance(criteria, list) or len(criteria) < 2:
                raise SchemaError(f"{where}.criteria: a score needs a list of at least 2 levels, lowest first")
            if len(criteria) > MAX_OPTIONS:
                raise SchemaError(f"{where}.criteria: at most {MAX_OPTIONS} levels")
            for i, level in enumerate(criteria):
                if not (isinstance(level, str) and level.strip()) and not (
                        isinstance(level, dict) and isinstance(level.get("label"), str) and level["label"].strip()):
                    raise SchemaError(f"{where}.criteria[{i}]: a level is a non-empty string or an object with 'label'")
        else:
            if not (instructions and _text(instructions).strip()):
                raise SchemaError(f"{where}.instructions: a noul question needs the statement to judge")
            # Jev takes no criteria on noul; Clef allows optional true/false wording. Accept that shape
            # (it is not used) so Clef-style clients work, and reject anything else.
            if criteria is not None and not (isinstance(criteria, dict) and set(criteria) <= {"true", "false"}):
                raise SchemaError(f"{where}.criteria: noul questions take no criteria")


def render(qid, question):
    """What the model reads for one question: prompt text, option lines, and the answer keys."""
    kind = question["type"]
    instructions = question.get("instructions")
    text = _text(instructions).strip() if instructions is not None else ""
    prompt = text or str(qid)
    criteria = question.get("criteria")
    if kind == "choice":
        keys = list(criteria)
        labels = [k if d in (None, "", k) else f"{k}: {_text(d)}" for k, d in criteria.items()]
    elif kind == "score":
        keys = list(range(len(criteria)))
        labels = [f"level {i}: {level_text(level)}" for i, level in enumerate(criteria)]
        prompt = f"{prompt}\n(Rate on the ordered levels below, lowest first.)"
    else:
        keys = [True, False]
        labels = list(NOUL_OPTIONS)
        prompt = prompt if prompt.endswith("?") else f"Is this statement true? {prompt}"
    return {"id": qid, "kind": kind, "prompt": prompt, "labels": labels, "keys": keys}


def items(questions):
    return [render(qid, question) for qid, question in questions.items()]


def answer(item, probabilities, criteria=None):
    """Jev answer object for one question from its option probabilities (in render order)."""
    total = sum(probabilities) or 1.0
    p = [float(x) / total for x in probabilities]
    best = max(range(len(p)), key=p.__getitem__)
    if item["kind"] == "choice" and criteria:
        p, best = abstain(item["keys"], criteria, p, best)
    if item["kind"] == "choice":
        return {"type": "choice", "choice": item["keys"][best], "confidence": p[best],
                "probabilities": dict(zip(item["keys"], p))}
    if item["kind"] == "score":
        return {"type": "score", "score": sum(i * v for i, v in enumerate(p)), "confidence": p[best],
                "legend": {str(i): level_text(level) for i, level in enumerate(criteria)},
                "probabilities": {str(i): v for i, v in enumerate(p)}}
    return {"type": "noul", "noul": p[0]}


def abstain_index(keys, criteria):
    """Index of the option that means "I don't know", or None."""
    for i, key in enumerate(keys):
        description = criteria.get(key) if isinstance(criteria, dict) else None
        if ABSTAIN_TEXT.match(str(description or "")) or ABSTAIN_TEXT.match(str(key).replace("_", " ")):
            return i
    return None


def abstain(keys, criteria, p, best, threshold=None):
    """(probabilities, best) after selective answering: below the threshold, "I don't know" wins.

    The answers keep their relative probabilities; "I don't know" takes the mass needed to be
    the highest, so the response stays a valid distribution.
    """
    threshold = ABSTAIN_THRESHOLD if threshold is None else threshold
    idk = abstain_index(keys, criteria)
    if idk is None or threshold <= 0 or best == idk or p[best] >= threshold:
        return p, best
    others = 1.0 - p[idk]
    top = max(v for i, v in enumerate(p) if i != idk)
    if others <= 0:
        return p, idk
    scale = 0.9 / (top + others)        # top * scale < 1 - others * scale, so "I don't know" is highest
    q = [v * scale if i != idk else 0.0 for i, v in enumerate(p)]
    q[idk] = 1.0 - sum(q)
    return q, idk


def response(model, questions, probabilities, input_tokens):
    return {"model": model,
            "answers": {item["id"]: answer(item, probs, questions[item["id"]].get("criteria"))
                        for item, probs in zip(items(questions), probabilities)},
            "usage": {"input_tokens": int(input_tokens), "output_tokens": 0}}


# ---- training records -------------------------------------------------------------------------

RECORD_FIELDS = ("id", "task", "source", "license", "state", "questions", "expected")


def validate_record(record):
    """Raise SchemaError unless the record is a valid request with a right answer for every question."""
    for field in RECORD_FIELDS:
        if field not in record:
            raise SchemaError(f"record is missing '{field}'")
    validate_request(record)
    expected = record["expected"]
    if not isinstance(expected, dict) or set(expected) != set(record["questions"]):
        raise SchemaError("'expected' must have exactly one answer per question")
    for qid, question in record["questions"].items():
        value = expected[qid]
        kind = question["type"]
        if kind == "choice" and value not in question["criteria"]:
            raise SchemaError(f"expected.{qid}: '{value}' is not one of the criteria keys")
        if kind == "score" and not (isinstance(value, int) and not isinstance(value, bool)
                                    and 0 <= value < len(question["criteria"])):
            raise SchemaError(f"expected.{qid}: must be a level index 0..{len(question['criteria']) - 1}")
        if kind == "noul" and not isinstance(value, bool):
            raise SchemaError(f"expected.{qid}: must be true or false")
    teacher = record.get("teacher")
    if teacher is not None:
        for qid, probs in teacher.items():
            if qid not in record["questions"] or not isinstance(probs, dict):
                raise SchemaError(f"teacher.{qid}: unknown question or not an object")
            if not math.isclose(sum(probs.values()), 1.0, abs_tol=1e-2):
                raise SchemaError(f"teacher.{qid}: probabilities must sum to 1")


def gold_index(item, value):
    """Position of the expected answer among the rendered options."""
    return item["keys"].index(value)


def teacher_vector(item, probs):
    """Teacher probabilities in render order, or None."""
    if not probs:
        return None
    if item["kind"] == "noul":
        p = float(probs.get("true", probs.get(True, 0.0)))
        return [p, 1.0 - p]
    return [float(probs.get(str(key), probs.get(key, 0.0))) for key in item["keys"]]


# ================================================================================================
# Token layout of one model pass
# ================================================================================================

INTRO = "Read the state, then answer each question by choosing one of its options.\n\nState:\n"


class TooLong(ValueError):
    pass


def question_pieces(k, item):
    """Text pieces of question k; marks say which pieces end at a scored token."""
    pieces = [(f"\n\nQuestion {k + 1}: {item['prompt']}\nOptions:", None)]
    pieces += [(f"\n[{i + 1}] {label}", "option") for i, label in enumerate(item["labels"])]
    pieces.append((f"\nAnswer {k + 1}:", "answer"))
    return pieces


def encode_pieces(tokenizer, texts):
    return tokenizer(texts, add_special_tokens=False)["input_ids"] if texts else []


def question_tokens(tokenizer, items):
    """Token pieces per question, numbered as if each were first in its pass (k is fixed later)."""
    return [list(zip(encode_pieces(tokenizer, [t for t, _ in question_pieces(0, item)]),
                     [m for _, m in question_pieces(0, item)])) for item in items]


def plan(tokenizer, state, items, max_length):
    """Split questions into passes that fit max_length with the whole state in each.

    Returns (passes, state_tokens, question_sizes); each pass is a list of item indices.
    Raises TooLong with the index of the first question that cannot fit even alone.
    """
    intro = encode_pieces(tokenizer, [INTRO, state])
    base = len(intro[0]) + len(intro[1])
    sizes = [sum(len(ids) for ids, _ in pieces) + 4 for pieces in question_tokens(tokenizer, items)]
    passes, current, used = [], [], base
    for index, size in enumerate(sizes):
        if base + size > max_length:
            raise TooLong(index)
        if current and used + size > max_length:
            passes.append(current)
            current, used = [], base
        current.append(index)
        used += size
    if current:
        passes.append(current)
    return passes, len(intro[1]), sizes


def build(tokenizer, state, items):
    """Token ids plus the scored positions for one pass over these items."""
    texts, marks = [INTRO, state], [None, None]
    for k, item in enumerate(items):
        for text, mark in question_pieces(k, item):
            texts.append(text)
            marks.append(mark)
    ids, answers, options, current = [], [], [], []
    for piece, mark in zip(encode_pieces(tokenizer, texts), marks):
        ids += piece
        if mark == "option":
            current.append(len(ids) - 1)
        elif mark == "answer":
            answers.append(len(ids) - 1)
            options.append(current)
            current = []
    return {"ids": ids, "answers": answers, "options": options}


# ================================================================================================
# Model: merged Qwen3.5-2B backbone (bidirectional full attention) + option-pointer decision head
# ================================================================================================

import torch

HEAD_WEIGHTS = "decider_head.safetensors"
HEAD_CONFIG = "decider_head_config.json"
NEG = -1e4


class Encoder:
    """Batch tensors for a list of {"state": text, "items": items(questions)} records."""

    def __init__(self, tokenizer, pad_to_multiple=8):
        self.tokenizer = tokenizer
        self.pad_to_multiple = pad_to_multiple

    def __call__(self, batch):
        layouts = [build(self.tokenizer, x["state"], x["items"]) for x in batch]
        width = max(len(x["ids"]) for x in layouts)
        width += (-width) % self.pad_to_multiple
        most = max(len(o) for x in layouts for o in x["options"])
        input_ids = torch.full((len(batch), width), self.tokenizer.pad_token_id, dtype=torch.long)
        attention_mask = torch.zeros((len(batch), width), dtype=torch.long)
        answer_pos, option_pos, counts = [], [], []
        for b, layout in enumerate(layouts):
            input_ids[b, : len(layout["ids"])] = torch.tensor(layout["ids"])
            attention_mask[b, : len(layout["ids"])] = 1
            for answer, positions in zip(layout["answers"], layout["options"]):
                answer_pos.append(b * width + answer)
                option_pos.append([b * width + p for p in positions] + [0] * (most - len(positions)))
                counts.append(len(positions))
        return {"input_ids": input_ids, "attention_mask": attention_mask,
                "answer_pos": torch.tensor(answer_pos, dtype=torch.long),
                "option_pos": torch.tensor(option_pos, dtype=torch.long),
                "option_mask": torch.arange(most)[None] < torch.tensor(counts)[:, None]}


def encode_record(record, questions=None):
    """{"state", "items"} for one Jev/SystemOne request (optionally a subset of its question ids)."""
    chosen = record["questions"] if questions is None else {q: record["questions"][q] for q in questions}
    return {"state": request_state_text(record["state"], record["questions"]), "items": items(chosen)}


class DeciderModel(torch.nn.Module):
    """The released model: one forward pass scores every option of every question in a request."""

    def __init__(self, path, dtype=torch.bfloat16, quantization=None, device=None):
        super().__init__()
        from safetensors.torch import load_file
        from transformers import AutoModelForCausalLM, AutoTokenizer

        with open(os.path.join(path, HEAD_CONFIG)) as file:
            self.config = json.load(file)
        self.tokenizer = AutoTokenizer.from_pretrained(path)
        if self.tokenizer.pad_token_id is None:
            self.tokenizer.pad_token = self.tokenizer.eos_token
        self.encoder = Encoder(self.tokenizer)
        if quantization:
            # 8-bit or 4-bit backbone via bitsandbytes (CUDA only); the decision head stays in float32.
            from transformers import BitsAndBytesConfig
            if quantization == "8bit":
                bnb = BitsAndBytesConfig(load_in_8bit=True)
            elif quantization == "4bit":
                bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16)
            else:
                raise ValueError("quantization must be None, '8bit' or '4bit'")
            lm = AutoModelForCausalLM.from_pretrained(path, dtype=dtype, quantization_config=bnb,
                                                      device_map={"": device or "cuda"})
        else:
            lm = AutoModelForCausalLM.from_pretrained(path, dtype=dtype)
        head = lm.get_output_embeddings()
        hidden = head.weight.shape[1]
        # The vocabulary head is unused: the backbone returns its final hidden states.
        for module in list(lm.modules()):
            for name, child in module.named_children():
                if child is head:
                    setattr(module, name, torch.nn.Identity())
        self.text_config = getattr(lm.config, "text_config", lm.config)
        self.bidirectional = bool(self.config.get("bidirectional", True))
        if self.bidirectional:
            for module in lm.modules():
                if hasattr(module, "is_causal") and hasattr(module, "q_proj"):
                    module.is_causal = False
        self.lm = lm
        self.head_dim = int(self.config["head_dim"])
        self.norm = torch.nn.RMSNorm(hidden, eps=1e-6)
        self.query = torch.nn.Linear(hidden, self.head_dim, bias=False)
        self.key = torch.nn.Linear(hidden, self.head_dim, bias=False)
        self.prior = torch.nn.Linear(hidden, 1)
        state = load_file(os.path.join(path, HEAD_WEIGHTS))
        for name in ("norm", "query", "key", "prior"):
            getattr(self, name).load_state_dict({k.split(".", 1)[1]: v for k, v in state.items() if k.startswith(name + ".")})
        self.temperature = float(self.config.get("temperature", 1.0))
        self.max_length = int(self.config.get("max_length", 8192))

    def encode(self, batch):
        return self.encoder(batch)

    def masks(self, embeds, attention_mask):
        """Bidirectional masks for the full-attention layers, padding-only for linear attention."""
        from transformers.masking_utils import create_bidirectional_mask, create_recurrent_attention_mask

        return {"full_attention": create_bidirectional_mask(config=self.text_config, inputs_embeds=embeds,
                                                            attention_mask=attention_mask),
                "linear_attention": create_recurrent_attention_mask(self.text_config, embeds, attention_mask)}

    def forward(self, input_ids, attention_mask, answer_pos, option_pos, option_mask, **_):
        """Option logits [questions, most options] (masked options are -1e4). Divide by
        self.temperature and softmax per question for calibrated probabilities."""
        with torch.autocast("cuda", dtype=torch.bfloat16, enabled=input_ids.is_cuda):
            if self.bidirectional:
                embeds = self.lm.get_input_embeddings()(input_ids)
                hidden = self.lm(inputs_embeds=embeds, attention_mask=self.masks(embeds, attention_mask)).logits
            else:
                hidden = self.lm(input_ids=input_ids, attention_mask=attention_mask).logits
        flat = hidden.reshape(-1, hidden.shape[-1]).float()
        query = self.query(self.norm(flat[answer_pos]))
        options = self.norm(flat[option_pos])
        logits = torch.einsum("qd,qmd->qm", query, self.key(options)) / math.sqrt(self.head_dim)
        logits = logits + self.prior(options).squeeze(-1)
        return logits.masked_fill(~option_mask, NEG)


def load_release_model(path, device="cuda", dtype=None, quantization=None):
    """Load the released model from a local folder (e.g. huggingface_hub.snapshot_download(...)).

    quantization: None (bf16 on GPU, float32 on CPU), "8bit" or "4bit" (bitsandbytes, CUDA only:
    about 2.5 GB or 1.8 GB of GPU memory instead of 4.5 GB).
    The tuned abstention threshold in decider_head_config.json is applied unless the
    DECIDER_ABSTAIN_THRESHOLD environment variable is set.
    """
    global ABSTAIN_THRESHOLD
    dtype = dtype or (torch.bfloat16 if str(device).startswith("cuda") else torch.float32)
    model = DeciderModel(path, dtype=dtype, quantization=quantization, device=device)
    model.head_device = device
    if "abstain_threshold" in model.config and "DECIDER_ABSTAIN_THRESHOLD" not in os.environ:
        ABSTAIN_THRESHOLD = float(model.config["abstain_threshold"])
    model.norm.float(); model.query.float(); model.key.float(); model.prior.float()
    if quantization:  # the backbone is already placed; move only the head
        for part in (model.norm, model.query, model.key, model.prior):
            part.to(device)
        return model.eval()
    return model.to(device).eval()


@torch.inference_mode()
def systemone(model, body, name="decider-2b"):
    """Answer one Jev/SystemOne request body; returns {"model", "answers", "usage"}.

    Questions that do not fit next to the full state in one pass are split across passes, each
    with the whole state; nothing is truncated.
    """
    validate_request(body)
    questions = body["questions"]
    state = request_state_text(body["state"], questions)
    rendered = items(questions)
    device = next(model.parameters()).device
    passes, state_tokens, sizes = plan(model.tokenizer, state, rendered, model.max_length)
    probabilities = [None] * len(rendered)
    for indices in passes:
        tensors = model.encode([{"state": state, "items": [rendered[i] for i in indices]}])
        logits = model(**{k: v.to(device) for k, v in tensors.items()}).float() / model.temperature
        for row, i in enumerate(indices):
            count = len(rendered[i]["labels"])
            probabilities[i] = logits[row, :count].softmax(-1).tolist()
    total = len(passes) * state_tokens + sum(sizes)
    return response(body.get("model") or name, questions, probabilities, total)