Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +14 -0
- .gitignore +8 -0
- README.md +92 -0
- common.py +312 -0
- cpu_fp16/acoustic_connector.onnx +3 -0
- cpu_fp16/acoustic_decoder.onnx +3 -0
- cpu_fp16/acoustic_encoder.onnx +3 -0
- cpu_fp16/chat_template.jinja +54 -0
- cpu_fp16/diffusion_head.onnx +3 -0
- cpu_fp16/genai_config.json +49 -0
- cpu_fp16/llm_decoder.onnx +3 -0
- cpu_fp16/llm_decoder.onnx.data +3 -0
- cpu_fp16/semantic_connector.onnx +3 -0
- cpu_fp16/semantic_encoder.onnx +3 -0
- cpu_fp16/tokenizer.json +3 -0
- cpu_fp16/tokenizer_config.json +30 -0
- cpu_fp32/acoustic_connector.onnx +3 -0
- cpu_fp32/acoustic_decoder.onnx +3 -0
- cpu_fp32/acoustic_encoder.onnx +3 -0
- cpu_fp32/chat_template.jinja +54 -0
- cpu_fp32/diffusion_head.onnx +3 -0
- cpu_fp32/genai_config.json +48 -0
- cpu_fp32/llm_decoder.onnx +3 -0
- cpu_fp32/llm_decoder.onnx.data +3 -0
- cpu_fp32/semantic_connector.onnx +3 -0
- cpu_fp32/semantic_encoder.onnx +3 -0
- cpu_fp32/tokenizer.json +3 -0
- cpu_fp32/tokenizer_config.json +30 -0
- cpu_int4/acoustic_connector.onnx +3 -0
- cpu_int4/acoustic_decoder.onnx +3 -0
- cpu_int4/acoustic_encoder.onnx +3 -0
- cpu_int4/chat_template.jinja +54 -0
- cpu_int4/diffusion_head.onnx +3 -0
- cpu_int4/genai_config.json +48 -0
- cpu_int4/llm_decoder.onnx +3 -0
- cpu_int4/llm_decoder.onnx.data +3 -0
- cpu_int4/semantic_connector.onnx +3 -0
- cpu_int4/semantic_encoder.onnx +3 -0
- cpu_int4/tokenizer.json +3 -0
- cpu_int4/tokenizer_config.json +30 -0
- eval.py +243 -0
- figures/Fig1.png +3 -0
- gpu_fp16/acoustic_connector.onnx +3 -0
- gpu_fp16/acoustic_decoder.onnx +3 -0
- gpu_fp16/acoustic_encoder.onnx +3 -0
- gpu_fp16/chat_template.jinja +54 -0
- gpu_fp16/diffusion_head.onnx +3 -0
- gpu_fp16/genai_config.json +55 -0
- gpu_fp16/llm_decoder.onnx +3 -0
- 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
|
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
|