niqun123123 commited on
Commit
84612ff
·
verified ·
1 Parent(s): 0615ccb

Replace v1 autojev runtime with LemonDecider v2 package

Browse files
Files changed (3) hide show
  1. configuration_autojev.py +0 -32
  2. modeling_autojev.py +0 -86
  3. sft_receipt.json +0 -18
configuration_autojev.py DELETED
@@ -1,32 +0,0 @@
1
- """Configuration for a Qwen backbone with a dynamic-option decision head."""
2
- import math
3
- from transformers.models.qwen3_5.configuration_qwen3_5 import Qwen3_5Config
4
-
5
-
6
- class AutoJevConfig(Qwen3_5Config):
7
- model_type = "autojev_decision"
8
-
9
- def __init__(self, codes=None, token_ids=None, max_options=255, temperature=1.0,
10
- base_model="Qwen/Qwen3.8-27B", initialization_step=0,
11
- max_input_length=8192, **kwargs):
12
- super().__init__(**kwargs)
13
- if max_options != 255:
14
- raise ValueError("This artifact uses exactly 255 option positions")
15
- if not math.isfinite(temperature) or temperature <= 0:
16
- raise ValueError("temperature must be positive and finite")
17
- self.max_options = max_options
18
- self.codes = list(codes or [])
19
- self.token_ids = list(token_ids or [])
20
- if self.codes or self.token_ids:
21
- if len(self.codes) != max_options or len(set(self.codes)) != max_options:
22
- raise ValueError("Expected 255 unique answer codes")
23
- if len(self.token_ids) != max_options or len(set(self.token_ids)) != max_options:
24
- raise ValueError("Expected 255 unique answer token IDs")
25
- if any(type(i) is not int or not 0 <= i < self.text_config.vocab_size for i in self.token_ids):
26
- raise ValueError("Answer token IDs outside base vocabulary")
27
- self.temperature = float(temperature)
28
- self.base_model = base_model
29
- self.initialization_step = initialization_step
30
- self.max_input_length = int(max_input_length)
31
- if self.max_input_length < 1:
32
- raise ValueError("max_input_length must be positive")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modeling_autojev.py DELETED
@@ -1,86 +0,0 @@
1
- """AutoJev-style full-weight decision model. No autoregressive generation head.
2
-
3
- The checkpoint's backbone is copied byte-for-byte from Qwen, while readout rows
4
- are selected from its original LM head. T is used in postprocessing, not CE loss.
5
- """
6
- from dataclasses import dataclass
7
- import torch
8
- import torch.nn.functional as F
9
- from transformers.utils import ModelOutput
10
- from transformers.models.qwen3_5.modeling_qwen3_5 import Qwen3_5Model, Qwen3_5PreTrainedModel
11
- from .configuration_autojev import AutoJevConfig
12
-
13
-
14
- @dataclass
15
- class AutoJevOutput(ModelOutput):
16
- loss: torch.Tensor | None = None
17
- logits: torch.Tensor | None = None
18
-
19
-
20
- class AutoJevForDecisionClassification(Qwen3_5PreTrainedModel):
21
- config_class = AutoJevConfig
22
- base_model_prefix = "backbone"
23
-
24
- def __init__(self, config):
25
- super().__init__(config)
26
- self.backbone = Qwen3_5Model(config)
27
- self.readout = torch.nn.Linear(config.text_config.hidden_size, config.max_options, bias=False)
28
- self.post_init()
29
-
30
- def get_input_embeddings(self):
31
- return self.backbone.get_input_embeddings()
32
-
33
- def set_input_embeddings(self, value):
34
- self.backbone.set_input_embeddings(value)
35
-
36
- def forward(self, input_ids=None, attention_mask=None, option_counts=None,
37
- labels=None, return_dict=True, **kwargs):
38
- if input_ids is None or input_ids.ndim != 2 or input_ids.shape[1] == 0:
39
- raise ValueError("input_ids must be a nonempty [batch, length] tensor")
40
- if input_ids.shape[1] > self.config.max_input_length:
41
- raise ValueError("Input exceeds max_input_length; truncation is not allowed")
42
- if attention_mask is None:
43
- attention_mask = torch.ones_like(input_ids)
44
- if attention_mask.shape != input_ids.shape or not bool((attention_mask[:, -1] == 1).all()):
45
- raise ValueError("Left padding required: last prompt position must be valid")
46
- if option_counts is None:
47
- raise ValueError("option_counts is required for each input")
48
- counts = torch.as_tensor(option_counts, device=input_ids.device)
49
- if counts.dtype == torch.bool or counts.is_floating_point() or counts.shape != (input_ids.shape[0],):
50
- raise ValueError("option_counts must contain one integer per row")
51
- if not bool(((counts >= 1) & (counts <= self.config.max_options)).all()):
52
- raise ValueError("Each question must contain 1..255 options")
53
- if kwargs.pop("use_cache", False) or kwargs.get("past_key_values") is not None:
54
- raise ValueError("Decision forward does not accept KV-cache decoding")
55
- output = self.backbone(input_ids=input_ids, attention_mask=attention_mask,
56
- use_cache=False, return_dict=True, **kwargs)
57
- # Qwen3_5Model.last_hidden_state is AFTER language_model.norm (RMSNorm).
58
- hidden = output.last_hidden_state[:, -1, :]
59
- logits = self.readout(hidden).float()
60
- invalid = torch.arange(self.config.max_options, device=logits.device)[None] >= counts[:, None]
61
- logits = logits.masked_fill(invalid, -1e9)
62
- loss = None
63
- if labels is not None:
64
- labels = labels.to(logits.device)
65
- if labels.shape == (len(counts),):
66
- if labels.is_floating_point() or labels.dtype == torch.bool or not bool(((labels >= 0) & (labels < counts)).all()):
67
- raise ValueError("Hard targets must be valid option indices")
68
- loss = F.cross_entropy(logits, labels.long())
69
- elif labels.shape == logits.shape:
70
- target = labels.float()
71
- if not bool(torch.isfinite(target).all()) or bool((target < 0).any()):
72
- raise ValueError("Invalid soft targets")
73
- if not torch.allclose(target.sum(-1), torch.ones(len(counts), device=target.device), atol=1e-6, rtol=0):
74
- raise ValueError("Soft targets must sum to one")
75
- if bool((target.masked_select(invalid) != 0).any()):
76
- raise ValueError("Soft targets assign mass to invalid options")
77
- loss = -(target * F.log_softmax(logits, dim=-1)).sum(-1).mean()
78
- else:
79
- raise ValueError("labels must be [batch] or [batch,255]")
80
- if not return_dict:
81
- return (loss, logits) if loss is not None else (logits,)
82
- return AutoJevOutput(loss=loss, logits=logits)
83
-
84
-
85
- AutoJevConfig.register_for_auto_class()
86
- AutoJevForDecisionClassification.register_for_auto_class("AutoModel")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
sft_receipt.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "step": 24,
3
- "dev_accuracy_t1": 0.7735191583633423,
4
- "best_step": 3,
5
- "best_dev_accuracy_t1": 0.7804877758026123,
6
- "lr": 2.2827515498423204e-07,
7
- "examples_seen": 6144,
8
- "temperature_fit": {
9
- "method": "NLL scan on dev 574 under fork _known() semantics, T grid [0.30,5.00]x0.05 (from cached T=1 probs)",
10
- "best_T": 0.6,
11
- "dev_nll_at_T": 0.56265,
12
- "dev_brier_at_T": 0.28261,
13
- "dev_nll_at_1": 0.6016,
14
- "dev_brier_at_1": 0.29885,
15
- "bound": false,
16
- "reason": "best_T=0.60 != serving T=1.0; NOT applied — public-set re-eval required before adoption (dev acc unchanged at T*, argmax-invariant except noul boundary)"
17
- }
18
- }