fix: local talker & talker input structure
Browse files- Now, local talker follows the backbone talker
to use attention_mask and cos/sin RoPE as input.
- This reduces the amount of CPU fallback ops
from mask and cos/sin creations.
- Both still use scatter with indexing from cache_pos
for KV-cache update. This needs to be modified to
avoid CPU fallback.
- Also separate the .onnx file as _prefill and _step
as handling the KV-cache without scatter in the
next revision will need baked static flow.
- This is within the process of optimizing Ops from
CPU fallback.
- qwen3-tts_onnx/{talker_local_model.onnx → talker_local_model_prefill.onnx} +2 -2
- qwen3-tts_onnx/{talker_model.onnx → talker_local_model_step.onnx} +2 -2
- qwen3-tts_onnx/talker_model_prefill.onnx +3 -0
- qwen3-tts_onnx/talker_model_step.onnx +3 -0
- src/inference/qwen3_tts_inferencer_onnx.py +252 -28
- test_qwen3-tts-streaming_onnx.py +13 -12
qwen3-tts_onnx/{talker_local_model.onnx → talker_local_model_prefill.onnx}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a64b5cc7bd8345a6a40c3cb0882d6ac699152817bd19e6f3a203214642c843c5
|
| 3 |
+
size 314880101
|
qwen3-tts_onnx/{talker_model.onnx → talker_local_model_step.onnx}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:76e7a751f3d8038c5adf5e81c0b1f4f56a480b43be643928ff1e4f748ff4ce43
|
| 3 |
+
size 314880101
|
qwen3-tts_onnx/talker_model_prefill.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:144ff25e52308068829932309acf2e8444965963a192b0649d07126b89983b4d
|
| 3 |
+
size 1775928908
|
qwen3-tts_onnx/talker_model_step.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2e0a94a3c6afafa67373fb841deef090bc432bdcf8c201bf86754db735da3932
|
| 3 |
+
size 1775928908
|
src/inference/qwen3_tts_inferencer_onnx.py
CHANGED
|
@@ -349,10 +349,14 @@ class Qwen3TTSInferencerONNX:
|
|
| 349 |
|
| 350 |
Parameters
|
| 351 |
----------
|
| 352 |
-
|
| 353 |
-
Path to ``
|
| 354 |
-
|
| 355 |
-
Path to ``
|
|
|
|
|
|
|
|
|
|
|
|
|
| 356 |
talker_local_lm_head_model_path : str
|
| 357 |
Path to ``talker_local_lm_head.onnx`` (batched lm_head for all 15 codebook groups).
|
| 358 |
codec_decoder_model_path : str
|
|
@@ -380,8 +384,10 @@ class Qwen3TTSInferencerONNX:
|
|
| 380 |
|
| 381 |
def __init__(
|
| 382 |
self,
|
| 383 |
-
|
| 384 |
-
|
|
|
|
|
|
|
| 385 |
talker_local_lm_head_model_path: str,
|
| 386 |
codec_decoder_model_path: str,
|
| 387 |
speaker_encoder_model_path: str,
|
|
@@ -421,18 +427,18 @@ class Qwen3TTSInferencerONNX:
|
|
| 421 |
log.info("Loading ONNX sessions...")
|
| 422 |
|
| 423 |
# Prefill sessions: IOBinding + CUDA graph (q_len is always fixed)
|
| 424 |
-
log.info(f" talker prefill <- {
|
| 425 |
-
_talker_prefill_sess = _sess(
|
| 426 |
-
log.info(f" local prefill <- {
|
| 427 |
-
_local_prefill_sess = _sess(
|
| 428 |
|
| 429 |
# Step sessions: IOBinding + CUDA graph
|
| 430 |
-
log.info(f" talker step <- {
|
| 431 |
-
_talker_step_sess = _sess(
|
| 432 |
|
| 433 |
# Unified Local Talker backbone step (shared for steps 2..15)
|
| 434 |
-
log.info(f" local step <- {
|
| 435 |
-
_local_step_sess = _sess(
|
| 436 |
|
| 437 |
# Batched lm_head (all 15 codebook groups in one session)
|
| 438 |
log.info(f" local lm_head <- {talker_local_lm_head_model_path}")
|
|
@@ -492,13 +498,14 @@ class Qwen3TTSInferencerONNX:
|
|
| 492 |
self._num_hidden_layers = self._talker_config.num_hidden_layers # 28
|
| 493 |
self._num_key_value_heads = self._talker_config.num_key_value_heads # 8
|
| 494 |
self._text_hidden_size = self._talker_config.text_hidden_size # 2048
|
| 495 |
-
self._text_vocab_size = self._talker_config.text_vocab_size
|
| 496 |
self._vocab_size = self._talker_config.vocab_size # 3072
|
| 497 |
|
| 498 |
# Local Talker dims
|
| 499 |
self._local_head_dim = self._code_predictor_config.head_dim # 128
|
| 500 |
self._local_hidden_size = self._code_predictor_config.hidden_size # 1024
|
| 501 |
self._local_num_hidden_layers = self._code_predictor_config.num_hidden_layers # 5
|
|
|
|
| 502 |
self._local_num_key_value_heads = self._code_predictor_config.num_key_value_heads # 8
|
| 503 |
self._local_vocab_size = self._code_predictor_config.vocab_size # 2048
|
| 504 |
|
|
@@ -608,11 +615,49 @@ class Qwen3TTSInferencerONNX:
|
|
| 608 |
(1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
|
| 609 |
)
|
| 610 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
# Pre-allocate input OrtValues for Local Talker prefill
|
| 612 |
self._local_prefill_inputs_embeds_ov = _make_device_ortvalue(
|
| 613 |
(1, 2, self._hidden_size), np.float32, self._device, cuda_device_id
|
| 614 |
)
|
| 615 |
self._local_prefill_cache_position_ov = _make_device_ortvalue((2), np.int64, self._device, cuda_device_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 616 |
|
| 617 |
# Pre-allocate output OrtValues for Local Talker prefill
|
| 618 |
# Backbone outputs last_hidden [1, cp_hidden_size]; logits come from lm_head
|
|
@@ -625,6 +670,33 @@ class Qwen3TTSInferencerONNX:
|
|
| 625 |
(1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
|
| 626 |
)
|
| 627 |
self._local_step_cache_position_ov = _make_device_ortvalue((1), np.int64, self._device, cuda_device_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 628 |
|
| 629 |
# Pre-allocate output OrtValue for the unified Local Talker backbone step
|
| 630 |
self._local_step_hidden_ov = _make_device_ortvalue(
|
|
@@ -812,6 +884,12 @@ class Qwen3TTSInferencerONNX:
|
|
| 812 |
b = self._local_prefill_bound
|
| 813 |
b.bind_input_device("inputs_embeds", self._local_prefill_inputs_embeds_ov)
|
| 814 |
b.bind_input_device("cache_position", self._local_prefill_cache_position_ov)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 815 |
for i in range(self._local_num_hidden_layers):
|
| 816 |
b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
|
| 817 |
b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
|
|
@@ -854,6 +932,12 @@ class Qwen3TTSInferencerONNX:
|
|
| 854 |
b = self._local_step_bound
|
| 855 |
b.bind_input_device("inputs_embeds", self._local_step_inputs_embeds_ov)
|
| 856 |
b.bind_input_device("cache_position", self._local_step_cache_position_ov)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 857 |
for i in range(self._local_num_hidden_layers):
|
| 858 |
b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
|
| 859 |
b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
|
|
@@ -936,6 +1020,7 @@ class Qwen3TTSInferencerONNX:
|
|
| 936 |
return langs
|
| 937 |
|
| 938 |
# ── Helper to build RoPE cos and sin tables for the talker ────────────────
|
|
|
|
| 939 |
def _build_rope_tables_numpy(self):
|
| 940 |
"""
|
| 941 |
Build NumPy RoPE cosine and sine lookup tables with interleaved multimodal layout.
|
|
@@ -1039,9 +1124,97 @@ class Qwen3TTSInferencerONNX:
|
|
| 1039 |
# Add singleton dimension to match expected broadcast shape.
|
| 1040 |
cos = np.expand_dims(cos, axis=unsqueeze_dim)
|
| 1041 |
sin = np.expand_dims(sin, axis=unsqueeze_dim)
|
| 1042 |
-
# each cos and sin with shape (bs, 1, positions, rope_dim
|
| 1043 |
|
| 1044 |
-
return cos, sin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1045 |
|
| 1046 |
# ── CPU sampling ──────────────────────────────────────────────────────────
|
| 1047 |
|
|
@@ -1200,8 +1373,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1200 |
cache_position = np.arange(_TALKER_PREFILL_LEN, dtype=np.int64)
|
| 1201 |
causal_rows = self._causal_tril[:, :, cache_position, :] # [1,1,q_len,MAX]
|
| 1202 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1203 |
-
cos_rope = self._cos_rope[:, :, cache_position]
|
| 1204 |
-
sin_rope = self._sin_rope[:, :, cache_position]
|
| 1205 |
self._run_talker_prefill(inputs_embeds, cache_position, attn_mask, cos_rope, sin_rope)
|
| 1206 |
self._talker_seq_len = _TALKER_PREFILL_LEN
|
| 1207 |
# Snapshot the post-prefill KV state for turn resets
|
|
@@ -1262,7 +1435,11 @@ class Qwen3TTSInferencerONNX:
|
|
| 1262 |
self,
|
| 1263 |
inputs_embeds: np.ndarray, # [1, 2, talker_hidden_size]
|
| 1264 |
cache_position: np.ndarray, # [2]
|
|
|
|
|
|
|
|
|
|
| 1265 |
) -> np.ndarray:
|
|
|
|
| 1266 |
"""Execute the Local Talker prefill backbone via IOBinding (CUDA graph).
|
| 1267 |
|
| 1268 |
The local KV-cache device OrtValues are updated in-place. Returns
|
|
@@ -1272,6 +1449,10 @@ class Qwen3TTSInferencerONNX:
|
|
| 1272 |
b = self._local_prefill_bound
|
| 1273 |
_copy_numpy_to_ortvalue(inputs_embeds, self._local_prefill_inputs_embeds_ov)
|
| 1274 |
_copy_numpy_to_ortvalue(cache_position, self._local_prefill_cache_position_ov)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1275 |
b.run()
|
| 1276 |
return self._local_prefill_hidden_ov.numpy() # [1, cp_hidden_size]
|
| 1277 |
|
|
@@ -1281,7 +1462,11 @@ class Qwen3TTSInferencerONNX:
|
|
| 1281 |
self,
|
| 1282 |
inputs_embeds: np.ndarray, # [1, 1, talker_hidden_size]
|
| 1283 |
cache_position: np.ndarray, # [1]
|
|
|
|
|
|
|
|
|
|
| 1284 |
) -> np.ndarray:
|
|
|
|
| 1285 |
"""Execute one unified Local Talker backbone step via IOBinding.
|
| 1286 |
|
| 1287 |
Returns the last-token hidden state [1, cp_hidden_size] as NumPy.
|
|
@@ -1290,6 +1475,10 @@ class Qwen3TTSInferencerONNX:
|
|
| 1290 |
b = self._local_step_bound
|
| 1291 |
_copy_numpy_to_ortvalue(inputs_embeds, self._local_step_inputs_embeds_ov)
|
| 1292 |
_copy_numpy_to_ortvalue(cache_position, self._local_step_cache_position_ov)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1293 |
b.run()
|
| 1294 |
return self._local_step_hidden_ov.numpy() # [1, cp_hidden_size]
|
| 1295 |
|
|
@@ -1356,8 +1545,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1356 |
cache_position = np.array([self._talker_seq_len], dtype=np.int64)
|
| 1357 |
causal_rows = self._causal_tril[:, :, cache_position, :] # [1,1,q_len,MAX]
|
| 1358 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1359 |
-
cos_rope = self._cos_rope[:, :, cache_position]
|
| 1360 |
-
sin_rope = self._sin_rope[:, :, cache_position]
|
| 1361 |
logits = self._run_talker_step(inputs_embeds, cache_position, attn_mask, cos_rope, sin_rope) # [1, vocab]
|
| 1362 |
log.info(f"step-idx-{self._step_idx} logits {logits} {logits.shape} {logits.dtype}")
|
| 1363 |
|
|
@@ -1418,8 +1607,21 @@ class Qwen3TTSInferencerONNX:
|
|
| 1418 |
) # [1, 2, talker_hidden_size]
|
| 1419 |
cache_position_prefill = np.array([0, 1], dtype=np.int64)
|
| 1420 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1421 |
# Backbone prefill → last_hidden [1, cp_hidden_size]
|
| 1422 |
-
hidden = self._run_local_prefill(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1423 |
# Batched lm_head → [15, local_vocab_size]; select group 0 (codebook group 1)
|
| 1424 |
all_logits = self._run_local_lm_head(hidden) # [15, local_vocab_size]
|
| 1425 |
logits_g1 = all_logits[0:1, :] # [1, local_vocab_size]
|
|
@@ -1443,11 +1645,21 @@ class Qwen3TTSInferencerONNX:
|
|
| 1443 |
head_idx = step_i - 1 # 1..14 (0-indexed into the 15-row logits tensor)
|
| 1444 |
cache_position_step = np.array([step_i], dtype=np.int64)
|
| 1445 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1446 |
# Unified backbone step → last_hidden [1, cp_hidden_size]
|
| 1447 |
hidden = self._run_local_step(
|
| 1448 |
prev_embed.astype(np.float32),
|
| 1449 |
cache_position_step,
|
|
|
|
|
|
|
|
|
|
| 1450 |
)
|
|
|
|
| 1451 |
# Batched lm_head → [15, local_vocab_size]; select the current group
|
| 1452 |
all_logits = self._run_local_lm_head(hidden)
|
| 1453 |
logits_gi = all_logits[head_idx : head_idx + 1, :] # [1, local_vocab_size]
|
|
@@ -1524,8 +1736,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1524 |
causal_rows = self._causal_tril[:, :, cache_pos, :] # [1,1,q_len,MAX]
|
| 1525 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1526 |
for _ in range(n_iter):
|
| 1527 |
-
cos_rope = self._cos_rope[:, :, cache_pos]
|
| 1528 |
-
sin_rope = self._sin_rope[:, :, cache_pos]
|
| 1529 |
t0 = time.perf_counter()
|
| 1530 |
self._run_talker_prefill(dummy_embeds, cache_pos, attn_mask, cos_rope, sin_rope)
|
| 1531 |
times["talker_prefill"].append((time.perf_counter() - t0) * 1000)
|
|
@@ -1540,8 +1752,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1540 |
cache_pos_step = np.array([_TALKER_PREFILL_LEN + n], dtype=np.int64)
|
| 1541 |
causal_rows = self._causal_tril[:, :, cache_pos_step, :] # [1,1,q_len,MAX]
|
| 1542 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1543 |
-
cos_rope = self._cos_rope[:, :, cache_pos_step]
|
| 1544 |
-
sin_rope = self._sin_rope[:, :, cache_pos_step]
|
| 1545 |
t0 = time.perf_counter()
|
| 1546 |
self._run_talker_step(dummy_step_embeds, cache_pos_step, attn_mask, cos_rope, sin_rope)
|
| 1547 |
times["talker_step"].append((time.perf_counter() - t0) * 1000)
|
|
@@ -1553,9 +1765,15 @@ class Qwen3TTSInferencerONNX:
|
|
| 1553 |
log.info("Warming-up local talker prefill...")
|
| 1554 |
dummy_lp_embeds = np.random.randn(1, _LOCAL_PREFILL_LEN, self._local_hidden_size).astype(np.float32)
|
| 1555 |
cache_pos_lp = np.array([0, 1], dtype=np.int64)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1556 |
for _ in range(n_iter):
|
| 1557 |
t0 = time.perf_counter()
|
| 1558 |
-
self._run_local_prefill(dummy_lp_embeds, cache_pos_lp)
|
|
|
|
| 1559 |
times["local_prefill"].append((time.perf_counter() - t0) * 1000)
|
| 1560 |
exec_time_tot = sum(times["local_prefill"]) / 1000
|
| 1561 |
avg_exec_time = exec_time_tot / len(times["local_prefill"]) * 1000
|
|
@@ -1568,9 +1786,15 @@ class Qwen3TTSInferencerONNX:
|
|
| 1568 |
log.info("Warming-up local talker step...")
|
| 1569 |
dummy_ls_embeds = np.random.randn(1, 1, self._hidden_size).astype(np.float32)
|
| 1570 |
cache_pos_ls = np.array([2], dtype=np.int64)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1571 |
for _ in range(n_iter):
|
| 1572 |
t0 = time.perf_counter()
|
| 1573 |
-
self._run_local_step(dummy_ls_embeds, cache_pos_ls)
|
|
|
|
| 1574 |
times["local_step"].append((time.perf_counter() - t0) * 1000)
|
| 1575 |
exec_time_tot = sum(times["local_step"]) / 1000
|
| 1576 |
avg_exec_time = exec_time_tot / len(times["local_step"]) * 1000
|
|
|
|
| 349 |
|
| 350 |
Parameters
|
| 351 |
----------
|
| 352 |
+
talker_model_prefill_path : str
|
| 353 |
+
Path to ``talker_model_prefill.onnx``.
|
| 354 |
+
talker_model_step_path : str
|
| 355 |
+
Path to ``talker_model_step.onnx``.
|
| 356 |
+
talker_local_model_prefill_path : str
|
| 357 |
+
Path to ``talker_local_model_prefill.onnx``.
|
| 358 |
+
talker_local_model_step_path : str
|
| 359 |
+
Path to ``talker_local_model_step.onnx``.
|
| 360 |
talker_local_lm_head_model_path : str
|
| 361 |
Path to ``talker_local_lm_head.onnx`` (batched lm_head for all 15 codebook groups).
|
| 362 |
codec_decoder_model_path : str
|
|
|
|
| 384 |
|
| 385 |
def __init__(
|
| 386 |
self,
|
| 387 |
+
talker_model_prefill_path: str,
|
| 388 |
+
talker_model_step_path: str,
|
| 389 |
+
talker_local_model_prefill_path: str,
|
| 390 |
+
talker_local_model_step_path: str,
|
| 391 |
talker_local_lm_head_model_path: str,
|
| 392 |
codec_decoder_model_path: str,
|
| 393 |
speaker_encoder_model_path: str,
|
|
|
|
| 427 |
log.info("Loading ONNX sessions...")
|
| 428 |
|
| 429 |
# Prefill sessions: IOBinding + CUDA graph (q_len is always fixed)
|
| 430 |
+
log.info(f" talker prefill <- {talker_model_prefill_path}")
|
| 431 |
+
_talker_prefill_sess = _sess(talker_model_prefill_path, graph=self._enable_cuda_graph)
|
| 432 |
+
log.info(f" local prefill <- {talker_local_model_prefill_path}")
|
| 433 |
+
_local_prefill_sess = _sess(talker_local_model_prefill_path, graph=self._enable_cuda_graph)
|
| 434 |
|
| 435 |
# Step sessions: IOBinding + CUDA graph
|
| 436 |
+
log.info(f" talker step <- {talker_model_step_path}")
|
| 437 |
+
_talker_step_sess = _sess(talker_model_step_path, graph=self._enable_cuda_graph)
|
| 438 |
|
| 439 |
# Unified Local Talker backbone step (shared for steps 2..15)
|
| 440 |
+
log.info(f" local step <- {talker_local_model_step_path}")
|
| 441 |
+
_local_step_sess = _sess(talker_local_model_step_path, graph=self._enable_cuda_graph)
|
| 442 |
|
| 443 |
# Batched lm_head (all 15 codebook groups in one session)
|
| 444 |
log.info(f" local lm_head <- {talker_local_lm_head_model_path}")
|
|
|
|
| 498 |
self._num_hidden_layers = self._talker_config.num_hidden_layers # 28
|
| 499 |
self._num_key_value_heads = self._talker_config.num_key_value_heads # 8
|
| 500 |
self._text_hidden_size = self._talker_config.text_hidden_size # 2048
|
| 501 |
+
self._text_vocab_size = self._talker_config.text_vocab_size # 151936
|
| 502 |
self._vocab_size = self._talker_config.vocab_size # 3072
|
| 503 |
|
| 504 |
# Local Talker dims
|
| 505 |
self._local_head_dim = self._code_predictor_config.head_dim # 128
|
| 506 |
self._local_hidden_size = self._code_predictor_config.hidden_size # 1024
|
| 507 |
self._local_num_hidden_layers = self._code_predictor_config.num_hidden_layers # 5
|
| 508 |
+
self._local_num_attention_heads = self._code_predictor_config.num_attention_heads # 16
|
| 509 |
self._local_num_key_value_heads = self._code_predictor_config.num_key_value_heads # 8
|
| 510 |
self._local_vocab_size = self._code_predictor_config.vocab_size # 2048
|
| 511 |
|
|
|
|
| 615 |
(1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
|
| 616 |
)
|
| 617 |
|
| 618 |
+
# Define causal_tril for attention_mask Local prefill and step
|
| 619 |
+
_causal_tril_local = np.tril(np.ones((self._num_code_groups, self._num_code_groups), dtype=bool))
|
| 620 |
+
self._causal_tril_local = _causal_tril_local.reshape(1, 1, self._num_code_groups, self._num_code_groups)
|
| 621 |
+
|
| 622 |
+
# Define cache_write mask for each position in the Local prefill and steps, used to update KV-cache
|
| 623 |
+
# self._local_cache_write_mask_list = self._make_local_cache_write_mask(batch_size=1) # 15 cache write masks
|
| 624 |
+
# For each, [B, H, 16, D], with varying 1/0 depending on the position
|
| 625 |
+
|
| 626 |
+
# Define cos and sin table for Local RoPE embedding
|
| 627 |
+
self._cos_rope_local, self._sin_rope_local = self._build_local_rope_tables_numpy()
|
| 628 |
+
|
| 629 |
# Pre-allocate input OrtValues for Local Talker prefill
|
| 630 |
self._local_prefill_inputs_embeds_ov = _make_device_ortvalue(
|
| 631 |
(1, 2, self._hidden_size), np.float32, self._device, cuda_device_id
|
| 632 |
)
|
| 633 |
self._local_prefill_cache_position_ov = _make_device_ortvalue((2), np.int64, self._device, cuda_device_id)
|
| 634 |
+
self._local_prefill_attention_mask_ov = _make_device_ortvalue(
|
| 635 |
+
(1, 1, 2, self._num_code_groups), np.float32, self._device, cuda_device_id
|
| 636 |
+
)
|
| 637 |
+
self._local_prefill_cos_rope_ov = _make_device_ortvalue(
|
| 638 |
+
(1, 2, self._head_dim), np.float32, self._device, cuda_device_id
|
| 639 |
+
)
|
| 640 |
+
self._local_prefill_sin_rope_ov = _make_device_ortvalue(
|
| 641 |
+
(1, 2, self._head_dim), np.float32, self._device, cuda_device_id
|
| 642 |
+
)
|
| 643 |
+
# self._local_prefill_cache_write_mask_ov = _make_device_ortvalue(
|
| 644 |
+
# (1, self._local_num_key_value_heads, self._num_code_groups, self._local_head_dim),
|
| 645 |
+
# np.bool,
|
| 646 |
+
# self._device,
|
| 647 |
+
# cuda_device_id,
|
| 648 |
+
# )
|
| 649 |
+
# self._local_prefill_key_gqa_expanded_ov = _make_device_ortvalue(
|
| 650 |
+
# (1, self._local_num_attention_heads, self._num_code_groups, self._local_head_dim),
|
| 651 |
+
# np.float32,
|
| 652 |
+
# self._device,
|
| 653 |
+
# cuda_device_id,
|
| 654 |
+
# )
|
| 655 |
+
# self._local_prefill_value_gqa_expanded_ov = _make_device_ortvalue(
|
| 656 |
+
# (1, self._local_num_attention_heads, self._num_code_groups, self._local_head_dim),
|
| 657 |
+
# np.float32,
|
| 658 |
+
# self._device,
|
| 659 |
+
# cuda_device_id,
|
| 660 |
+
# )
|
| 661 |
|
| 662 |
# Pre-allocate output OrtValues for Local Talker prefill
|
| 663 |
# Backbone outputs last_hidden [1, cp_hidden_size]; logits come from lm_head
|
|
|
|
| 670 |
(1, 1, self._hidden_size), np.float32, self._device, cuda_device_id
|
| 671 |
)
|
| 672 |
self._local_step_cache_position_ov = _make_device_ortvalue((1), np.int64, self._device, cuda_device_id)
|
| 673 |
+
self._local_step_attention_mask_ov = _make_device_ortvalue(
|
| 674 |
+
(1, 1, 1, self._num_code_groups), np.float32, self._device, cuda_device_id
|
| 675 |
+
)
|
| 676 |
+
self._local_step_cos_rope_ov = _make_device_ortvalue(
|
| 677 |
+
(1, 1, self._head_dim), np.float32, self._device, cuda_device_id
|
| 678 |
+
)
|
| 679 |
+
self._local_step_sin_rope_ov = _make_device_ortvalue(
|
| 680 |
+
(1, 1, self._head_dim), np.float32, self._device, cuda_device_id
|
| 681 |
+
)
|
| 682 |
+
# self._local_step_cache_write_mask_ov = _make_device_ortvalue(
|
| 683 |
+
# (1, self._local_num_key_value_heads, self._num_code_groups, self._local_head_dim),
|
| 684 |
+
# np.bool,
|
| 685 |
+
# self._device,
|
| 686 |
+
# cuda_device_id,
|
| 687 |
+
# )
|
| 688 |
+
# self._local_step_key_gqa_expanded_ov = _make_device_ortvalue(
|
| 689 |
+
# (1, self._local_num_attention_heads, self._num_code_groups, self._local_head_dim),
|
| 690 |
+
# np.float32,
|
| 691 |
+
# self._device,
|
| 692 |
+
# cuda_device_id,
|
| 693 |
+
# )
|
| 694 |
+
# self._local_step_value_gqa_expanded_ov = _make_device_ortvalue(
|
| 695 |
+
# (1, self._local_num_attention_heads, self._num_code_groups, self._local_head_dim),
|
| 696 |
+
# np.float32,
|
| 697 |
+
# self._device,
|
| 698 |
+
# cuda_device_id,
|
| 699 |
+
# )
|
| 700 |
|
| 701 |
# Pre-allocate output OrtValue for the unified Local Talker backbone step
|
| 702 |
self._local_step_hidden_ov = _make_device_ortvalue(
|
|
|
|
| 884 |
b = self._local_prefill_bound
|
| 885 |
b.bind_input_device("inputs_embeds", self._local_prefill_inputs_embeds_ov)
|
| 886 |
b.bind_input_device("cache_position", self._local_prefill_cache_position_ov)
|
| 887 |
+
b.bind_input_device("attention_mask", self._local_prefill_attention_mask_ov)
|
| 888 |
+
b.bind_input_device("cos_rope", self._local_prefill_cos_rope_ov)
|
| 889 |
+
b.bind_input_device("sin_rope", self._local_prefill_sin_rope_ov)
|
| 890 |
+
# b.bind_input_device("cache_write_mask", self._local_prefill_cache_write_mask_ov)
|
| 891 |
+
# b.bind_input_device("key_gqa_expanded", self._local_prefill_key_gqa_expanded_ov)
|
| 892 |
+
# b.bind_input_device("value_gqa_expanded", self._local_prefill_value_gqa_expanded_ov)
|
| 893 |
for i in range(self._local_num_hidden_layers):
|
| 894 |
b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
|
| 895 |
b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
|
|
|
|
| 932 |
b = self._local_step_bound
|
| 933 |
b.bind_input_device("inputs_embeds", self._local_step_inputs_embeds_ov)
|
| 934 |
b.bind_input_device("cache_position", self._local_step_cache_position_ov)
|
| 935 |
+
b.bind_input_device("attention_mask", self._local_step_attention_mask_ov)
|
| 936 |
+
b.bind_input_device("cos_rope", self._local_step_cos_rope_ov)
|
| 937 |
+
b.bind_input_device("sin_rope", self._local_step_sin_rope_ov)
|
| 938 |
+
# b.bind_input_device("cache_write_mask", self._local_step_cache_write_mask_ov)
|
| 939 |
+
# b.bind_input_device("key_gqa_expanded", self._local_step_key_gqa_expanded_ov)
|
| 940 |
+
# b.bind_input_device("value_gqa_expanded", self._local_step_value_gqa_expanded_ov)
|
| 941 |
for i in range(self._local_num_hidden_layers):
|
| 942 |
b.bind_input_device(f"past_key_{i}", self._kv_local_ov[2 * i])
|
| 943 |
b.bind_input_device(f"past_value_{i}", self._kv_local_ov[2 * i + 1])
|
|
|
|
| 1020 |
return langs
|
| 1021 |
|
| 1022 |
# ── Helper to build RoPE cos and sin tables for the talker ────────────────
|
| 1023 |
+
|
| 1024 |
def _build_rope_tables_numpy(self):
|
| 1025 |
"""
|
| 1026 |
Build NumPy RoPE cosine and sine lookup tables with interleaved multimodal layout.
|
|
|
|
| 1124 |
# Add singleton dimension to match expected broadcast shape.
|
| 1125 |
cos = np.expand_dims(cos, axis=unsqueeze_dim)
|
| 1126 |
sin = np.expand_dims(sin, axis=unsqueeze_dim)
|
| 1127 |
+
# each cos and sin with shape (bs, 1, positions, rope_dim)
|
| 1128 |
|
| 1129 |
+
return cos.astype(np.float32), sin.astype(np.float32)
|
| 1130 |
+
|
| 1131 |
+
def _build_local_rope_tables_numpy(self):
|
| 1132 |
+
"""
|
| 1133 |
+
Build NumPy RoPE cosine and sine lookup tables for the local talker.
|
| 1134 |
+
|
| 1135 |
+
This function reproduces the logic of the provided Torch code in NumPy:
|
| 1136 |
+
1. Compute inverse RoPE frequencies from `rope_theta`.
|
| 1137 |
+
2. Build position-angle frequencies for `max_steps`.
|
| 1138 |
+
3. Form full rotary embeddings by duplicating the frequency half.
|
| 1139 |
+
4. Return `cos` and `sin` tables with an added singleton axis.
|
| 1140 |
+
|
| 1141 |
+
Parameters obtained from self.
|
| 1142 |
+
----------
|
| 1143 |
+
_hidden_size : int
|
| 1144 |
+
Total hidden size of the model.
|
| 1145 |
+
_num_attention_heads : int
|
| 1146 |
+
Number of attention heads.
|
| 1147 |
+
_max_steps : int
|
| 1148 |
+
Maximum number of positions to precompute.
|
| 1149 |
+
base (rope_theta) : float
|
| 1150 |
+
RoPE base frequency parameter.
|
| 1151 |
+
mrope_section : sequence of int
|
| 1152 |
+
Section boundaries used to interleave multimodal rotary dimensions.
|
| 1153 |
+
|
| 1154 |
+
Returns
|
| 1155 |
+
-------
|
| 1156 |
+
cos : np.ndarray
|
| 1157 |
+
Cosine table with shape matching the Torch version, including the
|
| 1158 |
+
extra singleton dimension inserted at axis 1.
|
| 1159 |
+
sin : np.ndarray
|
| 1160 |
+
Sine table with shape matching the Torch version, including the
|
| 1161 |
+
extra singleton dimension inserted at axis 1.
|
| 1162 |
+
"""
|
| 1163 |
+
rope_dim = self._code_predictor_config.head_dim
|
| 1164 |
+
base = self._code_predictor_config.rope_theta
|
| 1165 |
+
|
| 1166 |
+
# Build inverse frequencies for RoPE.
|
| 1167 |
+
inv_idx = np.arange(0, rope_dim, 2, dtype=np.float32)
|
| 1168 |
+
|
| 1169 |
+
# Compute position-dependent phase angles.
|
| 1170 |
+
inv_freq = (1.0 / (base ** (inv_idx / rope_dim))).astype(np.float32)
|
| 1171 |
+
# Match the original broadcasted matmul behavior.
|
| 1172 |
+
inv_freq_expanded = np.broadcast_to(
|
| 1173 |
+
inv_freq[None, :, None], (1, len(inv_idx), 1)
|
| 1174 |
+
) # shape (bs, 1, rope_dim, 1)
|
| 1175 |
+
position_ids = np.arange(self._num_code_groups, dtype=np.float32)
|
| 1176 |
+
position_ids_expanded = np.broadcast_to(
|
| 1177 |
+
position_ids[None, None, :], (1, 1, len(position_ids))
|
| 1178 |
+
) # shape (bs, 1, positions)
|
| 1179 |
+
freqs = np.matmul(inv_freq_expanded, position_ids_expanded).transpose(
|
| 1180 |
+
0, 2, 1
|
| 1181 |
+
) # shape (bs, positions, rope_dim)
|
| 1182 |
+
|
| 1183 |
+
# Duplicate the half-dimension to form full rotary embeddings.
|
| 1184 |
+
emb = np.concatenate([freqs, freqs], axis=-1)
|
| 1185 |
+
cos = np.cos(emb)
|
| 1186 |
+
sin = np.sin(emb)
|
| 1187 |
+
# each cos and sin with shape (bs, positions, rope_dim)
|
| 1188 |
+
|
| 1189 |
+
return cos.astype(np.float32), sin.astype(np.float32)
|
| 1190 |
+
|
| 1191 |
+
# ── Other helper functions ────────────────────────────────────────────────
|
| 1192 |
+
|
| 1193 |
+
# def _make_local_cache_write_mask(self, batch_size=1):
|
| 1194 |
+
# t = np.arange(self._num_code_groups, dtype=np.int64).reshape(batch_size, 1, 1, self._num_code_groups)
|
| 1195 |
+
|
| 1196 |
+
# cache_position = np.asarray([0, 1], dtype=np.int64).reshape(batch_size, 1, -1, 1)
|
| 1197 |
+
# mask = (t == cache_position).any(axis=2) # shape [1, 1, max_seq_len]
|
| 1198 |
+
# mask = mask[..., None] # shape [1, 1, max_seq_len, 1]
|
| 1199 |
+
# mask_list = [
|
| 1200 |
+
# np.broadcast_to(
|
| 1201 |
+
# mask, (batch_size, self._local_num_key_value_heads, self._num_code_groups, self._local_head_dim)
|
| 1202 |
+
# )
|
| 1203 |
+
# ]
|
| 1204 |
+
|
| 1205 |
+
# # cache write mask for each codebook from 1 to 15 (0 is generated by talker)
|
| 1206 |
+
# for pos in range(2, self._num_code_groups):
|
| 1207 |
+
# cache_position = np.asarray([pos], dtype=np.int64).reshape(1, 1, -1, 1)
|
| 1208 |
+
# mask = (t == cache_position).any(axis=2) # shape [1, 1, max_seq_len]
|
| 1209 |
+
# mask = mask[..., None] # shape [1, 1, max_seq_len, 1]
|
| 1210 |
+
# mask_list.append(
|
| 1211 |
+
# np.broadcast_to(
|
| 1212 |
+
# mask, (batch_size, self._local_num_key_value_heads, self._num_code_groups, self._local_head_dim)
|
| 1213 |
+
# )
|
| 1214 |
+
# )
|
| 1215 |
+
# # this is used for torch.where inside attention function to update KV-cache buffer in-place
|
| 1216 |
+
|
| 1217 |
+
# return mask_list
|
| 1218 |
|
| 1219 |
# ── CPU sampling ──────────────────────────────────────────────────────────
|
| 1220 |
|
|
|
|
| 1373 |
cache_position = np.arange(_TALKER_PREFILL_LEN, dtype=np.int64)
|
| 1374 |
causal_rows = self._causal_tril[:, :, cache_position, :] # [1,1,q_len,MAX]
|
| 1375 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1376 |
+
cos_rope = self._cos_rope[:, :, cache_position].copy()
|
| 1377 |
+
sin_rope = self._sin_rope[:, :, cache_position].copy()
|
| 1378 |
self._run_talker_prefill(inputs_embeds, cache_position, attn_mask, cos_rope, sin_rope)
|
| 1379 |
self._talker_seq_len = _TALKER_PREFILL_LEN
|
| 1380 |
# Snapshot the post-prefill KV state for turn resets
|
|
|
|
| 1435 |
self,
|
| 1436 |
inputs_embeds: np.ndarray, # [1, 2, talker_hidden_size]
|
| 1437 |
cache_position: np.ndarray, # [2]
|
| 1438 |
+
attention_mask: np.ndarray, # [1, 1, 2, max_seq_len]
|
| 1439 |
+
cos_rope: np.ndarray, # [1, 1, 2, 128]
|
| 1440 |
+
sin_rope: np.ndarray, # [1, 1, 2, 128]
|
| 1441 |
) -> np.ndarray:
|
| 1442 |
+
# cache_write_mask: np.ndarray, # [1, 8, 16, D]
|
| 1443 |
"""Execute the Local Talker prefill backbone via IOBinding (CUDA graph).
|
| 1444 |
|
| 1445 |
The local KV-cache device OrtValues are updated in-place. Returns
|
|
|
|
| 1449 |
b = self._local_prefill_bound
|
| 1450 |
_copy_numpy_to_ortvalue(inputs_embeds, self._local_prefill_inputs_embeds_ov)
|
| 1451 |
_copy_numpy_to_ortvalue(cache_position, self._local_prefill_cache_position_ov)
|
| 1452 |
+
_copy_numpy_to_ortvalue(attention_mask, self._local_prefill_attention_mask_ov)
|
| 1453 |
+
_copy_numpy_to_ortvalue(cos_rope, self._local_prefill_cos_rope_ov)
|
| 1454 |
+
_copy_numpy_to_ortvalue(sin_rope, self._local_prefill_sin_rope_ov)
|
| 1455 |
+
# _copy_numpy_to_ortvalue(cache_write_mask, self._local_prefill_cache_write_mask_ov)
|
| 1456 |
b.run()
|
| 1457 |
return self._local_prefill_hidden_ov.numpy() # [1, cp_hidden_size]
|
| 1458 |
|
|
|
|
| 1462 |
self,
|
| 1463 |
inputs_embeds: np.ndarray, # [1, 1, talker_hidden_size]
|
| 1464 |
cache_position: np.ndarray, # [1]
|
| 1465 |
+
attention_mask: np.ndarray, # [1, 1, 1, max_seq_len]
|
| 1466 |
+
cos_rope: np.ndarray, # [1, 1, 1, 128]
|
| 1467 |
+
sin_rope: np.ndarray, # [1, 1, 1, 128]
|
| 1468 |
) -> np.ndarray:
|
| 1469 |
+
# cache_write_mask: np.ndarray, # [1, 8, 16, 128]
|
| 1470 |
"""Execute one unified Local Talker backbone step via IOBinding.
|
| 1471 |
|
| 1472 |
Returns the last-token hidden state [1, cp_hidden_size] as NumPy.
|
|
|
|
| 1475 |
b = self._local_step_bound
|
| 1476 |
_copy_numpy_to_ortvalue(inputs_embeds, self._local_step_inputs_embeds_ov)
|
| 1477 |
_copy_numpy_to_ortvalue(cache_position, self._local_step_cache_position_ov)
|
| 1478 |
+
_copy_numpy_to_ortvalue(attention_mask, self._local_step_attention_mask_ov)
|
| 1479 |
+
_copy_numpy_to_ortvalue(cos_rope, self._local_step_cos_rope_ov)
|
| 1480 |
+
_copy_numpy_to_ortvalue(sin_rope, self._local_step_sin_rope_ov)
|
| 1481 |
+
# _copy_numpy_to_ortvalue(cache_write_mask, self._local_step_cache_write_mask_ov)
|
| 1482 |
b.run()
|
| 1483 |
return self._local_step_hidden_ov.numpy() # [1, cp_hidden_size]
|
| 1484 |
|
|
|
|
| 1545 |
cache_position = np.array([self._talker_seq_len], dtype=np.int64)
|
| 1546 |
causal_rows = self._causal_tril[:, :, cache_position, :] # [1,1,q_len,MAX]
|
| 1547 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1548 |
+
cos_rope = self._cos_rope[:, :, cache_position].copy()
|
| 1549 |
+
sin_rope = self._sin_rope[:, :, cache_position].copy()
|
| 1550 |
logits = self._run_talker_step(inputs_embeds, cache_position, attn_mask, cos_rope, sin_rope) # [1, vocab]
|
| 1551 |
log.info(f"step-idx-{self._step_idx} logits {logits} {logits.shape} {logits.dtype}")
|
| 1552 |
|
|
|
|
| 1607 |
) # [1, 2, talker_hidden_size]
|
| 1608 |
cache_position_prefill = np.array([0, 1], dtype=np.int64)
|
| 1609 |
|
| 1610 |
+
causal_rows = self._causal_tril_local[:, :, cache_position_prefill, :] # [1,1,q_len,MAX]
|
| 1611 |
+
attn_mask_prefill = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1612 |
+
cos_rope_prefill = self._cos_rope_local[:, cache_position_prefill].copy()
|
| 1613 |
+
sin_rope_prefill = self._sin_rope_local[:, cache_position_prefill].copy()
|
| 1614 |
+
# cache_write_mask_prefill = self._local_cache_write_mask_list[0]
|
| 1615 |
+
|
| 1616 |
# Backbone prefill → last_hidden [1, cp_hidden_size]
|
| 1617 |
+
hidden = self._run_local_prefill(
|
| 1618 |
+
inputs_embeds_prefill,
|
| 1619 |
+
cache_position_prefill,
|
| 1620 |
+
attn_mask_prefill,
|
| 1621 |
+
cos_rope_prefill,
|
| 1622 |
+
sin_rope_prefill,
|
| 1623 |
+
)
|
| 1624 |
+
# cache_write_mask_prefill,
|
| 1625 |
# Batched lm_head → [15, local_vocab_size]; select group 0 (codebook group 1)
|
| 1626 |
all_logits = self._run_local_lm_head(hidden) # [15, local_vocab_size]
|
| 1627 |
logits_g1 = all_logits[0:1, :] # [1, local_vocab_size]
|
|
|
|
| 1645 |
head_idx = step_i - 1 # 1..14 (0-indexed into the 15-row logits tensor)
|
| 1646 |
cache_position_step = np.array([step_i], dtype=np.int64)
|
| 1647 |
|
| 1648 |
+
causal_rows = self._causal_tril_local[:, :, cache_position_step, :] # [1,1,q_len,MAX]
|
| 1649 |
+
attn_mask_step = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1650 |
+
cos_rope_step = self._cos_rope_local[:, cache_position_step].copy()
|
| 1651 |
+
sin_rope_step = self._sin_rope_local[:, cache_position_step].copy()
|
| 1652 |
+
# cache_write_mask_step = self._local_cache_write_mask_list[step_i - 1]
|
| 1653 |
+
|
| 1654 |
# Unified backbone step → last_hidden [1, cp_hidden_size]
|
| 1655 |
hidden = self._run_local_step(
|
| 1656 |
prev_embed.astype(np.float32),
|
| 1657 |
cache_position_step,
|
| 1658 |
+
attn_mask_step,
|
| 1659 |
+
cos_rope_step,
|
| 1660 |
+
sin_rope_step,
|
| 1661 |
)
|
| 1662 |
+
# cache_write_mask_step,
|
| 1663 |
# Batched lm_head → [15, local_vocab_size]; select the current group
|
| 1664 |
all_logits = self._run_local_lm_head(hidden)
|
| 1665 |
logits_gi = all_logits[head_idx : head_idx + 1, :] # [1, local_vocab_size]
|
|
|
|
| 1736 |
causal_rows = self._causal_tril[:, :, cache_pos, :] # [1,1,q_len,MAX]
|
| 1737 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1738 |
for _ in range(n_iter):
|
| 1739 |
+
cos_rope = self._cos_rope[:, :, cache_pos].copy()
|
| 1740 |
+
sin_rope = self._sin_rope[:, :, cache_pos].copy()
|
| 1741 |
t0 = time.perf_counter()
|
| 1742 |
self._run_talker_prefill(dummy_embeds, cache_pos, attn_mask, cos_rope, sin_rope)
|
| 1743 |
times["talker_prefill"].append((time.perf_counter() - t0) * 1000)
|
|
|
|
| 1752 |
cache_pos_step = np.array([_TALKER_PREFILL_LEN + n], dtype=np.int64)
|
| 1753 |
causal_rows = self._causal_tril[:, :, cache_pos_step, :] # [1,1,q_len,MAX]
|
| 1754 |
attn_mask = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1755 |
+
cos_rope = self._cos_rope[:, :, cache_pos_step].copy()
|
| 1756 |
+
sin_rope = self._sin_rope[:, :, cache_pos_step].copy()
|
| 1757 |
t0 = time.perf_counter()
|
| 1758 |
self._run_talker_step(dummy_step_embeds, cache_pos_step, attn_mask, cos_rope, sin_rope)
|
| 1759 |
times["talker_step"].append((time.perf_counter() - t0) * 1000)
|
|
|
|
| 1765 |
log.info("Warming-up local talker prefill...")
|
| 1766 |
dummy_lp_embeds = np.random.randn(1, _LOCAL_PREFILL_LEN, self._local_hidden_size).astype(np.float32)
|
| 1767 |
cache_pos_lp = np.array([0, 1], dtype=np.int64)
|
| 1768 |
+
causal_rows = self._causal_tril_local[:, :, cache_pos_lp, :] # [1,1,q_len,MAX]
|
| 1769 |
+
attn_mask_lp = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1770 |
+
cos_rope_lp = self._cos_rope_local[:, cache_pos_lp].copy()
|
| 1771 |
+
sin_rope_lp = self._sin_rope_local[:, cache_pos_lp].copy()
|
| 1772 |
+
# cache_write_mask_lp = self._local_cache_write_mask_list[0]
|
| 1773 |
for _ in range(n_iter):
|
| 1774 |
t0 = time.perf_counter()
|
| 1775 |
+
self._run_local_prefill(dummy_lp_embeds, cache_pos_lp, attn_mask_lp, cos_rope_lp, sin_rope_lp)
|
| 1776 |
+
# cache_write_mask_lp
|
| 1777 |
times["local_prefill"].append((time.perf_counter() - t0) * 1000)
|
| 1778 |
exec_time_tot = sum(times["local_prefill"]) / 1000
|
| 1779 |
avg_exec_time = exec_time_tot / len(times["local_prefill"]) * 1000
|
|
|
|
| 1786 |
log.info("Warming-up local talker step...")
|
| 1787 |
dummy_ls_embeds = np.random.randn(1, 1, self._hidden_size).astype(np.float32)
|
| 1788 |
cache_pos_ls = np.array([2], dtype=np.int64)
|
| 1789 |
+
causal_rows = self._causal_tril_local[:, :, cache_pos_ls, :] # [1,1,q_len,MAX]
|
| 1790 |
+
attn_mask_ls = np.where(causal_rows, 0.0, -np.inf).astype(np.float32) # [1, 1, q_len, MAX_SEQ_LEN]
|
| 1791 |
+
cos_rope_ls = self._cos_rope_local[:, cache_pos_ls].copy()
|
| 1792 |
+
sin_rope_ls = self._sin_rope_local[:, cache_pos_ls].copy()
|
| 1793 |
+
# cache_write_mask_ls = self._local_cache_write_mask_list[1]
|
| 1794 |
for _ in range(n_iter):
|
| 1795 |
t0 = time.perf_counter()
|
| 1796 |
+
self._run_local_step(dummy_ls_embeds, cache_pos_ls, attn_mask_ls, cos_rope_ls, sin_rope_ls)
|
| 1797 |
+
# cache_write_mask_ls
|
| 1798 |
times["local_step"].append((time.perf_counter() - t0) * 1000)
|
| 1799 |
exec_time_tot = sum(times["local_step"]) / 1000
|
| 1800 |
avg_exec_time = exec_time_tot / len(times["local_step"]) * 1000
|
test_qwen3-tts-streaming_onnx.py
CHANGED
|
@@ -24,12 +24,7 @@ This script demonstrates the full Qwen3-TTS-Streaming-ONNX pipeline by:
|
|
| 24 |
5. Writing the concatenated audio to a WAV file.
|
| 25 |
Usage:
|
| 26 |
python test_qwen3-tts-streaming_onnx.py \
|
| 27 |
-
--
|
| 28 |
-
--talker_local_model_path qwen3-tts_onnx/talker_local_model.onnx \
|
| 29 |
-
--codec_decoder_model_path qwen3-tts_onnx/codec_decoder_model.onnx \
|
| 30 |
-
--speaker_encoder_model_path qwen3-tts_onnx/speaker_encoder_model.onnx \
|
| 31 |
-
--talker_codec_embed_model_path qwen3-tts_onnx/talker_codec_embed_model.onnx \
|
| 32 |
-
--text_embed_proj_model_path qwen3-tts_onnx/text_embed_proj_model.onnx \
|
| 33 |
--model_config_path configs/config.json \
|
| 34 |
--codec_config_path configs/tokenizer_config.json \
|
| 35 |
--preprocessor_config_dir configs/ \
|
|
@@ -281,8 +276,10 @@ def main() -> None:
|
|
| 281 |
suffix = "_int8.onnx" if args.use_int8 else ".onnx"
|
| 282 |
|
| 283 |
# Build model paths
|
| 284 |
-
|
| 285 |
-
|
|
|
|
|
|
|
| 286 |
# Unified backbone step (shared for steps 2..15) and batched lm_head
|
| 287 |
talker_local_lm_head_path = _onnx_path(args.onnx_dir, f"talker_local_lm_head{suffix}")
|
| 288 |
|
|
@@ -294,8 +291,10 @@ def main() -> None:
|
|
| 294 |
|
| 295 |
# Validate required paths
|
| 296 |
required = [
|
| 297 |
-
|
| 298 |
-
|
|
|
|
|
|
|
| 299 |
talker_local_lm_head_path,
|
| 300 |
codec_decoder_path,
|
| 301 |
speaker_encoder_path,
|
|
@@ -312,8 +311,10 @@ def main() -> None:
|
|
| 312 |
|
| 313 |
log.info("Building inferencer...")
|
| 314 |
inferencer = Qwen3TTSInferencerONNX(
|
| 315 |
-
|
| 316 |
-
|
|
|
|
|
|
|
| 317 |
talker_local_lm_head_model_path=talker_local_lm_head_path,
|
| 318 |
codec_decoder_model_path=codec_decoder_path,
|
| 319 |
speaker_encoder_model_path=speaker_encoder_path,
|
|
|
|
| 24 |
5. Writing the concatenated audio to a WAV file.
|
| 25 |
Usage:
|
| 26 |
python test_qwen3-tts-streaming_onnx.py \
|
| 27 |
+
--onnx_dir qwen3-tts_onnx/ \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
--model_config_path configs/config.json \
|
| 29 |
--codec_config_path configs/tokenizer_config.json \
|
| 30 |
--preprocessor_config_dir configs/ \
|
|
|
|
| 276 |
suffix = "_int8.onnx" if args.use_int8 else ".onnx"
|
| 277 |
|
| 278 |
# Build model paths
|
| 279 |
+
talker_prefill_path = _onnx_path(args.onnx_dir, f"talker_model_prefill{suffix}")
|
| 280 |
+
talker_step_path = _onnx_path(args.onnx_dir, f"talker_model_step{suffix}")
|
| 281 |
+
talker_local_prefill_path = _onnx_path(args.onnx_dir, f"talker_local_model_prefill{suffix}")
|
| 282 |
+
talker_local_step_path = _onnx_path(args.onnx_dir, f"talker_local_model_step{suffix}")
|
| 283 |
# Unified backbone step (shared for steps 2..15) and batched lm_head
|
| 284 |
talker_local_lm_head_path = _onnx_path(args.onnx_dir, f"talker_local_lm_head{suffix}")
|
| 285 |
|
|
|
|
| 291 |
|
| 292 |
# Validate required paths
|
| 293 |
required = [
|
| 294 |
+
talker_prefill_path,
|
| 295 |
+
talker_step_path,
|
| 296 |
+
talker_local_prefill_path,
|
| 297 |
+
talker_local_step_path,
|
| 298 |
talker_local_lm_head_path,
|
| 299 |
codec_decoder_path,
|
| 300 |
speaker_encoder_path,
|
|
|
|
| 311 |
|
| 312 |
log.info("Building inferencer...")
|
| 313 |
inferencer = Qwen3TTSInferencerONNX(
|
| 314 |
+
talker_model_prefill_path=talker_prefill_path,
|
| 315 |
+
talker_model_step_path=talker_step_path,
|
| 316 |
+
talker_local_model_prefill_path=talker_local_prefill_path,
|
| 317 |
+
talker_local_model_step_path=talker_local_step_path,
|
| 318 |
talker_local_lm_head_model_path=talker_local_lm_head_path,
|
| 319 |
codec_decoder_model_path=codec_decoder_path,
|
| 320 |
speaker_encoder_model_path=speaker_encoder_path,
|