pltobing commited on
Commit
9fab525
Β·
1 Parent(s): 8252138

fix: bind all inputs for all talker & local

Browse files

- All inputs can be bound as shapes are
static.
- Using in_place to replace the values
of the buffer
- Codec decoder next, as there is still
a bug in it.

src/inference/qwen3_tts_inferencer_onnx.py CHANGED
@@ -440,7 +440,8 @@ class Qwen3TTSInferencerONNX:
440
 
441
  # Non-graphed utility sessions
442
  log.info(f" codec decoder <- {codec_decoder_model_path}")
443
- self._codec_decoder_sess = _sess(codec_decoder_model_path, graph=self._enable_cuda_graph)
 
444
  log.info(f" speaker encoder <- {speaker_encoder_model_path}")
445
  self._speaker_encoder = _sess(speaker_encoder_model_path, graph=False)
446
  log.info(f" codec embed <- {talker_codec_embed_model_path}")
@@ -560,6 +561,23 @@ class Qwen3TTSInferencerONNX:
560
  # Define cos and sin table for RoPE embedding
561
  self._cos_rope, self._sin_rope = self._build_rope_tables_numpy()
562
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
  # Pre-allocate output OrtValues for Talker prefill
564
  # Prefill outputs logits over the full q_len=9 sequence; we only need
565
  # the last position for sampling, but we allocate for the full length.
@@ -570,23 +588,55 @@ class Qwen3TTSInferencerONNX:
570
  (1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
571
  )
572
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  # Pre-allocate output OrtValues for the Talker step
574
  self._talker_logits_ov = _make_device_ortvalue((1, self._vocab_size), np.float32, self._device, cuda_device_id)
575
  self._talker_hidden_ov = _make_device_ortvalue(
576
  (1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
577
  )
578
 
 
 
 
 
 
 
579
  # Pre-allocate output OrtValues for Local Talker prefill
580
  # Backbone outputs last_hidden [1, cp_hidden_size]; logits come from lm_head
581
  self._local_prefill_hidden_ov = _make_device_ortvalue(
582
  (1, self._local_hidden_size), np.float32, self._device, cuda_device_id
583
  )
584
 
 
 
 
 
 
 
585
  # Pre-allocate output OrtValue for the unified Local Talker backbone step
586
  self._local_step_hidden_ov = _make_device_ortvalue(
587
  (1, self._local_hidden_size), np.float32, self._device, cuda_device_id
588
  )
589
 
 
 
 
 
 
590
  # Pre-allocate output OrtValue for the batched lm_head
591
  # Shape: [15, local_vocab_size] β€” all codebook group logits at once
592
  self._local_lm_head_logits_ov = _make_device_ortvalue(
@@ -622,6 +672,14 @@ class Qwen3TTSInferencerONNX:
622
  self._codec_decoder_bound = _BoundSession(self._codec_decoder_sess, self._device, cuda_device_id)
623
  self._codec_step_idx = 0
624
 
 
 
 
 
 
 
 
 
625
  # Pre-allocate OrtValues for Codec Decoder
626
  self._codec_wav_ov = _make_device_ortvalue(
627
  (1, 1, self._codec_chunk_frames * self._speech_tokenizer_decoder_total_upsample),
@@ -707,6 +765,8 @@ class Qwen3TTSInferencerONNX:
707
  b.bind_output_device("current_hidden_state_cache", self._codec_hidden_cache_ov)
708
  b.bind_output_device("current_pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
709
 
 
 
710
  b.bind_input_device("hidden_state_cache", self._codec_hidden_cache_ov)
711
  b.bind_input_device("pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
712
 
@@ -729,6 +789,11 @@ class Qwen3TTSInferencerONNX:
729
  here; they are re-bound on every call in ``_run_talker_prefill``.
730
  """
731
  b = self._talker_prefill_bound
 
 
 
 
 
732
  for i in range(self._num_hidden_layers):
733
  b.bind_input_device(f"past_key_{i}", self._kv_talker_ov[2 * i])
734
  b.bind_input_device(f"past_value_{i}", self._kv_talker_ov[2 * i + 1])
@@ -746,6 +811,8 @@ class Qwen3TTSInferencerONNX:
746
  Dynamic inputs are re-bound on every call in ``_run_local_prefill``.
747
  """
748
  b = self._local_prefill_bound
 
 
749
  for i in range(self._local_num_hidden_layers):
750
  b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
751
  b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
@@ -765,6 +832,11 @@ class Qwen3TTSInferencerONNX:
765
  here; they are re-bound on every call in ``_run_talker_step``.
766
  """
767
  b = self._talker_step_bound
 
 
 
 
 
768
  for i in range(self._num_hidden_layers):
769
  b.bind_input_device(f"past_key_{i}", self._kv_talker_ov[2 * i])
770
  b.bind_input_device(f"past_value_{i}", self._kv_talker_ov[2 * i + 1])
@@ -781,6 +853,8 @@ class Qwen3TTSInferencerONNX:
781
  is applied separately by ``_wire_local_lm_head_bindings``.
782
  """
783
  b = self._local_step_bound
 
 
784
  for i in range(self._local_num_hidden_layers):
785
  b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
786
  b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
@@ -796,6 +870,7 @@ class Qwen3TTSInferencerONNX:
796
  bound to the pre-allocated device OrtValue.
797
  """
798
  b = self._local_lm_head_bound
 
799
  b.bind_output_device("logits", self._local_lm_head_logits_ov)
800
 
801
  # ── Prefill KV snapshot helpers ───────────────────────────────────────────
@@ -1152,11 +1227,11 @@ class Qwen3TTSInferencerONNX:
1152
  and ``_talker_prefill_hidden_ov`` respectively.
1153
  """
1154
  b = self._talker_prefill_bound
1155
- b.bind_input_cpu("inputs_embeds", inputs_embeds)
1156
- b.bind_input_cpu("cache_position", cache_position)
1157
- b.bind_input_cpu("attention_mask", attention_mask)
1158
- b.bind_input_cpu("cos_rope", cos_rope)
1159
- b.bind_input_cpu("sin_rope", sin_rope)
1160
  b.run()
1161
 
1162
  # ── Talker step (IOBinding + CUDA graph) ──────────────────────────────────
@@ -1172,11 +1247,11 @@ class Qwen3TTSInferencerONNX:
1172
  """Execute one Talker step via IOBinding and return logits as NumPy."""
1173
  b = self._talker_step_bound
1174
  # Re-bind the two small dynamic inputs (Hβ†’D copy, ~4 KB total)
1175
- b.bind_input_cpu("inputs_embeds", inputs_embeds)
1176
- b.bind_input_cpu("cache_position", cache_position)
1177
- b.bind_input_cpu("attention_mask", attention_mask)
1178
- b.bind_input_cpu("cos_rope", cos_rope)
1179
- b.bind_input_cpu("sin_rope", sin_rope)
1180
  # All KV and output bindings are already wired statically
1181
  b.run()
1182
  # Copy logits to CPU for sampling (~12 KB for vocab_size=3072)
@@ -1196,8 +1271,8 @@ class Qwen3TTSInferencerONNX:
1196
  Logits are obtained by calling ``_run_local_lm_head`` with this hidden.
1197
  """
1198
  b = self._local_prefill_bound
1199
- b.bind_input_cpu("inputs_embeds", inputs_embeds)
1200
- b.bind_input_cpu("cache_position", cache_position)
1201
  b.run()
1202
  return self._local_prefill_hidden_ov.numpy() # [1, cp_hidden_size]
1203
 
@@ -1214,8 +1289,8 @@ class Qwen3TTSInferencerONNX:
1214
  Logits are obtained by calling ``_run_local_lm_head`` with this hidden.
1215
  """
1216
  b = self._local_step_bound
1217
- b.bind_input_cpu("inputs_embeds", inputs_embeds)
1218
- b.bind_input_cpu("cache_position", cache_position)
1219
  b.run()
1220
  return self._local_step_hidden_ov.numpy() # [1, cp_hidden_size]
1221
 
@@ -1231,7 +1306,7 @@ class Qwen3TTSInferencerONNX:
1231
  ``logits[head_idx]`` on the CPU for sampling.
1232
  """
1233
  b = self._local_lm_head_bound
1234
- b.bind_input_cpu("hidden_states", hidden)
1235
  b.run()
1236
  return self._local_lm_head_logits_ov.numpy() # [15, local_vocab_size]
1237
 
@@ -1246,11 +1321,16 @@ class Qwen3TTSInferencerONNX:
1246
  b = self._codec_decoder_bound
1247
  # Re-bind the two small dynamic inputs (Hβ†’D copy, ~4 KB total)
1248
  b.bind_input_cpu("codes", chunk_tokens)
1249
- b.bind_input_cpu("cache_position", pos)
 
 
 
 
1250
  # All KV and output bindings are already wired statically
1251
  b.run()
1252
  # Copy wav to CPU
1253
- return b.get_output_numpy("wav")
 
1254
 
1255
  # ── Main autoregressive step ──────────────────────────────────────────────
1256
 
@@ -1285,9 +1365,14 @@ class Qwen3TTSInferencerONNX:
1285
  cos_rope = self._cos_rope[:, :, cache_position]
1286
  sin_rope = self._sin_rope[:, :, cache_position]
1287
  logits = self._run_talker_step(inputs_embeds, cache_position, attn_mask, cos_rope, sin_rope) # [1, vocab]
 
1288
 
1289
  # Retrieve hidden states for Local Talker prefill
1290
  self._last_hidden_states_np = self._talker_hidden_ov.numpy() # [1, 1, H]
 
 
 
 
1291
  self._talker_seq_len += 1
1292
 
1293
  # ── Sample first token (CPU) ──────────────────────────────────────────
 
440
 
441
  # Non-graphed utility sessions
442
  log.info(f" codec decoder <- {codec_decoder_model_path}")
443
+ # self._codec_decoder_sess = _sess(codec_decoder_model_path, graph=self._enable_cuda_graph)
444
+ self._codec_decoder_sess = _sess(codec_decoder_model_path, graph=False)
445
  log.info(f" speaker encoder <- {speaker_encoder_model_path}")
446
  self._speaker_encoder = _sess(speaker_encoder_model_path, graph=False)
447
  log.info(f" codec embed <- {talker_codec_embed_model_path}")
 
561
  # Define cos and sin table for RoPE embedding
562
  self._cos_rope, self._sin_rope = self._build_rope_tables_numpy()
563
 
564
+ # Pre-allocate input OrtValues for Talker prefill
565
+ self._talker_prefill_inputs_embeds_ov = _make_device_ortvalue(
566
+ (1, _TALKER_PREFILL_LEN, self._hidden_size), np.float32, self._device, cuda_device_id
567
+ )
568
+ self._talker_prefill_cache_position_ov = _make_device_ortvalue(
569
+ (_TALKER_PREFILL_LEN), np.int64, self._device, cuda_device_id
570
+ )
571
+ self._talker_prefill_attention_mask_ov = _make_device_ortvalue(
572
+ (1, 1, _TALKER_PREFILL_LEN, _TALKER_MAX_SEQ_LEN), np.float32, self._device, cuda_device_id
573
+ )
574
+ self._talker_prefill_cos_rope_ov = _make_device_ortvalue(
575
+ (1, 1, _TALKER_PREFILL_LEN, self._head_dim), np.float32, self._device, cuda_device_id
576
+ )
577
+ self._talker_prefill_sin_rope_ov = _make_device_ortvalue(
578
+ (1, 1, _TALKER_PREFILL_LEN, self._head_dim), np.float32, self._device, cuda_device_id
579
+ )
580
+
581
  # Pre-allocate output OrtValues for Talker prefill
582
  # Prefill outputs logits over the full q_len=9 sequence; we only need
583
  # the last position for sampling, but we allocate for the full length.
 
588
  (1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
589
  )
590
 
591
+ # Pre-allocate input OrtValues for Talker step
592
+ self._talker_inputs_embeds_ov = _make_device_ortvalue(
593
+ (1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
594
+ )
595
+ self._talker_cache_position_ov = _make_device_ortvalue((1), np.int64, self._device, cuda_device_id)
596
+ self._talker_attention_mask_ov = _make_device_ortvalue(
597
+ (1, 1, 1, _TALKER_MAX_SEQ_LEN), np.float32, self._device, cuda_device_id
598
+ )
599
+ self._talker_cos_rope_ov = _make_device_ortvalue(
600
+ (1, 1, 1, self._head_dim), np.float32, self._device, cuda_device_id
601
+ )
602
+ self._talker_sin_rope_ov = _make_device_ortvalue(
603
+ (1, 1, 1, self._head_dim), np.float32, self._device, cuda_device_id
604
+ )
605
+
606
  # Pre-allocate output OrtValues for the Talker step
607
  self._talker_logits_ov = _make_device_ortvalue((1, self._vocab_size), np.float32, self._device, cuda_device_id)
608
  self._talker_hidden_ov = _make_device_ortvalue(
609
  (1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
610
  )
611
 
612
+ # Pre-allocate input OrtValues for Local Talker prefill
613
+ self._local_prefill_inputs_embeds_ov = _make_device_ortvalue(
614
+ (1, 2, self._hidden_size), np.float32, self._device, cuda_device_id
615
+ )
616
+ self._local_prefill_cache_position_ov = _make_device_ortvalue((2), np.int64, self._device, cuda_device_id)
617
+
618
  # Pre-allocate output OrtValues for Local Talker prefill
619
  # Backbone outputs last_hidden [1, cp_hidden_size]; logits come from lm_head
620
  self._local_prefill_hidden_ov = _make_device_ortvalue(
621
  (1, self._local_hidden_size), np.float32, self._device, cuda_device_id
622
  )
623
 
624
+ # Pre-allocate input OrtValues for Local Talker step
625
+ self._local_step_inputs_embeds_ov = _make_device_ortvalue(
626
+ (1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
627
+ )
628
+ self._local_step_cache_position_ov = _make_device_ortvalue((1), np.int64, self._device, cuda_device_id)
629
+
630
  # Pre-allocate output OrtValue for the unified Local Talker backbone step
631
  self._local_step_hidden_ov = _make_device_ortvalue(
632
  (1, self._local_hidden_size), np.float32, self._device, cuda_device_id
633
  )
634
 
635
+ # Pre-allocate input OrtValue for the batched lm_head
636
+ self._local_lm_head_hidden_states_ov = _make_device_ortvalue(
637
+ (1, self._local_hidden_size), np.float32, self._device, cuda_device_id
638
+ )
639
+
640
  # Pre-allocate output OrtValue for the batched lm_head
641
  # Shape: [15, local_vocab_size] β€” all codebook group logits at once
642
  self._local_lm_head_logits_ov = _make_device_ortvalue(
 
672
  self._codec_decoder_bound = _BoundSession(self._codec_decoder_sess, self._device, cuda_device_id)
673
  self._codec_step_idx = 0
674
 
675
+ # Pre-allocate OrtValues input for Codec Decoder
676
+ self._codec_codes_ov = _make_device_ortvalue(
677
+ (1, self._num_code_groups, self.chunk_frames), np.int64, self._device, cuda_device_id
678
+ )
679
+ self._codec_cache_position_ov = _make_device_ortvalue(
680
+ (self.chunk_frames), np.int64, self._device, cuda_device_id
681
+ )
682
+
683
  # Pre-allocate OrtValues for Codec Decoder
684
  self._codec_wav_ov = _make_device_ortvalue(
685
  (1, 1, self._codec_chunk_frames * self._speech_tokenizer_decoder_total_upsample),
 
765
  b.bind_output_device("current_hidden_state_cache", self._codec_hidden_cache_ov)
766
  b.bind_output_device("current_pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
767
 
768
+ # b.bind_input_device("codes", self._codec_codes_ov)
769
+ b.bind_input_device("cache_position", self._codec_cache_position_ov)
770
  b.bind_input_device("hidden_state_cache", self._codec_hidden_cache_ov)
771
  b.bind_input_device("pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
772
 
 
789
  here; they are re-bound on every call in ``_run_talker_prefill``.
790
  """
791
  b = self._talker_prefill_bound
792
+ b.bind_input_device("inputs_embeds", self._talker_prefill_inputs_embeds_ov)
793
+ b.bind_input_device("cache_position", self._talker_prefill_cache_position_ov)
794
+ b.bind_input_device("attention_mask", self._talker_prefill_attention_mask_ov)
795
+ b.bind_input_device("cos_rope", self._talker_prefill_cos_rope_ov)
796
+ b.bind_input_device("sin_rope", self._talker_prefill_sin_rope_ov)
797
  for i in range(self._num_hidden_layers):
798
  b.bind_input_device(f"past_key_{i}", self._kv_talker_ov[2 * i])
799
  b.bind_input_device(f"past_value_{i}", self._kv_talker_ov[2 * i + 1])
 
811
  Dynamic inputs are re-bound on every call in ``_run_local_prefill``.
812
  """
813
  b = self._local_prefill_bound
814
+ b.bind_input_device("inputs_embeds", self._local_prefill_inputs_embeds_ov)
815
+ b.bind_input_device("cache_position", self._local_prefill_cache_position_ov)
816
  for i in range(self._local_num_hidden_layers):
817
  b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
818
  b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
 
832
  here; they are re-bound on every call in ``_run_talker_step``.
833
  """
834
  b = self._talker_step_bound
835
+ b.bind_input_device("inputs_embeds", self._talker_inputs_embeds_ov)
836
+ b.bind_input_device("cache_position", self._talker_cache_position_ov)
837
+ b.bind_input_device("attention_mask", self._talker_attention_mask_ov)
838
+ b.bind_input_device("cos_rope", self._talker_cos_rope_ov)
839
+ b.bind_input_device("sin_rope", self._talker_sin_rope_ov)
840
  for i in range(self._num_hidden_layers):
841
  b.bind_input_device(f"past_key_{i}", self._kv_talker_ov[2 * i])
842
  b.bind_input_device(f"past_value_{i}", self._kv_talker_ov[2 * i + 1])
 
853
  is applied separately by ``_wire_local_lm_head_bindings``.
854
  """
855
  b = self._local_step_bound
856
+ b.bind_input_device("inputs_embeds", self._local_step_inputs_embeds_ov)
857
+ b.bind_input_device("cache_position", self._local_step_cache_position_ov)
858
  for i in range(self._local_num_hidden_layers):
859
  b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
860
  b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
 
870
  bound to the pre-allocated device OrtValue.
871
  """
872
  b = self._local_lm_head_bound
873
+ b.bind_input_device("hidden_states", self._local_lm_head_hidden_states_ov)
874
  b.bind_output_device("logits", self._local_lm_head_logits_ov)
875
 
876
  # ── Prefill KV snapshot helpers ───────────────────────────────────────────
 
1227
  and ``_talker_prefill_hidden_ov`` respectively.
1228
  """
1229
  b = self._talker_prefill_bound
1230
+ _copy_numpy_to_ortvalue(inputs_embeds, self._talker_prefill_inputs_embeds_ov)
1231
+ _copy_numpy_to_ortvalue(cache_position, self._talker_prefill_cache_position_ov)
1232
+ _copy_numpy_to_ortvalue(attention_mask, self._talker_prefill_attention_mask_ov)
1233
+ _copy_numpy_to_ortvalue(cos_rope, self._talker_prefill_cos_rope_ov)
1234
+ _copy_numpy_to_ortvalue(sin_rope, self._talker_prefill_sin_rope_ov)
1235
  b.run()
1236
 
1237
  # ── Talker step (IOBinding + CUDA graph) ──────────────────────────────────
 
1247
  """Execute one Talker step via IOBinding and return logits as NumPy."""
1248
  b = self._talker_step_bound
1249
  # Re-bind the two small dynamic inputs (Hβ†’D copy, ~4 KB total)
1250
+ _copy_numpy_to_ortvalue(inputs_embeds, self._talker_inputs_embeds_ov)
1251
+ _copy_numpy_to_ortvalue(cache_position, self._talker_cache_position_ov)
1252
+ _copy_numpy_to_ortvalue(attention_mask, self._talker_attention_mask_ov)
1253
+ _copy_numpy_to_ortvalue(cos_rope, self._talker_cos_rope_ov)
1254
+ _copy_numpy_to_ortvalue(sin_rope, self._talker_sin_rope_ov)
1255
  # All KV and output bindings are already wired statically
1256
  b.run()
1257
  # Copy logits to CPU for sampling (~12 KB for vocab_size=3072)
 
1271
  Logits are obtained by calling ``_run_local_lm_head`` with this hidden.
1272
  """
1273
  b = self._local_prefill_bound
1274
+ _copy_numpy_to_ortvalue(inputs_embeds, self._local_prefill_inputs_embeds_ov)
1275
+ _copy_numpy_to_ortvalue(cache_position, self._local_prefill_cache_position_ov)
1276
  b.run()
1277
  return self._local_prefill_hidden_ov.numpy() # [1, cp_hidden_size]
1278
 
 
1289
  Logits are obtained by calling ``_run_local_lm_head`` with this hidden.
1290
  """
1291
  b = self._local_step_bound
1292
+ _copy_numpy_to_ortvalue(inputs_embeds, self._local_step_inputs_embeds_ov)
1293
+ _copy_numpy_to_ortvalue(cache_position, self._local_step_cache_position_ov)
1294
  b.run()
1295
  return self._local_step_hidden_ov.numpy() # [1, cp_hidden_size]
1296
 
 
1306
  ``logits[head_idx]`` on the CPU for sampling.
1307
  """
1308
  b = self._local_lm_head_bound
1309
+ _copy_numpy_to_ortvalue(hidden, self._local_lm_head_hidden_states_ov)
1310
  b.run()
1311
  return self._local_lm_head_logits_ov.numpy() # [15, local_vocab_size]
1312
 
 
1321
  b = self._codec_decoder_bound
1322
  # Re-bind the two small dynamic inputs (Hβ†’D copy, ~4 KB total)
1323
  b.bind_input_cpu("codes", chunk_tokens)
1324
+ # log.info(f"run_codec_decoder chunk_tokens {chunk_tokens.shape} {chunk_tokens.dtype}")
1325
+ # b.bind_input_cpu("cache_position", pos)
1326
+ # log.info(f"run_codec_decoder pos {pos.shape} {pos.dtype}")
1327
+ # _copy_numpy_to_ortvalue(chunk_tokens, self._codec_codes_ov)
1328
+ _copy_numpy_to_ortvalue(pos, self._codec_cache_position_ov)
1329
  # All KV and output bindings are already wired statically
1330
  b.run()
1331
  # Copy wav to CPU
1332
+ # return b.get_output_numpy("wav")
1333
+ return self._codec_wav_ov.numpy()
1334
 
1335
  # ── Main autoregressive step ──────────────────────────────────────────────
1336
 
 
1365
  cos_rope = self._cos_rope[:, :, cache_position]
1366
  sin_rope = self._sin_rope[:, :, cache_position]
1367
  logits = self._run_talker_step(inputs_embeds, cache_position, attn_mask, cos_rope, sin_rope) # [1, vocab]
1368
+ log.info(f"step-idx-{self._step_idx} logits {logits} {logits.shape} {logits.dtype}")
1369
 
1370
  # Retrieve hidden states for Local Talker prefill
1371
  self._last_hidden_states_np = self._talker_hidden_ov.numpy() # [1, 1, H]
1372
+ log.info(
1373
+ f"step-idx-{self._step_idx} self._last_hidden_states_np {self._last_hidden_states_np} "
1374
+ f"{self._last_hidden_states_np.shape} {self._last_hidden_states_np.dtype}"
1375
+ )
1376
  self._talker_seq_len += 1
1377
 
1378
  # ── Sample first token (CPU) ──────────────────────────────────────────