yue-maincode commited on
Commit
862bb5d
·
verified ·
1 Parent(s): a567b4d

Remote code revision 2: generate() honours max_length / stopping_criteria / logits_processor and the other standard transformers arguments (revision 1 always produced 128 new tokens, truncating CoT under lm-eval); tie_weights() is a no-op at the top level; card documents the change. Weights unchanged.

Browse files
Files changed (3) hide show
  1. README.md +10 -6
  2. configuration_platypus.py +8 -1
  3. modeling_platypus.py +181 -24
README.md CHANGED
@@ -12,9 +12,6 @@ tags:
12
  - qwen3
13
  - base-model
14
  ---
15
-
16
- ![hf-banner-dark-1920x768](https://cdn-uploads.huggingface.co/production/uploads/6aa9440959f763ca569102fb/7qbqokPMFuEwqW6vhMvdX.png)
17
-
18
  # Matilda Platypus 11B (base)
19
 
20
  **Any size you want.** Matilda Platypus is a family of intermediate-size language models built by connecting the lower
@@ -79,7 +76,7 @@ import torch
79
  from transformers import AutoModelForCausalLM, AutoTokenizer
80
 
81
  repo = "Maincode/Matilda-Platypus-11B-Base"
82
- tok = AutoTokenizer.from_pretrained(repo)
83
  model = AutoModelForCausalLM.from_pretrained(repo, trust_remote_code=True, dtype=torch.bfloat16).cuda()
84
  inputs = tok("The capital of Australia is", return_tensors="pt").to("cuda")
85
  out = model.generate(**inputs, max_new_tokens=32)
@@ -88,8 +85,15 @@ print(tok.decode(out[0], skip_special_tokens=True))
88
 
89
  The remote code loads the lower block from `Qwen/Qwen3-14B-Base`, the upper
90
  block from `upper_block/` and the bridge from `bridge.safetensors`, truncates both parents to the retained layers and
91
- runs them through their standard `transformers` forward passes with one KV cache per block. `generate` supports greedy
92
- decoding and nucleus sampling (`do_sample`, `temperature`, `top_p`). Requires `transformers >= 4.56` (Qwen3 support).
 
 
 
 
 
 
 
93
 
94
  ## Limitations
95
 
 
12
  - qwen3
13
  - base-model
14
  ---
 
 
 
15
  # Matilda Platypus 11B (base)
16
 
17
  **Any size you want.** Matilda Platypus is a family of intermediate-size language models built by connecting the lower
 
76
  from transformers import AutoModelForCausalLM, AutoTokenizer
77
 
78
  repo = "Maincode/Matilda-Platypus-11B-Base"
79
+ tok = AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
80
  model = AutoModelForCausalLM.from_pretrained(repo, trust_remote_code=True, dtype=torch.bfloat16).cuda()
81
  inputs = tok("The capital of Australia is", return_tensors="pt").to("cuda")
82
  out = model.generate(**inputs, max_new_tokens=32)
 
85
 
86
  The remote code loads the lower block from `Qwen/Qwen3-14B-Base`, the upper
87
  block from `upper_block/` and the bridge from `bridge.safetensors`, truncates both parents to the retained layers and
88
+ runs them through their standard `transformers` forward passes with one KV cache per block. `generate` follows the
89
+ standard `transformers` keyword arguments (`max_new_tokens` / `max_length`, `min_new_tokens`, `stopping_criteria`,
90
+ `logits_processor`, `do_sample`, `temperature`, `top_k`, `top_p`, `repetition_penalty`, `eos_token_id`, `pad_token_id`,
91
+ `streamer`), so the model runs unchanged under lm-eval-harness (`--model hf --model_args pretrained=Maincode/Matilda-Platypus-11B-Base,trust_remote_code=True`).
92
+ Greedy and sampled decoding only; beam search raises `NotImplementedError`. Requires `transformers >= 4.56` (tested on 4.56 and 5.x).
93
+
94
+ Remote-code revision 2 (2026-10-31): revision 1 ignored `max_length` and `stopping_criteria` and always produced 128 new
95
+ tokens, which truncated chain-of-thought answers under lm-eval and under-reported generative benchmarks (GSM8K read ~0.58
96
+ instead of the table value); `tie_weights()` is now a no-op at the top level. Model weights are unchanged.
97
 
98
  ## Limitations
99
 
configuration_platypus.py CHANGED
@@ -9,7 +9,8 @@ class MatildaPlatypusConfig(PretrainedConfig):
9
 
10
  def __init__(self, lower_model="Qwen/Qwen3-8B-Base", lower_layers=25, upper_model="upper_block",
11
  upper_start_layer=25, upper_layers=11, bridge_file="bridge.safetensors",
12
- lower_hidden_size=4096, upper_hidden_size=2560, vocab_size=151936, **kwargs):
 
13
  self.lower_model = lower_model # hub id, or a sub-folder of this repo
14
  self.lower_layers = lower_layers # k: decoder layers kept from the larger parent (layers 1..k)
15
  self.upper_model = upper_model # sub-folder holding the adapted smaller parent (HF checkpoint)
@@ -19,4 +20,10 @@ class MatildaPlatypusConfig(PretrainedConfig):
19
  self.lower_hidden_size = lower_hidden_size
20
  self.upper_hidden_size = upper_hidden_size
21
  self.vocab_size = vocab_size
 
 
 
 
 
 
22
  super().__init__(**kwargs)
 
9
 
10
  def __init__(self, lower_model="Qwen/Qwen3-8B-Base", lower_layers=25, upper_model="upper_block",
11
  upper_start_layer=25, upper_layers=11, bridge_file="bridge.safetensors",
12
+ lower_hidden_size=4096, upper_hidden_size=2560, vocab_size=151936,
13
+ max_position_embeddings=None, **kwargs):
14
  self.lower_model = lower_model # hub id, or a sub-folder of this repo
15
  self.lower_layers = lower_layers # k: decoder layers kept from the larger parent (layers 1..k)
16
  self.upper_model = upper_model # sub-folder holding the adapted smaller parent (HF checkpoint)
 
20
  self.lower_hidden_size = lower_hidden_size
21
  self.upper_hidden_size = upper_hidden_size
22
  self.vocab_size = vocab_size
23
+ # context length; filled in from the parents at load time when not given (harnesses read it)
24
+ self.max_position_embeddings = max_position_embeddings
25
+ # The lower block's embedding (d_lower) and the upper block's output head (d_upper) differ in width and are
26
+ # never tied; PretrainedConfig would otherwise default this to True and generic tie_weights() calls would
27
+ # try to tie them.
28
+ kwargs.setdefault("tie_word_embeddings", False)
29
  super().__init__(**kwargs)
modeling_platypus.py CHANGED
@@ -2,18 +2,30 @@
2
 
3
  Self-contained: the two blocks are ordinary Hugging Face Qwen3 checkpoints run through their public forward passes
4
  (the lower one truncated to its first k layers with its final norm removed, the upper one starting at layer j with
5
- `inputs_embeds`), so no custom kernels are involved. `generate` keeps one KV cache per block.
 
 
 
 
6
 
7
  from transformers import AutoModelForCausalLM, AutoTokenizer
8
- tok = AutoTokenizer.from_pretrained("maincode/matilda-platypus-7b-base")
9
- model = AutoModelForCausalLM.from_pretrained("maincode/matilda-platypus-7b-base", trust_remote_code=True,
10
  dtype=torch.bfloat16).cuda()
11
  out = model.generate(**tok("The capital of Australia is", return_tensors="pt").to("cuda"), max_new_tokens=32)
 
 
 
 
 
 
 
12
  """
13
  from __future__ import annotations
14
 
15
  import os
16
- from typing import Optional, Tuple
 
17
 
18
  import torch
19
  import torch.nn as nn
@@ -24,6 +36,22 @@ from transformers.modeling_outputs import CausalLMOutputWithPast
24
 
25
  from .configuration_platypus import MatildaPlatypusConfig
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  class RepresentationBridge(nn.Module):
29
  """y = W x + b on the residual stream, computed in float32 (W: [d_upper, d_lower])."""
@@ -39,13 +67,19 @@ class RepresentationBridge(nn.Module):
39
 
40
  class MatildaPlatypusForCausalLM(PreTrainedModel):
41
  config_class = MatildaPlatypusConfig
 
42
  _supports_cache_class = True
 
43
 
44
  def __init__(self, config: MatildaPlatypusConfig, lower: Optional[PreTrainedModel] = None,
45
  upper: Optional[PreTrainedModel] = None, bridge: Optional[RepresentationBridge] = None):
46
  super().__init__(config)
47
  self.lower, self.upper, self.bridge = lower, upper, bridge
48
 
 
 
 
 
49
  # ------------------------------------------------------------------ loading
50
  @classmethod
51
  def from_pretrained(cls, pretrained_model_name_or_path, *args, dtype=None, torch_dtype=None, token=None,
@@ -83,11 +117,27 @@ class MatildaPlatypusForCausalLM(PreTrainedModel):
83
  bridge.proj.weight.data.copy_(t["W"].float()); bridge.proj.bias.data.copy_(t["b"].float())
84
  for p in lower.parameters():
85
  p.requires_grad_(False)
 
 
 
 
 
 
86
  model = cls(config, lower, upper, bridge).eval()
87
  if device_map is not None and isinstance(device_map, (str, torch.device)) and device_map != "auto":
88
  model.to(device_map)
89
  return model
90
 
 
 
 
 
 
 
 
 
 
 
91
  # ------------------------------------------------------------------ forward
92
  @property
93
  def dtype(self) -> torch.dtype:
@@ -112,42 +162,149 @@ class MatildaPlatypusForCausalLM(PreTrainedModel):
112
  return CausalLMOutputWithPast(logits=logits, past_key_values=(cl, cu) if use_cache else None)
113
 
114
  # ------------------------------------------------------------------ generation
 
 
 
 
 
115
  @torch.no_grad()
116
- def generate(self, input_ids: torch.LongTensor, attention_mask: Optional[torch.Tensor] = None,
117
- max_new_tokens: int = 128, do_sample: bool = False, temperature: float = 1.0, top_p: float = 1.0,
118
- eos_token_id: Optional[int] = None, pad_token_id: Optional[int] = None, **kwargs) -> torch.LongTensor:
119
- """Greedy or nucleus sampling with KV caches for both blocks; stops when every row has produced EOS."""
120
- if eos_token_id is None:
121
- eos_token_id = getattr(self.upper.generation_config, "eos_token_id", None) or self.upper.config.eos_token_id
122
- if isinstance(eos_token_id, (list, tuple)):
123
- eos_token_id = eos_token_id[0]
124
- if pad_token_id is None:
125
- pad_token_id = getattr(self.upper.config, "pad_token_id", None) or eos_token_id
126
- device = input_ids.device
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  if attention_mask is None:
128
  attention_mask = torch.ones_like(input_ids)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  out = self.forward(input_ids, attention_mask=attention_mask, use_cache=True)
130
  caches = out.past_key_values
131
  seq = input_ids
132
- done = torch.zeros(input_ids.shape[0], dtype=torch.bool, device=device)
133
- for _ in range(max_new_tokens):
134
  logits = out.logits[:, -1, :].float()
135
- if do_sample:
136
- logits = logits / max(temperature, 1e-5)
137
- if top_p < 1.0:
 
 
 
 
 
 
 
 
 
 
 
138
  sorted_logits, idx = torch.sort(logits, descending=True)
139
  probs = torch.softmax(sorted_logits, dim=-1)
140
- keep = probs.cumsum(-1) - probs < top_p
141
  sorted_logits[~keep] = float("-inf")
142
  logits = torch.full_like(logits, float("-inf")).scatter(1, idx, sorted_logits)
143
  nxt = torch.multinomial(torch.softmax(logits, dim=-1), 1).squeeze(1)
144
  else:
145
  nxt = logits.argmax(-1)
146
- nxt = torch.where(done, torch.full_like(nxt, pad_token_id), nxt)
147
  seq = torch.cat([seq, nxt[:, None]], dim=1)
148
  attention_mask = torch.cat([attention_mask, torch.ones_like(nxt[:, None])], dim=1)
149
- done |= nxt == eos_token_id
 
 
 
 
 
 
 
150
  if bool(done.all()):
151
  break
152
  out = self.forward(nxt[:, None], attention_mask=attention_mask, past_key_values=caches, use_cache=True)
153
- return seq
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  Self-contained: the two blocks are ordinary Hugging Face Qwen3 checkpoints run through their public forward passes
4
  (the lower one truncated to its first k layers with its final norm removed, the upper one starting at layer j with
5
+ `inputs_embeds`), so no custom kernels are involved. `generate` keeps one KV cache per block and follows the standard
6
+ `transformers` keyword arguments (`max_new_tokens` / `max_length`, `stopping_criteria`, `logits_processor`, sampling
7
+ knobs, `eos_token_id` / `pad_token_id`, `streamer`), so it runs unchanged under evaluation harnesses such as
8
+ lm-eval-harness (`--model hf --model_args pretrained=...,trust_remote_code=True`). Greedy and sampling only; beam
9
+ search is not implemented and raises.
10
 
11
  from transformers import AutoModelForCausalLM, AutoTokenizer
12
+ tok = AutoTokenizer.from_pretrained("Maincode/Matilda-Platypus-7B-Base")
13
+ model = AutoModelForCausalLM.from_pretrained("Maincode/Matilda-Platypus-7B-Base", trust_remote_code=True,
14
  dtype=torch.bfloat16).cuda()
15
  out = model.generate(**tok("The capital of Australia is", return_tensors="pt").to("cuda"), max_new_tokens=32)
16
+
17
+ Remote-code revision 2 (2026-10-31): `generate` honours `max_length`, `stopping_criteria`, `logits_processor`,
18
+ `min_new_tokens`, `top_k`, `repetition_penalty`, list-valued `eos_token_id`, `generation_config` and `streamer`, and
19
+ warns instead of silently ignoring unknown arguments; `tie_weights()` is a no-op at the top level (the lower block's
20
+ 4096-d embedding and the upper block's 2560-d head must never be tied, and each parent was already tied on load).
21
+ Revision 1 ignored `max_length` and `stopping_criteria` (it always produced its default of 128 new tokens), which
22
+ truncated chain-of-thought answers under lm-eval and under-reported generative benchmarks.
23
  """
24
  from __future__ import annotations
25
 
26
  import os
27
+ import warnings
28
+ from typing import Optional, Sequence, Tuple, Union
29
 
30
  import torch
31
  import torch.nn as nn
 
36
 
37
  from .configuration_platypus import MatildaPlatypusConfig
38
 
39
+ REMOTE_CODE_REVISION = 2
40
+ _DEFAULT_NEW_TOKENS = 128 # used only when neither max_new_tokens, max_length nor a generation_config gives a budget
41
+
42
+ # generate() arguments that would change the result if ignored -> refuse loudly instead of pretending
43
+ _UNSUPPORTED_GENERATE_KWARGS = ("prefix_allowed_tokens_fn", "bad_words_ids", "force_words_ids", "suppress_tokens",
44
+ "begin_suppress_tokens", "forced_bos_token_id", "forced_eos_token_id", "constraints",
45
+ "assistant_model", "guidance_scale", "penalty_alpha", "num_beam_groups",
46
+ "diversity_penalty", "exponential_decay_length_penalty", "sequence_bias",
47
+ "no_repeat_ngram_size", "encoder_repetition_penalty", "typical_p", "epsilon_cutoff",
48
+ "eta_cutoff", "renormalize_logits", "token_healing", "dola_layers", "watermarking_config")
49
+ # generate() arguments that are safe to accept and ignore
50
+ _IGNORED_GENERATE_KWARGS = ("use_cache", "synced_gpus", "output_attentions", "output_hidden_states", "output_scores",
51
+ "output_logits", "return_legacy_cache", "cache_implementation", "cache_config",
52
+ "compile_config", "disable_compile", "negative_prompt_ids", "negative_prompt_attention_mask",
53
+ "kwargs", "tokenizer", "position_ids", "cache_position", "token_type_ids")
54
+
55
 
56
  class RepresentationBridge(nn.Module):
57
  """y = W x + b on the residual stream, computed in float32 (W: [d_upper, d_lower])."""
 
67
 
68
  class MatildaPlatypusForCausalLM(PreTrainedModel):
69
  config_class = MatildaPlatypusConfig
70
+ main_input_name = "input_ids"
71
  _supports_cache_class = True
72
+ _tied_weights_keys = None # nothing is tied across the two blocks (see tie_weights)
73
 
74
  def __init__(self, config: MatildaPlatypusConfig, lower: Optional[PreTrainedModel] = None,
75
  upper: Optional[PreTrainedModel] = None, bridge: Optional[RepresentationBridge] = None):
76
  super().__init__(config)
77
  self.lower, self.upper, self.bridge = lower, upper, bridge
78
 
79
+ @classmethod
80
+ def can_generate(cls) -> bool: # text-generation pipelines ask this before calling .generate()
81
+ return True
82
+
83
  # ------------------------------------------------------------------ loading
84
  @classmethod
85
  def from_pretrained(cls, pretrained_model_name_or_path, *args, dtype=None, torch_dtype=None, token=None,
 
117
  bridge.proj.weight.data.copy_(t["W"].float()); bridge.proj.bias.data.copy_(t["b"].float())
118
  for p in lower.parameters():
119
  p.requires_grad_(False)
120
+ # context length = the shorter of the two parents (harnesses read this to size their prompts)
121
+ mp = [getattr(c, "max_position_embeddings", None) for c in (lower.config, upper.config)]
122
+ mp = [x for x in mp if isinstance(x, int)]
123
+ if mp and getattr(config, "max_position_embeddings", None) is None:
124
+ config.max_position_embeddings = min(mp)
125
+ config.tie_word_embeddings = False
126
  model = cls(config, lower, upper, bridge).eval()
127
  if device_map is not None and isinstance(device_map, (str, torch.device)) and device_map != "auto":
128
  model.to(device_map)
129
  return model
130
 
131
+ # ------------------------------------------------------------------ weight tying: never across blocks
132
+ def tie_weights(self, *args, **kwargs) -> None:
133
+ """No-op. The lower block's input embedding (d_lower) and the upper block's output head (d_upper) have
134
+ different widths and must never be tied; each parent block was already tied (if its config says so) when
135
+ it was loaded, and the upper block's token embedding has since been replaced, so re-tying would fail."""
136
+ return None
137
+
138
+ def tie_embeddings_and_encoder_decoder(self) -> None: # transformers 4.x entry point
139
+ return None
140
+
141
  # ------------------------------------------------------------------ forward
142
  @property
143
  def dtype(self) -> torch.dtype:
 
162
  return CausalLMOutputWithPast(logits=logits, past_key_values=(cl, cu) if use_cache else None)
163
 
164
  # ------------------------------------------------------------------ generation
165
+ def _default_eos(self) -> Optional[Union[int, Sequence[int]]]:
166
+ gc = getattr(self.upper, "generation_config", None)
167
+ eos = getattr(gc, "eos_token_id", None) if gc is not None else None
168
+ return eos if eos is not None else getattr(self.upper.config, "eos_token_id", None)
169
+
170
  @torch.no_grad()
171
+ def generate(self, input_ids: Optional[torch.LongTensor] = None, attention_mask: Optional[torch.Tensor] = None, *,
172
+ inputs: Optional[torch.LongTensor] = None, generation_config=None,
173
+ max_new_tokens: Optional[int] = None, max_length: Optional[int] = None,
174
+ min_new_tokens: Optional[int] = None, do_sample: Optional[bool] = None,
175
+ temperature: Optional[float] = None, top_k: Optional[int] = None, top_p: Optional[float] = None,
176
+ repetition_penalty: Optional[float] = None,
177
+ eos_token_id: Optional[Union[int, Sequence[int]]] = None, pad_token_id: Optional[int] = None,
178
+ stopping_criteria=None, logits_processor=None, streamer=None,
179
+ num_beams: int = 1, num_return_sequences: int = 1, return_dict_in_generate: bool = False,
180
+ **kwargs) -> torch.LongTensor:
181
+ """Greedy or sampled decoding with one KV cache per block, following the `transformers.generate` contract.
182
+
183
+ Budget: `max_new_tokens` > `max_length` (total length, prompt included) > `generation_config.max_new_tokens`
184
+ > 128. A row stops at any `eos_token_id` (int or list), when `stopping_criteria` says so, or at the budget;
185
+ finished rows are padded with `pad_token_id`. `logits_processor` (a `LogitsProcessorList`) is applied before
186
+ sampling. Beam search and `num_return_sequences > 1` are not implemented.
187
+ """
188
+ if input_ids is None:
189
+ input_ids = inputs
190
+ if input_ids is None:
191
+ raise ValueError("generate() needs `input_ids` (or `inputs`)")
192
+ if num_beams != 1 or num_return_sequences != 1:
193
+ raise NotImplementedError("Matilda Platypus implements greedy and sampled decoding only "
194
+ "(num_beams=1, num_return_sequences=1)")
195
+ bad = [k for k in _UNSUPPORTED_GENERATE_KWARGS if kwargs.get(k) not in (None, False, [], 1.0, 0)]
196
+ if bad:
197
+ raise NotImplementedError(f"generate() arguments not supported by Matilda Platypus: {bad}")
198
+ unknown = sorted(k for k in kwargs if k not in _UNSUPPORTED_GENERATE_KWARGS and k not in _IGNORED_GENERATE_KWARGS)
199
+ if unknown:
200
+ warnings.warn(f"MatildaPlatypusForCausalLM.generate() is ignoring unrecognised arguments: {unknown}",
201
+ stacklevel=2)
202
+ gc = generation_config
203
+
204
+ def pick(name, value, default):
205
+ if value is not None:
206
+ return value
207
+ v = getattr(gc, name, None) if gc is not None else None
208
+ return default if v is None else v
209
+
210
+ device = self.device
211
+ input_ids = input_ids.to(device)
212
+ batch, prompt_len = input_ids.shape
213
  if attention_mask is None:
214
  attention_mask = torch.ones_like(input_ids)
215
+ attention_mask = attention_mask.to(device)
216
+
217
+ # ---- budget
218
+ if max_new_tokens is None and max_length is not None:
219
+ budget = int(max_length) - prompt_len
220
+ else:
221
+ if max_new_tokens is not None and max_length is not None:
222
+ warnings.warn("Both `max_new_tokens` and `max_length` were given; `max_new_tokens` takes precedence.",
223
+ stacklevel=2)
224
+ budget = pick("max_new_tokens", max_new_tokens, None)
225
+ if budget is None:
226
+ budget = _DEFAULT_NEW_TOKENS
227
+ budget = int(budget)
228
+ if budget <= 0:
229
+ warnings.warn(f"generate(): the prompt ({prompt_len} tokens) already fills the requested length; "
230
+ "returning the prompt unchanged.", stacklevel=2)
231
+ return self._wrap(input_ids, return_dict_in_generate)
232
+ min_new = int(pick("min_new_tokens", min_new_tokens, 0) or 0)
233
+
234
+ # ---- special tokens
235
+ eos = pick("eos_token_id", eos_token_id, None)
236
+ if eos is None:
237
+ eos = self._default_eos()
238
+ eos_list = [int(e) for e in (eos if isinstance(eos, (list, tuple)) else ([] if eos is None else [eos]))]
239
+ eos_t = torch.tensor(eos_list, device=device, dtype=input_ids.dtype) if eos_list else None
240
+ pad = pick("pad_token_id", pad_token_id, None)
241
+ if pad is None:
242
+ pad = getattr(self.upper.config, "pad_token_id", None)
243
+ if pad is None:
244
+ pad = eos_list[0] if eos_list else 0
245
+ pad = int(pad)
246
+
247
+ # ---- sampling knobs (greedy unless do_sample)
248
+ sample = bool(pick("do_sample", do_sample, False))
249
+ temp = float(pick("temperature", temperature, 1.0))
250
+ tk = pick("top_k", top_k, None)
251
+ tp = float(pick("top_p", top_p, 1.0))
252
+ rep = float(pick("repetition_penalty", repetition_penalty, 1.0))
253
+
254
+ if streamer is not None and batch == 1:
255
+ streamer.put(input_ids.cpu())
256
  out = self.forward(input_ids, attention_mask=attention_mask, use_cache=True)
257
  caches = out.past_key_values
258
  seq = input_ids
259
+ done = torch.zeros(batch, dtype=torch.bool, device=device)
260
+ for step in range(budget):
261
  logits = out.logits[:, -1, :].float()
262
+ if rep != 1.0:
263
+ prev = torch.gather(logits, 1, seq)
264
+ prev = torch.where(prev < 0, prev * rep, prev / rep)
265
+ logits = logits.scatter(1, seq, prev)
266
+ if logits_processor is not None:
267
+ logits = logits_processor(seq, logits)
268
+ if step < min_new and eos_t is not None:
269
+ logits[:, eos_t] = float("-inf")
270
+ if sample:
271
+ logits = logits / max(temp, 1e-5)
272
+ if tk is not None and 0 < int(tk) < logits.shape[-1]:
273
+ kth = torch.topk(logits, int(tk), dim=-1).values[:, -1, None]
274
+ logits = logits.masked_fill(logits < kth, float("-inf"))
275
+ if tp < 1.0:
276
  sorted_logits, idx = torch.sort(logits, descending=True)
277
  probs = torch.softmax(sorted_logits, dim=-1)
278
+ keep = probs.cumsum(-1) - probs < tp
279
  sorted_logits[~keep] = float("-inf")
280
  logits = torch.full_like(logits, float("-inf")).scatter(1, idx, sorted_logits)
281
  nxt = torch.multinomial(torch.softmax(logits, dim=-1), 1).squeeze(1)
282
  else:
283
  nxt = logits.argmax(-1)
284
+ nxt = torch.where(done, torch.full_like(nxt, pad), nxt)
285
  seq = torch.cat([seq, nxt[:, None]], dim=1)
286
  attention_mask = torch.cat([attention_mask, torch.ones_like(nxt[:, None])], dim=1)
287
+ if streamer is not None and batch == 1:
288
+ streamer.put(nxt.cpu())
289
+ if eos_t is not None:
290
+ done |= torch.isin(nxt, eos_t)
291
+ if stopping_criteria is not None:
292
+ flag = stopping_criteria(seq, logits)
293
+ flag = torch.as_tensor(flag, device=device).to(torch.bool)
294
+ done |= flag if flag.dim() else flag.expand(batch)
295
  if bool(done.all()):
296
  break
297
  out = self.forward(nxt[:, None], attention_mask=attention_mask, past_key_values=caches, use_cache=True)
298
+ if streamer is not None:
299
+ streamer.end()
300
+ return self._wrap(seq, return_dict_in_generate)
301
+
302
+ @staticmethod
303
+ def _wrap(seq: torch.LongTensor, return_dict: bool):
304
+ if not return_dict:
305
+ return seq
306
+ try:
307
+ from transformers.generation.utils import GenerateDecoderOnlyOutput
308
+ return GenerateDecoderOnlyOutput(sequences=seq)
309
+ except Exception: # pragma: no cover - very old/new transformers without that class
310
+ return seq