niqun123123 commited on
Commit
3c1aeab
·
verified ·
1 Parent(s): 1adc3a9

Upload configuration_lemondecider.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. configuration_lemondecider.py +171 -0
configuration_lemondecider.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration for a Qwen or Llama backbone with a dynamic-option decision head."""
2
+ import math
3
+ from transformers.configuration_utils import PreTrainedConfig
4
+ from transformers.models.llama.configuration_llama import LlamaConfig
5
+ from transformers.models.qwen3_5.configuration_qwen3_5 import Qwen3_5Config
6
+
7
+
8
+ _LLAMA_KEYS = {
9
+ "vocab_size", "hidden_size", "intermediate_size", "num_hidden_layers",
10
+ "num_attention_heads", "num_key_value_heads", "hidden_act",
11
+ "max_position_embeddings", "initializer_range", "rms_norm_eps", "use_cache",
12
+ "pad_token_id", "bos_token_id", "eos_token_id", "pretraining_tp",
13
+ "tie_word_embeddings", "rope_parameters", "rope_scaling", "rope_theta",
14
+ "attention_bias", "attention_dropout", "mlp_bias", "head_dim",
15
+ }
16
+
17
+
18
+ def _apply_decision_fields(obj, *, max_options, code_scheme, temperature, codes, token_ids,
19
+ base_model, initialization_step, max_input_length, vocab_size,
20
+ attention_mode="causal", pooling="last"):
21
+ if type(max_options) is not int or not 1 <= max_options <= 255:
22
+ raise ValueError("max_options must be an integer in 1..255")
23
+ if code_scheme not in ("letters-v1", "number30-v1"):
24
+ raise ValueError(f"Unknown answer code scheme: {code_scheme}")
25
+ if code_scheme == "number30-v1" and max_options != 30:
26
+ raise ValueError("number30-v1 requires exactly 30 option positions")
27
+ if not math.isfinite(temperature) or temperature <= 0:
28
+ raise ValueError("temperature must be positive and finite")
29
+ if attention_mode not in ("causal", "noncausal_full_attention"):
30
+ raise ValueError(f"Unknown attention mode: {attention_mode}")
31
+ if pooling not in ("last",):
32
+ raise ValueError(f"Unknown pooling mode: {pooling}")
33
+ codes = list(codes or [])
34
+ token_ids = list(token_ids or [])
35
+ if codes or token_ids:
36
+ if len(codes) != max_options or len(set(codes)) != max_options:
37
+ raise ValueError(f"Expected {max_options} unique answer codes")
38
+ if len(token_ids) != max_options or len(set(token_ids)) != max_options:
39
+ raise ValueError(f"Expected {max_options} unique answer token IDs")
40
+ if any(type(i) is not int or not 0 <= i < vocab_size for i in token_ids):
41
+ raise ValueError("Answer token IDs outside base vocabulary")
42
+ max_input_length = int(max_input_length)
43
+ if max_input_length < 1:
44
+ raise ValueError("max_input_length must be positive")
45
+ obj.code_scheme = code_scheme
46
+ obj.max_options = max_options
47
+ obj.codes = codes
48
+ obj.token_ids = token_ids
49
+ obj.temperature = float(temperature)
50
+ obj.base_model = base_model
51
+ obj.initialization_step = initialization_step
52
+ obj.max_input_length = max_input_length
53
+ obj.attention_mode = attention_mode
54
+ obj.pooling = pooling
55
+
56
+
57
+ def _llama_requested(backbone_type, llama_config, kwargs):
58
+ if backbone_type == "llama" or llama_config is not None:
59
+ return True
60
+ if backbone_type in ("qwen3_5",):
61
+ return False
62
+ if kwargs.get("text_config") is not None or kwargs.get("vision_config") is not None:
63
+ return False
64
+ return False
65
+
66
+
67
+ def _llama_from_kwargs(llama_config, kwargs):
68
+ llama_kwargs = dict(llama_config or {})
69
+ llama_kwargs.update({k: kwargs.pop(k) for k in list(kwargs) if k in _LLAMA_KEYS})
70
+ llama_kwargs.pop("model_type", None)
71
+ llama_kwargs.pop("architectures", None)
72
+ if llama_kwargs.get("rope_scaling") is None:
73
+ llama_kwargs.pop("rope_scaling", None)
74
+ if "rope_theta" in llama_kwargs and "rope_parameters" not in llama_kwargs:
75
+ llama_kwargs["rope_parameters"] = {"rope_theta": llama_kwargs.pop("rope_theta"), "rope_type": "default"}
76
+ return LlamaConfig(**llama_kwargs)
77
+
78
+
79
+ class LemonDeciderConfig(Qwen3_5Config):
80
+ model_type = "lemondecider_decision"
81
+
82
+ def __init__(self, codes=None, token_ids=None, max_options=255, temperature=1.0,
83
+ base_model="Qwen/Qwen3.8-27B", initialization_step=0,
84
+ max_input_length=8192, code_scheme="letters-v1",
85
+ backbone_type=None, llama_config=None,
86
+ attention_mode="causal", pooling="last", decision_protocol="autojev-v1", **kwargs):
87
+ # auto_map is the serialized trust_remote_code contract of every published
88
+ # checkpoint: the serving/eval stack reloads exported configs via AutoModel.
89
+ # Stash instead of dropping it, then re-attach after the base constructors
90
+ # (which do not accept it on this fork of Llama/Qwen config init paths).
91
+ auto_map = kwargs.pop("auto_map", None)
92
+ project_name = kwargs.pop("project_name", None)
93
+ model_id = kwargs.pop("model_id", None)
94
+ attention_mode = kwargs.pop("attention_mode", attention_mode)
95
+ pooling = kwargs.pop("pooling", pooling)
96
+ if "torch_dtype" in kwargs and "dtype" not in kwargs:
97
+ kwargs["dtype"] = kwargs.pop("torch_dtype")
98
+ llama_mode = _llama_requested(backbone_type, llama_config, kwargs)
99
+ if llama_mode:
100
+ if attention_mode != "causal":
101
+ raise ValueError("noncausal_full_attention is only implemented for the Qwen3.5 hybrid backbone")
102
+ inner = _llama_from_kwargs(llama_config, kwargs)
103
+ kwargs.pop("text_config", None)
104
+ kwargs.pop("vision_config", None)
105
+ PreTrainedConfig.__init__(self, **kwargs)
106
+ object.__setattr__(self, "backbone_type", "llama")
107
+ object.__setattr__(self, "llama_config", inner)
108
+ vocab_size = inner.vocab_size
109
+ else:
110
+ kwargs.pop("llama_config", None)
111
+ super().__init__(**kwargs)
112
+ object.__setattr__(self, "backbone_type", "qwen3_5")
113
+ object.__setattr__(self, "llama_config", None)
114
+ vocab_size = super().__getattribute__("text_config").vocab_size
115
+ _apply_decision_fields(
116
+ self, max_options=max_options, code_scheme=code_scheme, temperature=temperature,
117
+ codes=codes, token_ids=token_ids, base_model=base_model,
118
+ initialization_step=initialization_step, max_input_length=max_input_length,
119
+ vocab_size=vocab_size, attention_mode=attention_mode, pooling=pooling,
120
+ )
121
+ if decision_protocol not in ('autojev-v1', 'lemondecider-v1'):
122
+ raise ValueError('Unknown decision protocol')
123
+ if decision_protocol == 'lemondecider-v1' and (self.backbone_type != 'qwen3_5' or max_options != 255
124
+ or code_scheme != 'letters-v1' or attention_mode != 'noncausal_full_attention'):
125
+ raise ValueError('LemonDecider requires Qwen3.5-family, 255 letter codes and noncausal full attention')
126
+ self.decision_protocol = decision_protocol
127
+ self._sync_text_causality()
128
+ if auto_map is not None:
129
+ self.auto_map = auto_map
130
+ if project_name is not None:
131
+ self.project_name = project_name
132
+ if model_id is not None:
133
+ self.model_id = model_id
134
+
135
+ def __getattribute__(self, name):
136
+ if name == "text_config":
137
+ data = object.__getattribute__(self, "__dict__")
138
+ if data.get("backbone_type") == "llama":
139
+ return data["llama_config"]
140
+ return super().__getattribute__(name)
141
+
142
+ @property
143
+ def inner_backbone_config(self):
144
+ if getattr(self, "backbone_type", "qwen3_5") == "llama":
145
+ return self.llama_config
146
+ return self
147
+
148
+ def _sync_text_causality(self):
149
+ """Qwen3.5 full-attention reads is_causal from the nested text config."""
150
+ if getattr(self, "backbone_type", "qwen3_5") != "qwen3_5":
151
+ return
152
+ text = super().__getattribute__("text_config")
153
+ text.is_causal = self.attention_mode == "causal"
154
+
155
+ def to_dict(self):
156
+ if getattr(self, "backbone_type", "qwen3_5") == "llama":
157
+ output = PreTrainedConfig.to_dict(self)
158
+ output["backbone_type"] = "llama"
159
+ output["llama_config"] = self.llama_config.to_dict()
160
+ output.pop("text_config", None)
161
+ output.pop("vision_config", None)
162
+ return output
163
+ output = super().to_dict()
164
+ output["backbone_type"] = "qwen3_5"
165
+ output.pop("llama_config", None)
166
+ output["attention_mode"] = getattr(self, "attention_mode", "causal")
167
+ output["pooling"] = getattr(self, "pooling", "last")
168
+ text = output.get("text_config")
169
+ if isinstance(text, dict):
170
+ text["is_causal"] = output["attention_mode"] == "causal"
171
+ return output