Prince-1 commited on
Commit
f7a6ee6
·
verified ·
1 Parent(s): 96eec76

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +14 -0
  2. .gitignore +8 -0
  3. README.md +92 -0
  4. common.py +312 -0
  5. cpu_fp16/acoustic_connector.onnx +3 -0
  6. cpu_fp16/acoustic_decoder.onnx +3 -0
  7. cpu_fp16/acoustic_encoder.onnx +3 -0
  8. cpu_fp16/chat_template.jinja +54 -0
  9. cpu_fp16/diffusion_head.onnx +3 -0
  10. cpu_fp16/genai_config.json +49 -0
  11. cpu_fp16/llm_decoder.onnx +3 -0
  12. cpu_fp16/llm_decoder.onnx.data +3 -0
  13. cpu_fp16/semantic_connector.onnx +3 -0
  14. cpu_fp16/semantic_encoder.onnx +3 -0
  15. cpu_fp16/tokenizer.json +3 -0
  16. cpu_fp16/tokenizer_config.json +30 -0
  17. cpu_fp32/acoustic_connector.onnx +3 -0
  18. cpu_fp32/acoustic_decoder.onnx +3 -0
  19. cpu_fp32/acoustic_encoder.onnx +3 -0
  20. cpu_fp32/chat_template.jinja +54 -0
  21. cpu_fp32/diffusion_head.onnx +3 -0
  22. cpu_fp32/genai_config.json +48 -0
  23. cpu_fp32/llm_decoder.onnx +3 -0
  24. cpu_fp32/llm_decoder.onnx.data +3 -0
  25. cpu_fp32/semantic_connector.onnx +3 -0
  26. cpu_fp32/semantic_encoder.onnx +3 -0
  27. cpu_fp32/tokenizer.json +3 -0
  28. cpu_fp32/tokenizer_config.json +30 -0
  29. cpu_int4/acoustic_connector.onnx +3 -0
  30. cpu_int4/acoustic_decoder.onnx +3 -0
  31. cpu_int4/acoustic_encoder.onnx +3 -0
  32. cpu_int4/chat_template.jinja +54 -0
  33. cpu_int4/diffusion_head.onnx +3 -0
  34. cpu_int4/genai_config.json +48 -0
  35. cpu_int4/llm_decoder.onnx +3 -0
  36. cpu_int4/llm_decoder.onnx.data +3 -0
  37. cpu_int4/semantic_connector.onnx +3 -0
  38. cpu_int4/semantic_encoder.onnx +3 -0
  39. cpu_int4/tokenizer.json +3 -0
  40. cpu_int4/tokenizer_config.json +30 -0
  41. eval.py +243 -0
  42. figures/Fig1.png +3 -0
  43. gpu_fp16/acoustic_connector.onnx +3 -0
  44. gpu_fp16/acoustic_decoder.onnx +3 -0
  45. gpu_fp16/acoustic_encoder.onnx +3 -0
  46. gpu_fp16/chat_template.jinja +54 -0
  47. gpu_fp16/diffusion_head.onnx +3 -0
  48. gpu_fp16/genai_config.json +55 -0
  49. gpu_fp16/llm_decoder.onnx +3 -0
  50. gpu_fp16/llm_decoder.onnx.data +3 -0
.gitattributes CHANGED
@@ -33,3 +33,17 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.jpg filter=lfs diff=lfs merge=lfs -text
37
+ *.png filter=lfs diff=lfs merge=lfs -text
38
+ cpu_fp16/llm_decoder.onnx.data filter=lfs diff=lfs merge=lfs -text
39
+ cpu_fp16/tokenizer.json filter=lfs diff=lfs merge=lfs -text
40
+ cpu_fp32/llm_decoder.onnx.data filter=lfs diff=lfs merge=lfs -text
41
+ cpu_fp32/tokenizer.json filter=lfs diff=lfs merge=lfs -text
42
+ cpu_int4/llm_decoder.onnx.data filter=lfs diff=lfs merge=lfs -text
43
+ cpu_int4/tokenizer.json filter=lfs diff=lfs merge=lfs -text
44
+ gpu_fp16/llm_decoder.onnx.data filter=lfs diff=lfs merge=lfs -text
45
+ gpu_fp16/tokenizer.json filter=lfs diff=lfs merge=lfs -text
46
+ gpu_fp32/llm_decoder.onnx.data filter=lfs diff=lfs merge=lfs -text
47
+ gpu_fp32/tokenizer.json filter=lfs diff=lfs merge=lfs -text
48
+ gpu_int4/llm_decoder.onnx.data filter=lfs diff=lfs merge=lfs -text
49
+ gpu_int4/tokenizer.json filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Downloaded checkpoint + intermediate/build artifacts
2
+ model/
3
+ cache/
4
+ cpu_int4/models/*.onnx
5
+ cpu_int4/models/*.onnx.data
6
+ _genai_*/
7
+ __pycache__/
8
+ *.pyc
README.md ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ - zh
5
+ license: mit
6
+ pipeline_tag: text-to-speech
7
+ tags:
8
+ - Podcast
9
+ - onnx
10
+ - onnxruntime
11
+ library_name: onnxruntime
12
+ base_model:
13
+ - microsoft/VibeVoice-1.5B
14
+ ---
15
+
16
+ ## VibeVoice: A Frontier Open-Source Text-to-Speech Model
17
+
18
+ VibeVoice is a novel framework designed for generating expressive, long-form, multi-speaker conversational audio, such as podcasts, from text. It addresses significant challenges in traditional Text-to-Speech (TTS) systems, particularly in scalability, speaker consistency, and natural turn-taking.
19
+
20
+ A core innovation of VibeVoice is its use of continuous speech tokenizers (Acoustic and Semantic) operating at an ultra-low frame rate of 7.5 Hz. These tokenizers efficiently preserve audio fidelity while significantly boosting computational efficiency for processing long sequences. VibeVoice employs a next-token diffusion framework, leveraging a Large Language Model (LLM) to understand textual context and dialogue flow, and a diffusion head to generate high-fidelity acoustic details.
21
+
22
+ The model can synthesize speech up to **90 minutes** long with up to **4 distinct speakers**, surpassing the typical 1-2 speaker limits of many prior models.
23
+
24
+ ➡️ **Technical Report:** [VibeVoice Technical Report](https://arxiv.org/abs/2508.19205)
25
+
26
+ ➡️ **Project Page:** [microsoft/VibeVoice](https://microsoft.github.io/VibeVoice)
27
+
28
+ ➡️ **Code:** [microsoft/VibeVoice-Code](https://github.com/microsoft/VibeVoice)
29
+
30
+ <p align="left">
31
+ <img src="figures/Fig1.png" alt="VibeVoice Overview" height="250px">
32
+ </p>
33
+
34
+ ## Training Details
35
+ Transformer-based Large Language Model (LLM) integrated with specialized acoustic and semantic tokenizers and a diffusion-based decoding head.
36
+ - LLM: [Qwen2.5-1.5B](https://huggingface.co/Qwen/Qwen2.5-1.5B) for this release.
37
+ - Tokenizers:
38
+ - Acoustic Tokenizer: Based on a σ-VAE variant (proposed in [LatentLM](https://arxiv.org/pdf/2412.08635)), with a mirror-symmetric encoder-decoder structure featuring 7 stages of modified Transformer blocks. Achieves 3200x downsampling from 24kHz input. Encoder/decoder components are ~340M parameters each.
39
+ - Semantic Tokenizer: Encoder mirrors the Acoustic Tokenizer's architecture (without VAE components). Trained with an ASR proxy task.
40
+ - Diffusion Head: Lightweight module (4 layers, ~123M parameters) conditioned on LLM hidden states. Predicts acoustic VAE features using a Denoising Diffusion Probabilistic Models (DDPM) process. Uses Classifier-Free Guidance (CFG) and DPM-Solver (and variants) during inference.
41
+ - Context Length: Trained with a curriculum increasing up to 65,536 tokens.
42
+ - Training Stages:
43
+ - Tokenizer Pre-training: Acoustic and Semantic tokenizers are pre-trained separately.
44
+ - VibeVoice Training: Pre-trained tokenizers are frozen; only the LLM and diffusion head parameters are trained. A curriculum learning strategy is used for input sequence length (4k -> 16K -> 32K -> 64K). Text tokenizer not explicitly specified, but the LLM (Qwen2.5) typically uses its own. Audio is "tokenized" via the acoustic and semantic tokenizers.
45
+
46
+
47
+ ## Models
48
+ | Model | Context Length | Generation Length | Weight |
49
+ |-------|----------------|----------|----------|
50
+ | VibeVoice-0.5B-Streaming | - | - | [HF link](https://huggingface.co/microsoft/VibeVoice-Realtime-0.5B) |
51
+ | VibeVoice-1.5B | 64K | ~90 min | You are here. |
52
+ | VibeVoice-Large| 32K | ~45 min | Disabled |
53
+
54
+ ## Installation and Usage
55
+
56
+ Please refer to [GitHub README](https://github.com/microsoft/VibeVoice?tab=readme-ov-file#installation)
57
+
58
+ ## Responsible Usage
59
+ ### Direct intended uses
60
+ The VibeVoice model is limited to research purpose use exploring highly realistic audio dialogue generation detailed in the [tech report](https://arxiv.org/pdf/2508.19205).
61
+
62
+ ### Out-of-scope uses
63
+ Use in any manner that violates applicable laws or regulations (including trade compliance laws). Use in any other way that is prohibited by MIT License. Use to generate any text transcript. Furthermore, this release is not intended or licensed for any of the following scenarios:
64
+
65
+ - Voice impersonation without explicit, recorded consent – cloning a real individual’s voice for satire, advertising, ransom, social‑engineering, or authentication bypass.
66
+ - Disinformation or impersonation – creating audio presented as genuine recordings of real people or events.
67
+ - Real‑time or low‑latency voice conversion – telephone or video‑conference “live deep‑fake” applications.
68
+ - Unsupported language – the model is trained only on English and Chinese data; outputs in other languages are unsupported and may be unintelligible or offensive.
69
+ - Generation of background ambience, Foley, or music – VibeVoice is speech‑only and will not produce coherent non‑speech audio.
70
+
71
+
72
+ ## Risks and limitations
73
+ While efforts have been made to optimize it through various techniques, it may still produce outputs that are unexpected, biased, or inaccurate. VibeVoice inherits any biases, errors, or omissions produced by its base model (specifically, Qwen2.5 1.5b in this release).
74
+ Potential for Deepfakes and Disinformation: High-quality synthetic speech can be misused to create convincing fake audio content for impersonation, fraud, or spreading disinformation. Users must ensure transcripts are reliable, check content accuracy, and avoid using generated content in misleading ways. Users are expected to use the generated content and to deploy the models in a lawful manner, in full compliance with all applicable laws and regulations in the relevant jurisdictions. It is best practice to disclose the use of AI when sharing AI-generated content.
75
+ English and Chinese only: Transcripts in language other than English or Chinese may result in unexpected audio outputs.
76
+ Non-Speech Audio: The model focuses solely on speech synthesis and does not handle background noise, music, or other sound effects.
77
+ Overlapping Speech: The current model does not explicitly model or generate overlapping speech segments in conversations.
78
+
79
+
80
+ ## Recommendations
81
+ We do not recommend using VibeVoice in commercial or real-world applications without further testing and development. This model is intended for research and development purposes only. Please use responsibly.
82
+
83
+ To mitigate the risks of misuse, we have:
84
+ Embedded an audible disclaimer (e.g. “This segment was generated by AI”) automatically into every synthesized audio file.
85
+ Added an imperceptible watermark to generated audio so third parties can verify VibeVoice provenance. Please see contact information at the end of this model card.
86
+ Logged inference requests (hashed) for abuse pattern detection and publishing aggregated statistics quarterly.
87
+ Users are responsible for sourcing their datasets legally and ethically. This may include securing appropriate rights and/or anonymizing data prior to use with VibeVoice. Users are reminded to be mindful of data privacy concerns.
88
+
89
+
90
+ ## Contact
91
+ This project was conducted by members of Microsoft Research. We welcome feedback and collaboration from our audience. If you have suggestions, questions, or observe unexpected/offensive behavior in our technology, please contact us at VibeVoice@microsoft.com.
92
+ If the team receives reports of undesired behavior or identifies issues independently, we will update this repository with appropriate mitigations.
common.py ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Shared building blocks for VibeVoice ONNX inference (TTS / ASR / Realtime).
2
+
3
+ The three drivers (inference.py, inference_asr.py, inference_realtime.py) all lean on the
4
+ same primitives, factored here:
5
+
6
+ * resolve() — model key + checkpoint src + ONNX dir (reuses optimize.py's registry)
7
+ * OnnxLLM — drives the genai-exported llm_decoder.onnx directly via onnxruntime,
8
+ managing the 28×(k,v) KV cache + growing attention_mask. Works for
9
+ BOTH the TTS backbone (outputs hidden_states) and — with lm_head kept —
10
+ the ASR decoder. One prefill(embeds)->hidden + step(embeds)->hidden loop.
11
+ * OnnxOp — thin wrapper over a single-file ONNX session (encoders/decoder/
12
+ connector/diffusion_head/projector).
13
+ * DiffusionSampler — the DDPM/DPM denoise loop (diffusion_head.onnx + codes/ scheduler + CFG).
14
+ * audio load / normalize (-25 dBFS) / save — 24 kHz mono (VibeVoice standard).
15
+ * load_tokenizer, load_scaling — Qwen2.5 tokenizer + the stored speech scaling/bias factors.
16
+
17
+ These wrap the ALREADY-verified ONNX sub-parts (see eval.py); they don't re-load PyTorch.
18
+ Bit-exact TTS text prompts require the original VibeVoice processor/tokenizer assets (the repos
19
+ ship none — we fetch the plain Qwen2.5 tokenizer); where that matters it's called out in the driver.
20
+ """
21
+ import glob
22
+ import json
23
+ import sys
24
+ import types
25
+ from pathlib import Path
26
+
27
+ import numpy as np
28
+
29
+ HERE = Path(__file__).parent
30
+ sys.path.insert(0, str(HERE))
31
+ for _s in (sys.stdout, sys.stderr):
32
+ try: _s.reconfigure(encoding="utf-8", errors="replace")
33
+ except Exception: pass
34
+
35
+ import optimize as O
36
+
37
+ SR = 24000 # VibeVoice sample rate
38
+ TARGET_DB_FS = -25.0
39
+ VAE_DIM = 64
40
+
41
+
42
+ # --------------------------------------------------------------------------- resolve / io
43
+ def resolve(model_arg, device="cpu", precision="int4", onnx_dir=None):
44
+ key, src = O.resolve_target(model_arg)
45
+ od = Path(onnx_dir) if onnx_dir else (src / f"{device}_{precision}" / "models")
46
+ return key, src, od
47
+
48
+
49
+ # Friendly model ids for display.
50
+ MODEL_IDS = {
51
+ "1.5b": "microsoft/VibeVoice-1.5B",
52
+ "asr": "microsoft/VibeVoice-ASR",
53
+ "asr-hf": "microsoft/VibeVoice-ASR-HF",
54
+ "realtime": "microsoft/VibeVoice-Realtime-0.5B",
55
+ }
56
+
57
+
58
+ def resolve_from_path(model_path):
59
+ """Inference input: a built ONNX dir in the new layout onnx/{key}/{device}_{precision}
60
+ (e.g. onnx/asr/cuda_fp16). Also accepts the legacy <checkpoint>/{device}_{precision}[/models].
61
+
62
+ Returns (key, src_checkpoint, onnx_dir, device, precision, model_id). SystemExit on bad path.
63
+ """
64
+ p = Path(model_path).expanduser().resolve()
65
+ if not p.exists():
66
+ raise SystemExit(f"path does not exist: {p} (build it: uv run optimize.py <model>)")
67
+ if list(p.glob("*.onnx")):
68
+ onnx_dir = p
69
+ elif (p / "models").is_dir() and list((p / "models").glob("*.onnx")):
70
+ onnx_dir = p / "models"
71
+ else:
72
+ raise SystemExit(f"no .onnx files under {p} — pass a built dir, "
73
+ f"e.g. onnx/asr/cuda_fp16 (run: uv run optimize.py <model>)")
74
+ dp = onnx_dir.parent if onnx_dir.name == "models" else onnx_dir
75
+ device, sep, precision = dp.name.partition("_")
76
+ if not sep or device not in ("cpu", "cuda"):
77
+ raise SystemExit(f"cannot parse device/precision from '{dp.name}' — expected "
78
+ f"'<device>_<precision>' (e.g. cpu_int4, cuda_fp16)")
79
+ if dp.parent.name in O.MODELS: # new layout: onnx/{key}/{dev}_{prec}
80
+ key = dp.parent.name
81
+ src = (HERE / O.MODELS[key]["dir"]).resolve()
82
+ elif (dp.parent / "config.json").exists(): # legacy: <checkpoint>/{dev}_{prec}[/models]
83
+ src = dp.parent
84
+ key = O.detect_model_type(src)
85
+ else:
86
+ raise SystemExit(f"cannot locate the checkpoint for {dp} — expected an onnx/<key>/... layout "
87
+ f"or a config.json in {dp.parent}")
88
+ if not (src / "config.json").exists():
89
+ raise SystemExit(f"checkpoint dir missing config.json: {src}")
90
+ return key, src, onnx_dir, device, precision, MODEL_IDS.get(key, key)
91
+
92
+
93
+ def _ort():
94
+ import onnxruntime as ort
95
+ return ort
96
+
97
+
98
+ def _providers(device):
99
+ return ["CUDAExecutionProvider", "CPUExecutionProvider"] if device == "cuda" else ["CPUExecutionProvider"]
100
+
101
+
102
+ class OnnxOp:
103
+ """Single-input/-output-ish ONNX op. run(**named_np) -> first output array."""
104
+ def __init__(self, path, device="cpu"):
105
+ self.sess = _ort().InferenceSession(str(path), providers=_providers(device))
106
+ self.inames = [i.name for i in self.sess.get_inputs()]
107
+
108
+ def run(self, **feed):
109
+ feed = {k: np.asarray(v, dtype=np.float32) if v.dtype != np.int64 else v for k, v in feed.items()}
110
+ return self.sess.run(None, {k: feed[k] for k in self.inames})[0]
111
+
112
+
113
+ # --------------------------------------------------------------------------- audio
114
+ def load_audio(path, sr=SR):
115
+ import soundfile as sf
116
+ wav, in_sr = sf.read(path, dtype="float32", always_2d=False)
117
+ if wav.ndim > 1:
118
+ wav = wav.mean(1)
119
+ if in_sr != sr:
120
+ import librosa
121
+ wav = librosa.resample(wav, orig_sr=in_sr, target_sr=sr)
122
+ return wav.astype(np.float32)
123
+
124
+
125
+ def normalize_audio(wav, target_db_fs=TARGET_DB_FS, eps=1e-6):
126
+ rms = np.sqrt(np.mean(wav ** 2)) + eps
127
+ wav = wav * (10 ** (target_db_fs / 20) / rms)
128
+ peak = np.abs(wav).max()
129
+ if peak > 0.99:
130
+ wav = wav * (0.99 / peak)
131
+ return wav.astype(np.float32)
132
+
133
+
134
+ def save_wav(path, wav, sr=SR):
135
+ import soundfile as sf
136
+ wav = np.asarray(wav, dtype=np.float32).ravel()
137
+ sf.write(str(path), wav, sr)
138
+ return path
139
+
140
+
141
+ # --------------------------------------------------------------------------- tokenizer / scaling
142
+ def load_tokenizer(onnx_dir, src):
143
+ """Qwen2.5 tokenizer saved next to the ONNX (by ModelBuilder) or the standalone dir."""
144
+ from transformers import AutoTokenizer
145
+ for cand in (onnx_dir, onnx_dir.parent.parent, src):
146
+ if (Path(cand) / "tokenizer.json").exists() or (Path(cand) / "tokenizer_config.json").exists():
147
+ return AutoTokenizer.from_pretrained(str(cand))
148
+ return AutoTokenizer.from_pretrained("Qwen/Qwen2.5-1.5B")
149
+
150
+
151
+ def load_scaling(src):
152
+ """model.speech_scaling_factor / model.speech_bias_factor (stored scalars) or (1.0, 0.0)."""
153
+ from safetensors.torch import load_file
154
+ scale, bias = 1.0, 0.0
155
+ for sf in glob.glob(str(Path(src) / "*.safetensors")):
156
+ d = load_file(sf)
157
+ for k, v in d.items():
158
+ if k.endswith("speech_scaling_factor"):
159
+ scale = float(v.reshape(-1)[0])
160
+ elif k.endswith("speech_bias_factor"):
161
+ bias = float(v.reshape(-1)[0])
162
+ return scale, bias
163
+
164
+
165
+ # --------------------------------------------------------------------------- codes/ scheduler
166
+ def make_scheduler(diffusion_cfg):
167
+ """Instantiate codes/ DPMSolverMultistepScheduler from a diffusion_head_config dict."""
168
+ for name, sub in [("vibevoice", ""), ("vibevoice.schedule", "schedule")]:
169
+ m = types.ModuleType(name); m.__path__ = [str(HERE / "codes" / "vibevoice" / sub)]
170
+ sys.modules.setdefault(name, m)
171
+ import importlib
172
+ dpm = importlib.import_module("vibevoice.schedule.dpm_solver")
173
+ beta = diffusion_cfg.get("ddpm_beta_schedule", "cosine")
174
+ return dpm.DPMSolverMultistepScheduler(
175
+ num_train_timesteps=diffusion_cfg.get("ddpm_num_steps", 1000),
176
+ beta_schedule=beta,
177
+ prediction_type=diffusion_cfg.get("prediction_type", "v_prediction"),
178
+ algorithm_type="dpmsolver++",
179
+ )
180
+
181
+
182
+ class DiffusionSampler:
183
+ """DDPM/DPM sampling of one acoustic latent per frame via diffusion_head.onnx + CFG.
184
+
185
+ condition/neg_condition: [H] float32 (LLM hidden state / negative). Returns latent [B,64]."""
186
+ def __init__(self, head_op: OnnxOp, diffusion_cfg, device="cpu"):
187
+ self.head = head_op
188
+ self.cfg = diffusion_cfg
189
+ self.steps = int(diffusion_cfg.get("ddpm_num_inference_steps", 20))
190
+
191
+ def sample(self, condition, neg_condition=None, cfg_scale=1.3, n_frames=1, seed=0):
192
+ import torch
193
+ sched = make_scheduler(self.cfg)
194
+ sched.set_timesteps(self.steps)
195
+ rng = np.random.default_rng(seed)
196
+ cond = np.asarray(condition, dtype=np.float32).reshape(1, -1).repeat(n_frames, 0)
197
+ use_cfg = neg_condition is not None and cfg_scale != 1.0
198
+ if use_cfg:
199
+ neg = np.asarray(neg_condition, dtype=np.float32).reshape(1, -1).repeat(n_frames, 0)
200
+ cond_all = np.concatenate([cond, neg], 0) # [2n, H]: cond half, uncond half
201
+ else:
202
+ cond_all = cond
203
+ # ONE sample of n frames. CFG runs the SAME sample through both cond and uncond branches
204
+ # (duplicate for the head call only) — the reference does this each step; denoising must not
205
+ # mix guidance with a noise difference between two independent samples.
206
+ x = rng.standard_normal((n_frames, VAE_DIM)).astype(np.float32)
207
+ for t in sched.timesteps:
208
+ xin = np.concatenate([x, x], 0) if use_cfg else x
209
+ tf = np.full((xin.shape[0],), float(t), dtype=np.float32)
210
+ eps = self.head.run(noisy_images=xin, timesteps=tf, condition=cond_all)
211
+ if use_cfg:
212
+ c, u = np.split(eps, 2, 0)
213
+ eps = u + cfg_scale * (c - u) # [n, 64]
214
+ out = sched.step(torch.from_numpy(eps), t, torch.from_numpy(x))
215
+ x = out.prev_sample.numpy().astype(np.float32)
216
+ return x
217
+
218
+
219
+ # --------------------------------------------------------------------------- LLM (raw ORT KV cache)
220
+ class OnnxLLM:
221
+ """Drives a genai-exported decoder (llm_decoder.onnx) directly via onnxruntime.
222
+
223
+ Inputs: inputs_embeds[B,S,H], attention_mask[B,T], past_key_values.{i}.{key,value}[B,kv,P,hd]
224
+ Outputs: hidden_states[B,S,H], present.{i}.{key,value}
225
+ Rotary/positions are computed inside the GQA op from the attention_mask, so we only grow a
226
+ ones mask. Stateful: prefill(embeds) then step(embeds); .hidden holds the last hidden states."""
227
+ def __init__(self, path, device="cpu"):
228
+ import onnx
229
+ self.sess = _ort().InferenceSession(str(path), providers=_providers(device))
230
+ g = onnx.load(str(path), load_external_data=False).graph
231
+ self.in_names = [i.name for i in self.sess.get_inputs()]
232
+ kv = [n for n in self.in_names if n.startswith("past_key_values.")]
233
+ self.n_layers = len({n.split(".")[1] for n in kv})
234
+ shp = next(i for i in g.input if i.name == "past_key_values.0.key").type.tensor_type.shape.dim
235
+ self.kv_heads = shp[1].dim_value
236
+ self.head_dim = shp[3].dim_value
237
+ outs = [o.name for o in self.sess.get_outputs()]
238
+ # TTS backbone emits 'hidden_states'; an ASR decoder that kept lm_head emits 'logits'.
239
+ self.out_name = "logits" if "logits" in outs else "hidden_states"
240
+ self.hidden = None
241
+ self._reset()
242
+
243
+ def _reset(self, batch=1):
244
+ z = np.zeros((batch, self.kv_heads, 0, self.head_dim), dtype=np.float32)
245
+ self.past = {}
246
+ for i in range(self.n_layers):
247
+ self.past[f"past_key_values.{i}.key"] = z.copy()
248
+ self.past[f"past_key_values.{i}.value"] = z.copy()
249
+ self.total = 0
250
+ self.batch = batch
251
+
252
+ def _run(self, embeds):
253
+ embeds = np.asarray(embeds, dtype=np.float32)
254
+ b, s, _ = embeds.shape
255
+ self.total += s
256
+ feed = {"inputs_embeds": embeds,
257
+ "attention_mask": np.ones((b, self.total), dtype=np.int64)}
258
+ feed.update(self.past)
259
+ outs = self.sess.run(None, feed)
260
+ names = [o.name for o in self.sess.get_outputs()]
261
+ out = dict(zip(names, outs))
262
+ for i in range(self.n_layers):
263
+ self.past[f"past_key_values.{i}.key"] = out[f"present.{i}.key"]
264
+ self.past[f"past_key_values.{i}.value"] = out[f"present.{i}.value"]
265
+ self.hidden = out[self.out_name]
266
+ return self.hidden
267
+
268
+ def prefill(self, inputs_embeds):
269
+ """inputs_embeds [B,S,H] -> hidden [B,S,H]. Resets state to a fresh sequence."""
270
+ self._reset(batch=inputs_embeds.shape[0])
271
+ return self._run(inputs_embeds)
272
+
273
+ def step(self, inputs_embeds):
274
+ """inputs_embeds [B,s,H] appended to the running KV cache -> hidden [B,s,H]."""
275
+ return self._run(inputs_embeds)
276
+
277
+
278
+ # The exact embed_tokens key per model — the ONNX decoder excludes embeddings, so inference looks
279
+ # them up here. Realtime ships BOTH a base language_model AND a tts_language_model embed table (they
280
+ # differ); the exported decoder is the tts backbone, so we must match that exact key, not first-win.
281
+ EMBED_KEY = {
282
+ "1.5b": "model.language_model.embed_tokens.weight",
283
+ "asr": "model.language_model.embed_tokens.weight",
284
+ "asr-hf": "language_model.model.embed_tokens.weight",
285
+ "realtime": "model.tts_language_model.embed_tokens.weight",
286
+ }
287
+
288
+
289
+ def embed_tokens(src, token_ids, model_key):
290
+ """Look up token embeddings for the exported decoder of `model_key`.
291
+ Returns [1, len, H] float32. token_ids: 1-D list/array."""
292
+ from safetensors.torch import load_file
293
+ key = EMBED_KEY.get(model_key)
294
+ if key is None:
295
+ raise RuntimeError(f"no embed_tokens key mapping for model '{model_key}'")
296
+ ids = np.asarray(token_ids, dtype=np.int64).ravel()
297
+ for sf in glob.glob(str(Path(src) / "*.safetensors")):
298
+ d = load_file(sf)
299
+ if key in d:
300
+ return d[key].float().numpy()[ids][None].astype(np.float32)
301
+ raise RuntimeError(f"{key} not found in {src}")
302
+
303
+
304
+ def acoustic_decode_to_wav(dec_op: OnnxOp, latents, scale, bias):
305
+ """latents [B,T,64] (LLM-space) -> waveform. Applies /scale - bias then acoustic_decoder."""
306
+ lat = (np.asarray(latents, dtype=np.float32) / (scale if scale else 1.0)) - bias
307
+ return dec_op.run(latents=lat)
308
+
309
+
310
+ def component_path(onnx_dir, comp):
311
+ p = Path(onnx_dir) / f"{comp}.onnx"
312
+ return p if p.exists() else None
cpu_fp16/acoustic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9cf54e4869bbfe70ea74b784f3d67597b0691b3eac5f23b9213e86cdb5a1e4b6
3
+ size 4936693
cpu_fp16/acoustic_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b9b59b84ea79d1de3d8c6a477822377437bbba2fe096d74ee913233482bf1fef
3
+ size 688798049
cpu_fp16/acoustic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:df85a2dbd67230632bfe2c517c55f5c481bab7cca8b89164f1411885414f2f7e
3
+ size 688593181
cpu_fp16/chat_template.jinja ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0]['role'] == 'system' %}
4
+ {{- messages[0]['content'] }}
5
+ {%- else %}
6
+ {{- 'You are a helpful assistant.' }}
7
+ {%- endif %}
8
+ {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
9
+ {%- for tool in tools %}
10
+ {{- "\n" }}
11
+ {{- tool | tojson }}
12
+ {%- endfor %}
13
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
14
+ {%- else %}
15
+ {%- if messages[0]['role'] == 'system' %}
16
+ {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
17
+ {%- else %}
18
+ {{- '<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n' }}
19
+ {%- endif %}
20
+ {%- endif %}
21
+ {%- for message in messages %}
22
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}
23
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
24
+ {%- elif message.role == "assistant" %}
25
+ {{- '<|im_start|>' + message.role }}
26
+ {%- if message.content %}
27
+ {{- '\n' + message.content }}
28
+ {%- endif %}
29
+ {%- for tool_call in message.tool_calls %}
30
+ {%- if tool_call.function is defined %}
31
+ {%- set tool_call = tool_call.function %}
32
+ {%- endif %}
33
+ {{- '\n<tool_call>\n{"name": "' }}
34
+ {{- tool_call.name }}
35
+ {{- '", "arguments": ' }}
36
+ {{- tool_call.arguments | tojson }}
37
+ {{- '}\n</tool_call>' }}
38
+ {%- endfor %}
39
+ {{- '<|im_end|>\n' }}
40
+ {%- elif message.role == "tool" %}
41
+ {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
42
+ {{- '<|im_start|>user' }}
43
+ {%- endif %}
44
+ {{- '\n<tool_response>\n' }}
45
+ {{- message.content }}
46
+ {{- '\n</tool_response>' }}
47
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
48
+ {{- '<|im_end|>\n' }}
49
+ {%- endif %}
50
+ {%- endif %}
51
+ {%- endfor %}
52
+ {%- if add_generation_prompt %}
53
+ {{- '<|im_start|>assistant\n' }}
54
+ {%- endif %}
cpu_fp16/diffusion_head.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:97659f98af3bbcbeac37a544b08d8baaf4c7a431f0b2d47a595ae31e861ca2d8
3
+ size 246711153
cpu_fp16/genai_config.json ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": {
3
+ "bos_token_id": 1,
4
+ "context_length": 65536,
5
+ "decoder": {
6
+ "session_options": {
7
+ "log_id": "onnxruntime-genai",
8
+ "provider_options": []
9
+ },
10
+ "filename": "llm_decoder.onnx",
11
+ "head_size": 128,
12
+ "hidden_size": 1536,
13
+ "inputs": {
14
+ "inputs_embeds": "inputs_embeds",
15
+ "attention_mask": "attention_mask",
16
+ "position_ids": "position_ids",
17
+ "past_key_names": "past_key_values.%d.key",
18
+ "past_value_names": "past_key_values.%d.value"
19
+ },
20
+ "outputs": {
21
+ "present_key_names": "present.%d.key",
22
+ "present_value_names": "present.%d.value"
23
+ },
24
+ "num_attention_heads": 12,
25
+ "num_hidden_layers": 28,
26
+ "num_key_value_heads": 2
27
+ },
28
+ "eos_token_id": null,
29
+ "pad_token_id": null,
30
+ "type": "qwen2",
31
+ "vocab_size": 151936
32
+ },
33
+ "search": {
34
+ "diversity_penalty": 0.0,
35
+ "do_sample": false,
36
+ "early_stopping": true,
37
+ "length_penalty": 1.0,
38
+ "max_length": 65536,
39
+ "min_length": 0,
40
+ "no_repeat_ngram_size": 0,
41
+ "num_beams": 1,
42
+ "num_return_sequences": 1,
43
+ "past_present_share_buffer": false,
44
+ "repetition_penalty": 1.0,
45
+ "temperature": 1.0,
46
+ "top_k": 50,
47
+ "top_p": 1.0
48
+ }
49
+ }
cpu_fp16/llm_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:71f5c2d4e8ab8c4bb0011d1fa26c715774d3d29f9c2a7e45c2c9f8ccbfdc61ba
3
+ size 693048
cpu_fp16/llm_decoder.onnx.data ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d72b898d2f9c5d623df4d932ca989eff9f6c90ef8dca33f1374fabc719be891f
3
+ size 2637496320
cpu_fp16/semantic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:829d24a680c7f68c496a2d0274965303e71a13351c0527de099e5466e06e7717
3
+ size 5133304
cpu_fp16/semantic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0aad94f6d44dd4f20a570a5b2c17c9b2d4668f2dacb59a70e2c88e3c01ac0f91
3
+ size 690443001
cpu_fp16/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3fd169731d2cbde95e10bf356d66d5997fd885dd8dbb6fb4684da3f23b2585d8
3
+ size 11421892
cpu_fp16/tokenizer_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|endoftext|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "is_local": true,
24
+ "local_files_only": false,
25
+ "model_max_length": 65536,
26
+ "pad_token": "<|endoftext|>",
27
+ "split_special_tokens": false,
28
+ "tokenizer_class": "Qwen2Tokenizer",
29
+ "unk_token": null
30
+ }
cpu_fp32/acoustic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bf7183835daf1959ab105f4886b3a9867a0b65fe95c93ea832b46c0dd4e3d4d2
3
+ size 9861072
cpu_fp32/acoustic_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:15625fabb679e4bf01138118e7349e055e2e3dfd8b4546b1c108c09ad0ca160e
3
+ size 1376190019
cpu_fp32/acoustic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a6d5a0f7cfd27e06e39a6f11bcbc1abba63245e9e6b256b407e2d43bd67396ad
3
+ size 1375985271
cpu_fp32/chat_template.jinja ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0]['role'] == 'system' %}
4
+ {{- messages[0]['content'] }}
5
+ {%- else %}
6
+ {{- 'You are a helpful assistant.' }}
7
+ {%- endif %}
8
+ {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
9
+ {%- for tool in tools %}
10
+ {{- "\n" }}
11
+ {{- tool | tojson }}
12
+ {%- endfor %}
13
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
14
+ {%- else %}
15
+ {%- if messages[0]['role'] == 'system' %}
16
+ {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
17
+ {%- else %}
18
+ {{- '<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n' }}
19
+ {%- endif %}
20
+ {%- endif %}
21
+ {%- for message in messages %}
22
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}
23
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
24
+ {%- elif message.role == "assistant" %}
25
+ {{- '<|im_start|>' + message.role }}
26
+ {%- if message.content %}
27
+ {{- '\n' + message.content }}
28
+ {%- endif %}
29
+ {%- for tool_call in message.tool_calls %}
30
+ {%- if tool_call.function is defined %}
31
+ {%- set tool_call = tool_call.function %}
32
+ {%- endif %}
33
+ {{- '\n<tool_call>\n{"name": "' }}
34
+ {{- tool_call.name }}
35
+ {{- '", "arguments": ' }}
36
+ {{- tool_call.arguments | tojson }}
37
+ {{- '}\n</tool_call>' }}
38
+ {%- endfor %}
39
+ {{- '<|im_end|>\n' }}
40
+ {%- elif message.role == "tool" %}
41
+ {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
42
+ {{- '<|im_start|>user' }}
43
+ {%- endif %}
44
+ {{- '\n<tool_response>\n' }}
45
+ {{- message.content }}
46
+ {{- '\n</tool_response>' }}
47
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
48
+ {{- '<|im_end|>\n' }}
49
+ {%- endif %}
50
+ {%- endif %}
51
+ {%- endfor %}
52
+ {%- if add_generation_prompt %}
53
+ {{- '<|im_start|>assistant\n' }}
54
+ {%- endif %}
cpu_fp32/diffusion_head.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:063928366830acd04eb21b15fb3f05a08a064d0c077e49dd30a2bfe2901f505e
3
+ size 493270097
cpu_fp32/genai_config.json ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": {
3
+ "bos_token_id": 1,
4
+ "context_length": 65536,
5
+ "decoder": {
6
+ "session_options": {
7
+ "log_id": "onnxruntime-genai",
8
+ "provider_options": []
9
+ },
10
+ "filename": "llm_decoder.onnx",
11
+ "head_size": 128,
12
+ "hidden_size": 1536,
13
+ "inputs": {
14
+ "inputs_embeds": "inputs_embeds",
15
+ "attention_mask": "attention_mask",
16
+ "past_key_names": "past_key_values.%d.key",
17
+ "past_value_names": "past_key_values.%d.value"
18
+ },
19
+ "outputs": {
20
+ "present_key_names": "present.%d.key",
21
+ "present_value_names": "present.%d.value"
22
+ },
23
+ "num_attention_heads": 12,
24
+ "num_hidden_layers": 28,
25
+ "num_key_value_heads": 2
26
+ },
27
+ "eos_token_id": null,
28
+ "pad_token_id": null,
29
+ "type": "qwen2",
30
+ "vocab_size": 151936
31
+ },
32
+ "search": {
33
+ "diversity_penalty": 0.0,
34
+ "do_sample": false,
35
+ "early_stopping": true,
36
+ "length_penalty": 1.0,
37
+ "max_length": 65536,
38
+ "min_length": 0,
39
+ "no_repeat_ngram_size": 0,
40
+ "num_beams": 1,
41
+ "num_return_sequences": 1,
42
+ "past_present_share_buffer": true,
43
+ "repetition_penalty": 1.0,
44
+ "temperature": 1.0,
45
+ "top_k": 50,
46
+ "top_p": 1.0
47
+ }
48
+ }
cpu_fp32/llm_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:710b47c678f45ae232c1d8ee694642f90852ce03286ded62bee3d9ed012b9006
3
+ size 170303
cpu_fp32/llm_decoder.onnx.data ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d8d42ad79c9791300404c674ff6d9964910b7337e9a749fe3e6eff193a9b9efc
3
+ size 5274927104
cpu_fp32/semantic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1403fdabeef9ca7d4fcf8177bd071f931ff8135ad64f2b0d186cdcbdb8b1c215
3
+ size 10254291
cpu_fp32/semantic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:77dd17bc1f5a3cb5d21b6c337e4d5e1a883f2a6d79373c3155dee215ba6fd591
3
+ size 1379670225
cpu_fp32/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3fd169731d2cbde95e10bf356d66d5997fd885dd8dbb6fb4684da3f23b2585d8
3
+ size 11421892
cpu_fp32/tokenizer_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|endoftext|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "is_local": true,
24
+ "local_files_only": false,
25
+ "model_max_length": 65536,
26
+ "pad_token": "<|endoftext|>",
27
+ "split_special_tokens": false,
28
+ "tokenizer_class": "Qwen2Tokenizer",
29
+ "unk_token": null
30
+ }
cpu_int4/acoustic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bf7183835daf1959ab105f4886b3a9867a0b65fe95c93ea832b46c0dd4e3d4d2
3
+ size 9861072
cpu_int4/acoustic_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:15625fabb679e4bf01138118e7349e055e2e3dfd8b4546b1c108c09ad0ca160e
3
+ size 1376190019
cpu_int4/acoustic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a6d5a0f7cfd27e06e39a6f11bcbc1abba63245e9e6b256b407e2d43bd67396ad
3
+ size 1375985271
cpu_int4/chat_template.jinja ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0]['role'] == 'system' %}
4
+ {{- messages[0]['content'] }}
5
+ {%- else %}
6
+ {{- 'You are a helpful assistant.' }}
7
+ {%- endif %}
8
+ {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
9
+ {%- for tool in tools %}
10
+ {{- "\n" }}
11
+ {{- tool | tojson }}
12
+ {%- endfor %}
13
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
14
+ {%- else %}
15
+ {%- if messages[0]['role'] == 'system' %}
16
+ {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
17
+ {%- else %}
18
+ {{- '<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n' }}
19
+ {%- endif %}
20
+ {%- endif %}
21
+ {%- for message in messages %}
22
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}
23
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
24
+ {%- elif message.role == "assistant" %}
25
+ {{- '<|im_start|>' + message.role }}
26
+ {%- if message.content %}
27
+ {{- '\n' + message.content }}
28
+ {%- endif %}
29
+ {%- for tool_call in message.tool_calls %}
30
+ {%- if tool_call.function is defined %}
31
+ {%- set tool_call = tool_call.function %}
32
+ {%- endif %}
33
+ {{- '\n<tool_call>\n{"name": "' }}
34
+ {{- tool_call.name }}
35
+ {{- '", "arguments": ' }}
36
+ {{- tool_call.arguments | tojson }}
37
+ {{- '}\n</tool_call>' }}
38
+ {%- endfor %}
39
+ {{- '<|im_end|>\n' }}
40
+ {%- elif message.role == "tool" %}
41
+ {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
42
+ {{- '<|im_start|>user' }}
43
+ {%- endif %}
44
+ {{- '\n<tool_response>\n' }}
45
+ {{- message.content }}
46
+ {{- '\n</tool_response>' }}
47
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
48
+ {{- '<|im_end|>\n' }}
49
+ {%- endif %}
50
+ {%- endif %}
51
+ {%- endfor %}
52
+ {%- if add_generation_prompt %}
53
+ {{- '<|im_start|>assistant\n' }}
54
+ {%- endif %}
cpu_int4/diffusion_head.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:063928366830acd04eb21b15fb3f05a08a064d0c077e49dd30a2bfe2901f505e
3
+ size 493270097
cpu_int4/genai_config.json ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": {
3
+ "bos_token_id": 1,
4
+ "context_length": 65536,
5
+ "decoder": {
6
+ "session_options": {
7
+ "log_id": "onnxruntime-genai",
8
+ "provider_options": []
9
+ },
10
+ "filename": "llm_decoder.onnx",
11
+ "head_size": 128,
12
+ "hidden_size": 1536,
13
+ "inputs": {
14
+ "inputs_embeds": "inputs_embeds",
15
+ "attention_mask": "attention_mask",
16
+ "past_key_names": "past_key_values.%d.key",
17
+ "past_value_names": "past_key_values.%d.value"
18
+ },
19
+ "outputs": {
20
+ "present_key_names": "present.%d.key",
21
+ "present_value_names": "present.%d.value"
22
+ },
23
+ "num_attention_heads": 12,
24
+ "num_hidden_layers": 28,
25
+ "num_key_value_heads": 2
26
+ },
27
+ "eos_token_id": null,
28
+ "pad_token_id": null,
29
+ "type": "qwen2",
30
+ "vocab_size": 151936
31
+ },
32
+ "search": {
33
+ "diversity_penalty": 0.0,
34
+ "do_sample": false,
35
+ "early_stopping": true,
36
+ "length_penalty": 1.0,
37
+ "max_length": 65536,
38
+ "min_length": 0,
39
+ "no_repeat_ngram_size": 0,
40
+ "num_beams": 1,
41
+ "num_return_sequences": 1,
42
+ "past_present_share_buffer": true,
43
+ "repetition_penalty": 1.0,
44
+ "temperature": 1.0,
45
+ "top_k": 50,
46
+ "top_p": 1.0
47
+ }
48
+ }
cpu_int4/llm_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:eb58c302f5ca2927101b0e080d973b0d8740a4d3ac11a61a7052c597b616df2f
3
+ size 222061
cpu_int4/llm_decoder.onnx.data ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6be0d6d7da8a77a6fe37810483c09897ce25d91038854d407545112325a98ea7
3
+ size 857145344
cpu_int4/semantic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1403fdabeef9ca7d4fcf8177bd071f931ff8135ad64f2b0d186cdcbdb8b1c215
3
+ size 10254291
cpu_int4/semantic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:77dd17bc1f5a3cb5d21b6c337e4d5e1a883f2a6d79373c3155dee215ba6fd591
3
+ size 1379670225
cpu_int4/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3fd169731d2cbde95e10bf356d66d5997fd885dd8dbb6fb4684da3f23b2585d8
3
+ size 11421892
cpu_int4/tokenizer_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|endoftext|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "is_local": true,
24
+ "local_files_only": false,
25
+ "model_max_length": 65536,
26
+ "pad_token": "<|endoftext|>",
27
+ "split_special_tokens": false,
28
+ "tokenizer_class": "Qwen2Tokenizer",
29
+ "unk_token": null
30
+ }
eval.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Evaluate exported VibeVoice ONNX sub-parts against their PyTorch references.
2
+
3
+ Two stages:
4
+ A) COMPONENT parity — for every exported component (acoustic/semantic encoders & decoder,
5
+ diffusion_head, connectors, projector) load the PyTorch reference (user_script loaders) and
6
+ the ONNX session on the SAME inputs, then report cosine + max|Δ| with a PASS/FAIL threshold.
7
+ The LLM decoder is checked structurally (int4 MatMulNBits + GQA + inputs_embeds→hidden).
8
+ B) WHOLE pipeline — an end-to-end integrity chain of the ONNX pieces:
9
+ • TTS codec round-trip (audio → acoustic_encoder → acoustic_decoder → audio′): waveform
10
+ correlation + SNR — the standard neural-codec reconstruction metric.
11
+ • Full ONNX chain smoke: latent → acoustic_connector → (cond) → diffusion_head → 1 denoise
12
+ step, and acoustic_decoder → waveform — every exported block run in sequence, shapes +
13
+ finiteness verified. (The autoregressive LLM + multi-step DDPM loop need the genai
14
+ runtime and are out of scope here — reported as SKIPPED, not silently passed.)
15
+
16
+ Model is the FINAL positional (a key {1.5b,asr,asr-hf,realtime} or a checkpoint dir path).
17
+
18
+ Usage:
19
+ uv run eval.py 1.5b
20
+ uv run eval.py --device cuda --precision fp16 ./asr-hf
21
+ uv run eval.py --audio sample.wav 1.5b
22
+ uv run eval.py --components acoustic_encoder diffusion_head realtime
23
+ """
24
+ import argparse
25
+ import sys
26
+ import os
27
+ from pathlib import Path
28
+
29
+ import numpy as np
30
+
31
+ HERE = Path(__file__).parent
32
+ sys.path.insert(0, str(HERE))
33
+ for _s in (sys.stdout, sys.stderr):
34
+ try: _s.reconfigure(encoding="utf-8", errors="replace")
35
+ except Exception: pass
36
+
37
+ import optimize as O # registry (MODELS/DEVICES), resolve_target, detect
38
+ import user_script as us
39
+
40
+ COS_TOL = 0.99 # component parity threshold
41
+
42
+
43
+ def _np(o):
44
+ """Best-effort tensor → float32 numpy from a torch tensor or an output object."""
45
+ import torch
46
+ if torch.is_tensor(o):
47
+ return o.detach().float().cpu().numpy()
48
+ for a in ("latents", "mean", "sample", "audio", "last_hidden_state"):
49
+ if hasattr(o, a):
50
+ v = getattr(o, a); v = v() if callable(v) else v
51
+ if torch.is_tensor(v):
52
+ return v.detach().float().cpu().numpy()
53
+ if isinstance(o, (tuple, list)):
54
+ return _np(o[0])
55
+ raise TypeError(f"cannot convert output of type {type(o).__name__}")
56
+
57
+
58
+ def _cos(a, b):
59
+ a, b = a.ravel().astype(np.float64), b.ravel().astype(np.float64)
60
+ n = np.linalg.norm(a) * np.linalg.norm(b)
61
+ return float(a @ b / (n + 1e-9))
62
+
63
+
64
+ def _session(path):
65
+ import onnxruntime as ort
66
+ return ort.InferenceSession(str(path), providers=["CPUExecutionProvider"])
67
+
68
+
69
+ def parity_component(model_key, src, comp, onnx_path):
70
+ """Run PyTorch ref + ONNX on identical dummy inputs; return (cos, maxd, ok)."""
71
+ import torch
72
+ loader_name, io_name, dummy_name, env = O.MODELS[model_key]["olive"][comp]
73
+ os.environ.update(env)
74
+ pyt = getattr(us, loader_name)(str(src))
75
+ if hasattr(pyt, "eval"):
76
+ pyt = pyt.eval()
77
+ io = getattr(us, io_name)()
78
+ names = io["input_names"]
79
+ inputs = getattr(us, dummy_name)()
80
+ with torch.no_grad():
81
+ ref = _np(pyt(*[inputs[n] for n in names]))
82
+ got = _session(onnx_path).run(None, {n: inputs[n].numpy() for n in names})[0]
83
+ m = min(ref.size, got.size)
84
+ a, b = got.ravel()[:m].astype(np.float64), ref.ravel()[:m].astype(np.float64)
85
+ cos = _cos(a, b)
86
+ maxd = float(np.abs(a - b).max())
87
+ rel = maxd / (float(np.abs(b).max()) + 1e-12)
88
+ # PASS on cosine, OR when tensors are numerically identical (near-zero-signal inputs make
89
+ # cosine noise-dominated even though maxd≈0 — e.g. a decoder fed random latents → ~silence).
90
+ ok = (cos >= COS_TOL) or (maxd < 1e-4) or (rel < 1e-3)
91
+ return cos, maxd, ok
92
+
93
+
94
+ def check_llm(onnx_path):
95
+ """Structural check of the genai-built decoder (no full runtime inference)."""
96
+ import onnx
97
+ g = onnx.load(str(onnx_path), load_external_data=False).graph
98
+ ops = [n.op_type for n in g.node]
99
+ innames = [i.name for i in g.input]
100
+ nb, gqa = ops.count("MatMulNBits"), ops.count("GroupQueryAttention")
101
+ embeds_in = any("inputs_embeds" in n for n in innames)
102
+ ok = (nb > 0 or "MatMul" in ops) and embeds_in
103
+ return f"MatMulNBits={nb} GQA={gqa} inputs_embeds={embeds_in}", ok
104
+
105
+
106
+ # ---------------------------------------------------------------- whole pipeline
107
+
108
+ def _load_audio(path, samples, sr=24000):
109
+ import soundfile as sf, librosa
110
+ wav, in_sr = sf.read(path, dtype="float32", always_2d=False)
111
+ if wav.ndim > 1:
112
+ wav = wav.mean(1)
113
+ if in_sr != sr:
114
+ wav = librosa.resample(wav, orig_sr=in_sr, target_sr=sr)
115
+ if len(wav) < samples:
116
+ wav = np.pad(wav, (0, samples - len(wav)))
117
+ return wav[:samples].astype(np.float32)[None, None, :]
118
+
119
+
120
+ def _synth_audio(samples, sr=24000):
121
+ t = np.arange(samples) / sr
122
+ wav = 0.3 * (np.sin(2 * np.pi * 220 * t) + 0.5 * np.sin(2 * np.pi * 440 * t))
123
+ return wav.astype(np.float32)[None, None, :]
124
+
125
+
126
+ def whole_pipeline(model_key, models_dir, audio_path):
127
+ """End-to-end ONNX integrity: codec round-trip + full-chain smoke. Returns list of rows."""
128
+ rows = []
129
+ present = {c: models_dir / f"{c}.onnx" for c in
130
+ ("acoustic_encoder", "acoustic_decoder", "acoustic_connector", "diffusion_head",
131
+ "semantic_encoder", "multi_modal_projector")
132
+ if (models_dir / f"{c}.onnx").exists()}
133
+
134
+ # --- codec round-trip (encoder + decoder both present) ---
135
+ if "acoustic_encoder" in present and "acoustic_decoder" in present:
136
+ enc, dec = _session(present["acoustic_encoder"]), _session(present["acoustic_decoder"])
137
+ samples = enc.get_inputs()[0].shape[2]
138
+ samples = 24000 if not isinstance(samples, int) else samples
139
+ wav = _load_audio(audio_path, samples) if audio_path else _synth_audio(samples)
140
+ lat = enc.run(None, {"audio": wav})[0]
141
+ dec_frames = dec.get_inputs()[0].shape[1]
142
+ if isinstance(dec_frames, int) and lat.shape[1] != dec_frames:
143
+ f = min(lat.shape[1], dec_frames)
144
+ lat = lat[:, :f, :] if lat.shape[1] > f else np.pad(lat, ((0, 0), (0, dec_frames - lat.shape[1]), (0, 0)))
145
+ recon = dec.run(None, {"latents": lat.astype(np.float32)})[0].ravel()
146
+ n = min(len(recon), wav.size)
147
+ x = wav.ravel()[:n]; y = recon[:n]
148
+ corr = float(np.corrcoef(x, y)[0, 1]) if n > 1 else float("nan")
149
+ noise = x - y
150
+ snr = 10 * np.log10((np.sum(x**2) + 1e-12) / (np.sum(noise**2) + 1e-12))
151
+ finite = bool(np.isfinite(recon).all())
152
+ rows.append(("codec round-trip", f"corr={corr:+.3f} SNR={snr:+.1f}dB finite={finite} "
153
+ f"in={wav.size} out={len(recon)}", finite))
154
+ else:
155
+ rows.append(("codec round-trip", "SKIPPED (needs acoustic_encoder+decoder)", None))
156
+
157
+ # --- full ONNX chain smoke: latent → connector → diffusion_head; latent → decoder ---
158
+ if "acoustic_connector" in present and "diffusion_head" in present:
159
+ conn = _session(present["acoustic_connector"]); dh = _session(present["diffusion_head"])
160
+ rng = np.random.default_rng(0)
161
+ T = 8
162
+ lat = rng.standard_normal((1, T, 64)).astype(np.float32)
163
+ cond = conn.run(None, {"features": lat})[0] # [1,T,H]
164
+ H = cond.shape[-1]
165
+ ni = rng.standard_normal((T, 64)).astype(np.float32)
166
+ ts = (rng.random(T) * 1000).astype(np.float32)
167
+ pred = dh.run(None, {"noisy_images": ni, "timesteps": ts,
168
+ "condition": cond.reshape(T, H).astype(np.float32)})[0]
169
+ ok = pred.shape == (T, 64) and np.isfinite(pred).all() and np.isfinite(cond).all()
170
+ rows.append(("tts chain smoke", f"connector→[H={H}]→diffusion_head pred={pred.shape} finite={ok}", ok))
171
+ else:
172
+ rows.append(("tts chain smoke", "SKIPPED (needs acoustic_connector+diffusion_head)", None))
173
+
174
+ # --- ASR fusion chain: encoders → projector/connectors → fused features ---
175
+ if "multi_modal_projector" in present and "acoustic_encoder" in present and "semantic_encoder" in present:
176
+ ae, se, proj = (_session(present[k]) for k in ("acoustic_encoder", "semantic_encoder", "multi_modal_projector"))
177
+ wav = _synth_audio(24000)
178
+ al = ae.run(None, {"audio": wav})[0]; sl = se.run(None, {"audio": wav})[0]
179
+ f = min(al.shape[1], sl.shape[1])
180
+ fused = proj.run(None, {"acoustic_latents": al[:, :f].astype(np.float32),
181
+ "semantic_latents": sl[:, :f].astype(np.float32)})[0]
182
+ ok = np.isfinite(fused).all()
183
+ rows.append(("asr fusion chain", f"ac+sem→projector fused={fused.shape} finite={ok}", ok))
184
+
185
+ rows.append(("autoregressive LLM + DDPM loop", "SKIPPED (needs genai runtime; out of scope)", None))
186
+ return rows
187
+
188
+
189
+ def main():
190
+ ap = argparse.ArgumentParser(description="Evaluate VibeVoice ONNX sub-parts",
191
+ formatter_class=argparse.RawDescriptionHelpFormatter)
192
+ global COS_TOL
193
+ ap.add_argument("--device", choices=["cpu", "cuda", "gpu"], default="cpu")
194
+ ap.add_argument("--precision", choices=["int4", "fp16", "fp32"], default="int4")
195
+ ap.add_argument("--components", help="comma-separated subset (default: all present)")
196
+ ap.add_argument("--output-dir", help="models dir (default onnx/{model}/{device}_{precision})")
197
+ ap.add_argument("--audio", help="wav for codec round-trip (default: synthetic tone)")
198
+ ap.add_argument("--tol", type=float, default=COS_TOL, help=f"cosine PASS threshold (default {COS_TOL})")
199
+ ap.add_argument("model", help="keyword {1.5b,asr,asr-hf,realtime} or checkpoint dir path")
200
+ args = ap.parse_args()
201
+ COS_TOL = args.tol
202
+ device = "cuda" if args.device == "gpu" else args.device
203
+ model_key, src = O.resolve_target(args.model)
204
+ models_dir = Path(args.output_dir) if args.output_dir else (HERE / "onnx" / model_key / f"{device}_{args.precision}")
205
+ if not models_dir.exists():
206
+ sys.exit(f"no exported models at {models_dir} — run optimize.py first")
207
+
208
+ print(f"=== eval {model_key} src={src} models={models_dir} tol={COS_TOL} ===\n")
209
+
210
+ # ---- A) component parity ----
211
+ comps = [c.strip() for c in args.components.split(",")] if args.components else O.all_components(model_key)
212
+ print("A) COMPONENT PARITY (ONNX vs PyTorch)")
213
+ results = []
214
+ for comp in comps:
215
+ onnx_path = models_dir / (f"{comp}.onnx" if comp != "llm" else "llm_decoder.onnx")
216
+ if not onnx_path.exists():
217
+ print(f" {comp:22s} — not exported (skip)"); continue
218
+ try:
219
+ if comp == "llm":
220
+ info, ok = check_llm(onnx_path)
221
+ print(f" {comp:22s} {'PASS' if ok else 'FAIL'} {info}"); results.append(ok)
222
+ else:
223
+ cos, maxd, ok = parity_component(model_key, src, comp, onnx_path)
224
+ print(f" {comp:22s} {'PASS' if ok else 'FAIL'} cos={cos:.6f} maxd={maxd:.2e}")
225
+ results.append(ok)
226
+ except Exception as e:
227
+ print(f" {comp:22s} ERROR {type(e).__name__}: {str(e)[:120]}"); results.append(False)
228
+
229
+ # ---- B) whole pipeline ----
230
+ print("\nB) WHOLE PIPELINE (end-to-end ONNX integrity)")
231
+ for name, info, ok in whole_pipeline(model_key, models_dir, args.audio):
232
+ tag = "SKIP" if ok is None else ("PASS" if ok else "FAIL")
233
+ print(f" {name:32s} {tag} {info}")
234
+ if ok is not None:
235
+ results.append(ok)
236
+
237
+ npass = sum(1 for r in results if r); ntot = len(results)
238
+ print(f"\n=== {npass}/{ntot} checks passed ===")
239
+ sys.exit(0 if npass == ntot else 1)
240
+
241
+
242
+ if __name__ == "__main__":
243
+ main()
figures/Fig1.png ADDED

Git LFS Details

  • SHA256: 64464f28380f81e76c88d76431a08b48c7f82a283e17f2e32c241c4b03407d19
  • Pointer size: 131 Bytes
  • Size of remote file: 154 kB
gpu_fp16/acoustic_connector.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9cf54e4869bbfe70ea74b784f3d67597b0691b3eac5f23b9213e86cdb5a1e4b6
3
+ size 4936693
gpu_fp16/acoustic_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b9b59b84ea79d1de3d8c6a477822377437bbba2fe096d74ee913233482bf1fef
3
+ size 688798049
gpu_fp16/acoustic_encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:df85a2dbd67230632bfe2c517c55f5c481bab7cca8b89164f1411885414f2f7e
3
+ size 688593181
gpu_fp16/chat_template.jinja ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0]['role'] == 'system' %}
4
+ {{- messages[0]['content'] }}
5
+ {%- else %}
6
+ {{- 'You are a helpful assistant.' }}
7
+ {%- endif %}
8
+ {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
9
+ {%- for tool in tools %}
10
+ {{- "\n" }}
11
+ {{- tool | tojson }}
12
+ {%- endfor %}
13
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
14
+ {%- else %}
15
+ {%- if messages[0]['role'] == 'system' %}
16
+ {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
17
+ {%- else %}
18
+ {{- '<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n' }}
19
+ {%- endif %}
20
+ {%- endif %}
21
+ {%- for message in messages %}
22
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}
23
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
24
+ {%- elif message.role == "assistant" %}
25
+ {{- '<|im_start|>' + message.role }}
26
+ {%- if message.content %}
27
+ {{- '\n' + message.content }}
28
+ {%- endif %}
29
+ {%- for tool_call in message.tool_calls %}
30
+ {%- if tool_call.function is defined %}
31
+ {%- set tool_call = tool_call.function %}
32
+ {%- endif %}
33
+ {{- '\n<tool_call>\n{"name": "' }}
34
+ {{- tool_call.name }}
35
+ {{- '", "arguments": ' }}
36
+ {{- tool_call.arguments | tojson }}
37
+ {{- '}\n</tool_call>' }}
38
+ {%- endfor %}
39
+ {{- '<|im_end|>\n' }}
40
+ {%- elif message.role == "tool" %}
41
+ {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
42
+ {{- '<|im_start|>user' }}
43
+ {%- endif %}
44
+ {{- '\n<tool_response>\n' }}
45
+ {{- message.content }}
46
+ {{- '\n</tool_response>' }}
47
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
48
+ {{- '<|im_end|>\n' }}
49
+ {%- endif %}
50
+ {%- endif %}
51
+ {%- endfor %}
52
+ {%- if add_generation_prompt %}
53
+ {{- '<|im_start|>assistant\n' }}
54
+ {%- endif %}
gpu_fp16/diffusion_head.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:97659f98af3bbcbeac37a544b08d8baaf4c7a431f0b2d47a595ae31e861ca2d8
3
+ size 246711153
gpu_fp16/genai_config.json ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": {
3
+ "bos_token_id": 1,
4
+ "context_length": 65536,
5
+ "decoder": {
6
+ "session_options": {
7
+ "log_id": "onnxruntime-genai",
8
+ "provider_options": [
9
+ {
10
+ "cuda": {
11
+ "enable_cuda_graph": "0",
12
+ "enable_skip_layer_norm_strict_mode": "1"
13
+ }
14
+ }
15
+ ]
16
+ },
17
+ "filename": "llm_decoder.onnx",
18
+ "head_size": 128,
19
+ "hidden_size": 1536,
20
+ "inputs": {
21
+ "inputs_embeds": "inputs_embeds",
22
+ "attention_mask": "attention_mask",
23
+ "past_key_names": "past_key_values.%d.key",
24
+ "past_value_names": "past_key_values.%d.value"
25
+ },
26
+ "outputs": {
27
+ "present_key_names": "present.%d.key",
28
+ "present_value_names": "present.%d.value"
29
+ },
30
+ "num_attention_heads": 12,
31
+ "num_hidden_layers": 28,
32
+ "num_key_value_heads": 2
33
+ },
34
+ "eos_token_id": null,
35
+ "pad_token_id": null,
36
+ "type": "qwen2",
37
+ "vocab_size": 151936
38
+ },
39
+ "search": {
40
+ "diversity_penalty": 0.0,
41
+ "do_sample": false,
42
+ "early_stopping": true,
43
+ "length_penalty": 1.0,
44
+ "max_length": 65536,
45
+ "min_length": 0,
46
+ "no_repeat_ngram_size": 0,
47
+ "num_beams": 1,
48
+ "num_return_sequences": 1,
49
+ "past_present_share_buffer": true,
50
+ "repetition_penalty": 1.0,
51
+ "temperature": 1.0,
52
+ "top_k": 50,
53
+ "top_p": 1.0
54
+ }
55
+ }
gpu_fp16/llm_decoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:59e36731e6eb9593445c2d8e925e88290a364586c675bf2cbd7efd6fb516f1d8
3
+ size 170213
gpu_fp16/llm_decoder.onnx.data ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7b1adc93736ca403011ad3cb64614d8185f347142f5b404f6604aebe14eec0c8
3
+ size 2637496320