Sad-tts-v1: Vocence OmniVoice miner + weights
Browse files- .gitattributes +1 -0
- .gitignore +9 -0
- README.md +58 -0
- VOCENCE_HF.md +21 -0
- audio_tokenizer/.gitattributes +35 -0
- audio_tokenizer/LICENSE +43 -0
- audio_tokenizer/README.md +199 -0
- audio_tokenizer/config.json +129 -0
- audio_tokenizer/preprocessor_config.json +9 -0
- chat_template.jinja +89 -0
- chute_config.yml +26 -0
- config.json +101 -0
- miner.py +391 -0
- tokenizer.json +3 -0
- tokenizer_config.json +23 -0
- vocence_config.yaml +21 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ 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 |
+
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.cache/
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
*.bak
|
| 5 |
+
*.bak-*
|
| 6 |
+
|
| 7 |
+
# Large checkpoints — add from https://huggingface.co/k2-fsa/OmniVoice (or your fork) before Hub push
|
| 8 |
+
/model.safetensors
|
| 9 |
+
/audio_tokenizer/model.safetensors
|
README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
pipeline_tag: text-to-speech
|
| 4 |
+
language:
|
| 5 |
+
- en
|
| 6 |
+
- zh
|
| 7 |
+
- multilingual
|
| 8 |
+
tags:
|
| 9 |
+
- vocence
|
| 10 |
+
- bittensor
|
| 11 |
+
- prompt-tts
|
| 12 |
+
- omnivoice
|
| 13 |
+
- sad-tts-v1
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
# Sad-tts-v1 (Vocence PromptTTS)
|
| 17 |
+
|
| 18 |
+
**Sad-tts-v1** is a **[Vocence SN78](https://github.com/Vocence-bt/vocence)** miner bundle (OmniVoice backbone). Hub: **`KGSS/Sad-tts-v1`** — natural-language **instruction** plus **text** in, **mono WAV** out via [`miner.py`](./miner.py).
|
| 19 |
+
|
| 20 |
+
Base weights align with **[k2-fsa/OmniVoice](https://huggingface.co/k2-fsa/OmniVoice)** · Apache-2.0 · [`omnivoice`](https://pypi.org/project/omnivoice/) runtime. Pin commits in `miner_deploy_sad_tts_v1.py` and [VOCENCE_HF.md](./VOCENCE_HF.md).
|
| 21 |
+
|
| 22 |
+
## Vocence contract
|
| 23 |
+
|
| 24 |
+
| Method | Role |
|
| 25 |
+
|--------|------|
|
| 26 |
+
| `Miner(path_hf_repo)` | Load checkpoint from a directory (or HF snapshot) containing `config.json`, `model.safetensors`, tokenizers, and `audio_tokenizer/`. |
|
| 27 |
+
| `warmup()` | One short synthesis to prime the stack. |
|
| 28 |
+
| `generate_wav(instruction, text)` | Returns `(float32 mono ndarray, sample_rate)`; typically **24 kHz**. |
|
| 29 |
+
|
| 30 |
+
Validators send **free-form** `instruction`. OmniVoice **voice-design** only accepts [whitelisted attribute tags](https://huggingface.co/k2-fsa/OmniVoice); **`miner.py` maps** keywords (gender, age, pitch, whisper, accent, Chinese dialects) to those tags. Unmatched instructions fall back to `runtime.default_instruct` in [`vocence_config.yaml`](./vocence_config.yaml).
|
| 31 |
+
|
| 32 |
+
## Repo layout
|
| 33 |
+
|
| 34 |
+
| File | Role |
|
| 35 |
+
|------|------|
|
| 36 |
+
| `miner.py` | Engine + NL → `instruct` mapping |
|
| 37 |
+
| `chute_config.yml` | Chutes image (PyTorch cu128 + `omnivoice`) |
|
| 38 |
+
| `vocence_config.yaml` | Limits, default voice tags, `num_step` / `guidance_scale` |
|
| 39 |
+
| Weight files | Shipped in this Hub repo (`model.safetensors`, `audio_tokenizer/`); see [VOCENCE_HF.md](./VOCENCE_HF.md) |
|
| 40 |
+
|
| 41 |
+
## Local quick check (GPU)
|
| 42 |
+
|
| 43 |
+
```bash
|
| 44 |
+
pip install omnivoice torch torchaudio # match CUDA index from chute_config.yml
|
| 45 |
+
# Copy snapshot: huggingface-cli download k2-fsa/OmniVoice --local-dir ./OmniVoice_weights
|
| 46 |
+
python -c "
|
| 47 |
+
from pathlib import Path
|
| 48 |
+
from miner import Miner
|
| 49 |
+
m = Miner(Path('./OmniVoice_weights'))
|
| 50 |
+
m.warmup()
|
| 51 |
+
w, sr = m.generate_wav('Calm female voice, British accent.', 'Hello from OmniVoice on Vocence.')
|
| 52 |
+
print(w.shape, sr)
|
| 53 |
+
"
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
## License
|
| 57 |
+
|
| 58 |
+
**Apache-2.0** for this packaging layout and miner glue; **OmniVoice** weights and upstream code remain under their stated licenses on the [model card](https://huggingface.co/k2-fsa/OmniVoice).
|
VOCENCE_HF.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Publishing **Sad-tts-v1** (`KGSS/Sad-tts-v1`)
|
| 2 |
+
|
| 3 |
+
1. **Weights** — Full OmniVoice-style snapshot (main `model.safetensors` + `audio_tokenizer/`). Upstream reference: **[k2-fsa/OmniVoice](https://huggingface.co/k2-fsa/OmniVoice)**.
|
| 4 |
+
|
| 5 |
+
- `model.safetensors`
|
| 6 |
+
- `config.json`, `tokenizer.json`, `tokenizer_config.json`, `chat_template.jinja`, etc.
|
| 7 |
+
- `audio_tokenizer/` (directory with its `model.safetensors` and configs)
|
| 8 |
+
|
| 9 |
+
You can sync without Git LFS clutter locally:
|
| 10 |
+
|
| 11 |
+
```bash
|
| 12 |
+
huggingface-cli download k2-fsa/OmniVoice --local-dir ./mysnap
|
| 13 |
+
cp -r miner.py chute_config.yml vocence_config.yaml README.md ./mysnap/
|
| 14 |
+
# then push ./mysnap to your Hub repo
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
2. **Revision** — Pin the commit SHA in your deploy script as `VOCENCE_REVISION` and use the same value in `vocence miner commit --model-revision`.
|
| 18 |
+
|
| 19 |
+
3. **`chute_config.yml` on SN78** — Subnet Chutes integrations require TEE + supported GPU class (see your working `rhy-TTS-v1` deploy); this folder’s `chute_config.yml` matches that pattern.
|
| 20 |
+
|
| 21 |
+
4. **Safetensors metadata** — OmniVoice checkpoints from the official Hub use standard PyTorch safetensors metadata; no `pt-sn78v`-style patching should be needed (unlike some custom Qwen repacks).
|
audio_tokenizer/.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz 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
|
audio_tokenizer/LICENSE
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BOSON HIGGS AUDIO 2 COMMUNITY LICENSE AGREEMENT
|
| 2 |
+
|
| 3 |
+
Boson Higgs Audio 2 Version Release Date: June 20, 2025
|
| 4 |
+
|
| 5 |
+
This License Agreement (the “Agreement”) is entered into by and between Licensee (as defined below) and Boson AI USA, Inc. (“Boson”) and is based upon the Meta Llama 3 Community License Agreement as of April 18, 2024 (the “Meta License Agreement”), which can be found at https://llama.meta.com/llama3/license/. The terms and conditions of the Meta License Agreement are hereby incorporated herein by reference and Unless stated otherwise below, its terms apply. The Higgs Audio 2 model developed by Boson AI USA, Inc. (“Higgs Materials”) is an audio model derived from Meta Llama 3 software and algorithms.
|
| 6 |
+
|
| 7 |
+
“Agreement” means the terms and conditions for use, reproduction, distribution and modification of the Higgs Materials set forth herein and the Meta License Agreement.
|
| 8 |
+
|
| 9 |
+
“Licensee” or “you” means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity’s behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering into this Agreement on their behalf.
|
| 10 |
+
|
| 11 |
+
“Higgs Audio 2” means the foundational large audio language models and software and algorithms, including machine-learning model code, trained model weights, inference-enabling code, training-enabling code, fine-tuning enabling code and other elements of the foregoing developed by Boson AI distributed at https://github.com/boson-ai/boson-multimodal or otherwise.
|
| 12 |
+
“Higgs Materials” means, collectively, Boson’s proprietary modification of Meta Llama 3 and Documentation (and any portion thereof) made available under this Agreement.
|
| 13 |
+
|
| 14 |
+
“Boson” or “we” means Boson AI USA, Inc.
|
| 15 |
+
|
| 16 |
+
By clicking “I Accept” below or by using or distributing any portion or element of the Higgs Materials, you agree to be bound by this Agreement.
|
| 17 |
+
|
| 18 |
+
1. License Rights and Redistribution.
|
| 19 |
+
a. Grant of Rights. You are granted a non-exclusive, worldwide, non-transferable and royalty-free limited license under Boson’s intellectual property or other rights owned by Boson embodied in the Higgs Materials to use, reproduce, distribute, copy, create derivative works of, and make modifications to the Higgs Materials.
|
| 20 |
+
b. Redistribution and Use.
|
| 21 |
+
i. If you distribute or make available the Higgs Materials (or any derivative works thereof), or a product or service that uses any of them, including another AI model, you shall (A) provide a copy of this Agreement and the of Meta License ’s Llama 3 agreement with any such Higgs Materials; and (B) prominently display “Built with Higgs Materials licensed from Boson AI USA, Inc., Copyright Boson AI USA, Inc., All Rights Reserved and Meta Llama 3 licensed under the Meta Llama 3 Community License, Copyright Meta Platforms, Inc., All Right Reserved". based on Meta Llama 3” on a related website, user interface, blogpost, about page, or product documentation. If you use the Higgs Materials to create, modify, enhance, train, fine tune, or otherwise improve an AI model or similar software, which is distributed or made available, you shall also include “Higgs Audio 2” at the beginning of any such AI model or software name.
|
| 22 |
+
ii. Even if you receive Higgs Materials, or any modifications, enhancements or derivative works thereof, from a Licensee as part of an integrated end user product, then Section 2 of this Agreement will apply to you.
|
| 23 |
+
iii. You must retain in all copies of the Llama Materials that you distribute and as set forth above, include the following attribution notice within a “Notice” text file distributed as a part of such copies:
|
| 24 |
+
“Meta Llama 3 is licensed under the Meta Llama 3 Community License, Copyright © Meta Platforms, Inc. All Rights Reserved.”
|
| 25 |
+
“Boson Higgs Audio 2 is licensed under the Boson Community License, Copyright © Boson AI USA, Inc. All Rights Reserved.”
|
| 26 |
+
iv. Your use of the Higgs Materials must comply with applicable laws and regulations (including trade compliance laws and regulations) and adhere to the Acceptable Use Policy for the Llama Materials (available at https://llama.meta.com/llama3/use-policy), which is hereby incorporated by reference into this Agreement.
|
| 27 |
+
v. You will not use the Higgs Materials or any output or results of the Higgs Materials to improve any other large language model (excluding Boson Higgs Audio 2 or derivative works thereof).
|
| 28 |
+
vi. You hereby acknowledge that Boson is the owner of the Higgs Materials and under no circumstance shall you bring any legal action, claim, charge, demand challenging such ownership rights of Boson.
|
| 29 |
+
|
| 30 |
+
2. Additional Commercial Terms. If the annual active users of the products or services made available by or for Licensee, or Licensee’s affiliates, is greater than 100,000 annual active users in the preceding calendar year, you must request an expanded license from Boson AI, which Boson AI may grant to you in its sole discretion, and you are not authorized to exercise any of the rights under this Agreement unless or until Boson AI otherwise expressly grants you such rights.
|
| 31 |
+
|
| 32 |
+
3. Disclaimer of Warranty. UNLESS REQUIRED BY APPLICABLE LAW, THE Higgs Materials AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN “AS IS” BASIS, WITH ALL FAULTS, WITHOUT WARRANTIES OF ANY KIND EXPRESS, IMPLIED, BASED UPON CUSTOM AND USAGE OR COURSE OF DEALING, AND BOSON AI DISCLAIMS ALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE HIGGS MATERIALS AND ASSUME ANY AND ALL RISKS ASSOCIATED WITH YOUR USE OF THE HIGGS MATERIALS AND ANY OUTPUT AND RESULTS.
|
| 33 |
+
|
| 34 |
+
4. Limitation of Liability. IN NO EVENT WILL BOSON AI OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF BOSON, META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING.
|
| 35 |
+
|
| 36 |
+
5. Intellectual Property.
|
| 37 |
+
a. No trademark licenses are granted under this Agreement, or in connection with the Higgs Materials., nNeither Boson nor Licensee may use any name or mark owned by, or associated with, the other party hereto or any of its affiliates, except as required for reasonable and customary use in describing and redistributing the Higgs Materials or as set forth in this Section 5(a). Boson hereby grants you a license to use “Higgs Audio 2” (the “Mark”) solely as required to comply with the last sentence of Section 1.b.i. All goodwill arising out of your use of the Mark will inure to the benefit of Meta and Boson AI.
|
| 38 |
+
b. Subject to Boson’s ownership of the Higgs Materials and derivatives made by or for Boson AI, with respect to any derivative works and modifications of the Higgs Materials that are made by you, as between you and Boson AI, you are and will be the owner of such derivative works and modifications.
|
| 39 |
+
c. If you institute litigation or other proceedings against Boson AI, Meta or any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Higgs Materials or Boson Higgs Audio 2 outputs or results, or any portion thereof any of the foregoing, constitutes infringement of the intellectual property or other rights owned or licensable by you, then any licenses granted to you hereunder this Agreement shall immediately terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Boson AI from and against any claim, charge, demand, cause of action by any third party arising out of or related to your use or distribution of the Higgs Materials.
|
| 40 |
+
|
| 41 |
+
6. Term and Termination. The term of this Agreement will commence upon your acceptance of this Agreement or access to the Higgs Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Boson AI may terminate this Agreement if you are in breach of any term or condition of this Agreement by providing you with written notice. Upon your receipt of written notice of termination of this Agreement, you shall delete the Higgs Materials from any computer, server or IT device and cease use of the Higgs Materials in all respects. Sections 1(b)(vi), 3, 4 and 7 shall survive the termination of this Agreement.
|
| 42 |
+
|
| 43 |
+
7. Governing Law and Jurisdiction. This Agreement will be governed and construed under the laws of the State of California without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. The federal courts in the Northern District of California and the state courts in Santa Clara County, California shall have exclusive jurisdiction of any dispute arising out of this Agreement.
|
audio_tokenizer/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
library_name: transformers
|
| 3 |
+
tags: []
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Model Card for Model ID
|
| 7 |
+
|
| 8 |
+
<!-- Provide a quick summary of what the model is/does. -->
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
## Model Details
|
| 13 |
+
|
| 14 |
+
### Model Description
|
| 15 |
+
|
| 16 |
+
<!-- Provide a longer summary of what this model is. -->
|
| 17 |
+
|
| 18 |
+
This is the model card of a 🤗 transformers model that has been pushed on the Hub. This model card has been automatically generated.
|
| 19 |
+
|
| 20 |
+
- **Developed by:** [More Information Needed]
|
| 21 |
+
- **Funded by [optional]:** [More Information Needed]
|
| 22 |
+
- **Shared by [optional]:** [More Information Needed]
|
| 23 |
+
- **Model type:** [More Information Needed]
|
| 24 |
+
- **Language(s) (NLP):** [More Information Needed]
|
| 25 |
+
- **License:** [More Information Needed]
|
| 26 |
+
- **Finetuned from model [optional]:** [More Information Needed]
|
| 27 |
+
|
| 28 |
+
### Model Sources [optional]
|
| 29 |
+
|
| 30 |
+
<!-- Provide the basic links for the model. -->
|
| 31 |
+
|
| 32 |
+
- **Repository:** [More Information Needed]
|
| 33 |
+
- **Paper [optional]:** [More Information Needed]
|
| 34 |
+
- **Demo [optional]:** [More Information Needed]
|
| 35 |
+
|
| 36 |
+
## Uses
|
| 37 |
+
|
| 38 |
+
<!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
|
| 39 |
+
|
| 40 |
+
### Direct Use
|
| 41 |
+
|
| 42 |
+
<!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
|
| 43 |
+
|
| 44 |
+
[More Information Needed]
|
| 45 |
+
|
| 46 |
+
### Downstream Use [optional]
|
| 47 |
+
|
| 48 |
+
<!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
|
| 49 |
+
|
| 50 |
+
[More Information Needed]
|
| 51 |
+
|
| 52 |
+
### Out-of-Scope Use
|
| 53 |
+
|
| 54 |
+
<!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
|
| 55 |
+
|
| 56 |
+
[More Information Needed]
|
| 57 |
+
|
| 58 |
+
## Bias, Risks, and Limitations
|
| 59 |
+
|
| 60 |
+
<!-- This section is meant to convey both technical and sociotechnical limitations. -->
|
| 61 |
+
|
| 62 |
+
[More Information Needed]
|
| 63 |
+
|
| 64 |
+
### Recommendations
|
| 65 |
+
|
| 66 |
+
<!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
|
| 67 |
+
|
| 68 |
+
Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
|
| 69 |
+
|
| 70 |
+
## How to Get Started with the Model
|
| 71 |
+
|
| 72 |
+
Use the code below to get started with the model.
|
| 73 |
+
|
| 74 |
+
[More Information Needed]
|
| 75 |
+
|
| 76 |
+
## Training Details
|
| 77 |
+
|
| 78 |
+
### Training Data
|
| 79 |
+
|
| 80 |
+
<!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
|
| 81 |
+
|
| 82 |
+
[More Information Needed]
|
| 83 |
+
|
| 84 |
+
### Training Procedure
|
| 85 |
+
|
| 86 |
+
<!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
|
| 87 |
+
|
| 88 |
+
#### Preprocessing [optional]
|
| 89 |
+
|
| 90 |
+
[More Information Needed]
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
#### Training Hyperparameters
|
| 94 |
+
|
| 95 |
+
- **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
|
| 96 |
+
|
| 97 |
+
#### Speeds, Sizes, Times [optional]
|
| 98 |
+
|
| 99 |
+
<!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
|
| 100 |
+
|
| 101 |
+
[More Information Needed]
|
| 102 |
+
|
| 103 |
+
## Evaluation
|
| 104 |
+
|
| 105 |
+
<!-- This section describes the evaluation protocols and provides the results. -->
|
| 106 |
+
|
| 107 |
+
### Testing Data, Factors & Metrics
|
| 108 |
+
|
| 109 |
+
#### Testing Data
|
| 110 |
+
|
| 111 |
+
<!-- This should link to a Dataset Card if possible. -->
|
| 112 |
+
|
| 113 |
+
[More Information Needed]
|
| 114 |
+
|
| 115 |
+
#### Factors
|
| 116 |
+
|
| 117 |
+
<!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
|
| 118 |
+
|
| 119 |
+
[More Information Needed]
|
| 120 |
+
|
| 121 |
+
#### Metrics
|
| 122 |
+
|
| 123 |
+
<!-- These are the evaluation metrics being used, ideally with a description of why. -->
|
| 124 |
+
|
| 125 |
+
[More Information Needed]
|
| 126 |
+
|
| 127 |
+
### Results
|
| 128 |
+
|
| 129 |
+
[More Information Needed]
|
| 130 |
+
|
| 131 |
+
#### Summary
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
## Model Examination [optional]
|
| 136 |
+
|
| 137 |
+
<!-- Relevant interpretability work for the model goes here -->
|
| 138 |
+
|
| 139 |
+
[More Information Needed]
|
| 140 |
+
|
| 141 |
+
## Environmental Impact
|
| 142 |
+
|
| 143 |
+
<!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
|
| 144 |
+
|
| 145 |
+
Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
|
| 146 |
+
|
| 147 |
+
- **Hardware Type:** [More Information Needed]
|
| 148 |
+
- **Hours used:** [More Information Needed]
|
| 149 |
+
- **Cloud Provider:** [More Information Needed]
|
| 150 |
+
- **Compute Region:** [More Information Needed]
|
| 151 |
+
- **Carbon Emitted:** [More Information Needed]
|
| 152 |
+
|
| 153 |
+
## Technical Specifications [optional]
|
| 154 |
+
|
| 155 |
+
### Model Architecture and Objective
|
| 156 |
+
|
| 157 |
+
[More Information Needed]
|
| 158 |
+
|
| 159 |
+
### Compute Infrastructure
|
| 160 |
+
|
| 161 |
+
[More Information Needed]
|
| 162 |
+
|
| 163 |
+
#### Hardware
|
| 164 |
+
|
| 165 |
+
[More Information Needed]
|
| 166 |
+
|
| 167 |
+
#### Software
|
| 168 |
+
|
| 169 |
+
[More Information Needed]
|
| 170 |
+
|
| 171 |
+
## Citation [optional]
|
| 172 |
+
|
| 173 |
+
<!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
|
| 174 |
+
|
| 175 |
+
**BibTeX:**
|
| 176 |
+
|
| 177 |
+
[More Information Needed]
|
| 178 |
+
|
| 179 |
+
**APA:**
|
| 180 |
+
|
| 181 |
+
[More Information Needed]
|
| 182 |
+
|
| 183 |
+
## Glossary [optional]
|
| 184 |
+
|
| 185 |
+
<!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
|
| 186 |
+
|
| 187 |
+
[More Information Needed]
|
| 188 |
+
|
| 189 |
+
## More Information [optional]
|
| 190 |
+
|
| 191 |
+
[More Information Needed]
|
| 192 |
+
|
| 193 |
+
## Model Card Authors [optional]
|
| 194 |
+
|
| 195 |
+
[More Information Needed]
|
| 196 |
+
|
| 197 |
+
## Model Card Contact
|
| 198 |
+
|
| 199 |
+
[More Information Needed]
|
audio_tokenizer/config.json
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"acoustic_model_config": {
|
| 3 |
+
"codebook_dim": 8,
|
| 4 |
+
"codebook_loss_weight": 1.0,
|
| 5 |
+
"codebook_size": 1024,
|
| 6 |
+
"commitment_loss_weight": 0.25,
|
| 7 |
+
"decoder_hidden_size": 1024,
|
| 8 |
+
"downsampling_ratios": [
|
| 9 |
+
8,
|
| 10 |
+
5,
|
| 11 |
+
4,
|
| 12 |
+
2,
|
| 13 |
+
3
|
| 14 |
+
],
|
| 15 |
+
"encoder_hidden_size": 64,
|
| 16 |
+
"hidden_size": 256,
|
| 17 |
+
"hop_length": 960,
|
| 18 |
+
"model_type": "dac",
|
| 19 |
+
"n_codebooks": 9,
|
| 20 |
+
"quantizer_dropout": 0,
|
| 21 |
+
"sampling_rate": 16000,
|
| 22 |
+
"upsampling_ratios": [
|
| 23 |
+
8,
|
| 24 |
+
5,
|
| 25 |
+
4,
|
| 26 |
+
2,
|
| 27 |
+
3
|
| 28 |
+
]
|
| 29 |
+
},
|
| 30 |
+
"architectures": [
|
| 31 |
+
"HiggsAudioV2TokenizerModel"
|
| 32 |
+
],
|
| 33 |
+
"block_dilations": [
|
| 34 |
+
1,
|
| 35 |
+
1
|
| 36 |
+
],
|
| 37 |
+
"channel_ratios": [
|
| 38 |
+
1,
|
| 39 |
+
1
|
| 40 |
+
],
|
| 41 |
+
"codebook_dim": 64,
|
| 42 |
+
"codebook_size": 1024,
|
| 43 |
+
"downsample_factor": 320,
|
| 44 |
+
"dtype": "float32",
|
| 45 |
+
"initializer_range": 0.02,
|
| 46 |
+
"kernel_size": 3,
|
| 47 |
+
"model_type": "higgs_audio_v2_tokenizer",
|
| 48 |
+
"sample_rate": 24000,
|
| 49 |
+
"semantic_model_config": {
|
| 50 |
+
"activation_dropout": 0.1,
|
| 51 |
+
"apply_spec_augment": true,
|
| 52 |
+
"attention_dropout": 0.1,
|
| 53 |
+
"bos_token_id": 1,
|
| 54 |
+
"classifier_proj_size": 256,
|
| 55 |
+
"conv_bias": false,
|
| 56 |
+
"conv_dim": [
|
| 57 |
+
512,
|
| 58 |
+
512,
|
| 59 |
+
512,
|
| 60 |
+
512,
|
| 61 |
+
512,
|
| 62 |
+
512,
|
| 63 |
+
512
|
| 64 |
+
],
|
| 65 |
+
"conv_kernel": [
|
| 66 |
+
10,
|
| 67 |
+
3,
|
| 68 |
+
3,
|
| 69 |
+
3,
|
| 70 |
+
3,
|
| 71 |
+
2,
|
| 72 |
+
2
|
| 73 |
+
],
|
| 74 |
+
"conv_pos_batch_norm": false,
|
| 75 |
+
"conv_stride": [
|
| 76 |
+
5,
|
| 77 |
+
2,
|
| 78 |
+
2,
|
| 79 |
+
2,
|
| 80 |
+
2,
|
| 81 |
+
2,
|
| 82 |
+
2
|
| 83 |
+
],
|
| 84 |
+
"ctc_loss_reduction": "sum",
|
| 85 |
+
"ctc_zero_infinity": false,
|
| 86 |
+
"do_stable_layer_norm": false,
|
| 87 |
+
"eos_token_id": 2,
|
| 88 |
+
"feat_extract_activation": "gelu",
|
| 89 |
+
"feat_extract_norm": "group",
|
| 90 |
+
"feat_proj_dropout": 0.0,
|
| 91 |
+
"feat_proj_layer_norm": true,
|
| 92 |
+
"final_dropout": 0.1,
|
| 93 |
+
"hidden_act": "gelu",
|
| 94 |
+
"hidden_dropout": 0.1,
|
| 95 |
+
"hidden_size": 768,
|
| 96 |
+
"initializer_range": 0.02,
|
| 97 |
+
"intermediate_size": 3072,
|
| 98 |
+
"layer_norm_eps": 1e-05,
|
| 99 |
+
"layerdrop": 0.1,
|
| 100 |
+
"mask_feature_length": 10,
|
| 101 |
+
"mask_feature_min_masks": 0,
|
| 102 |
+
"mask_feature_prob": 0.0,
|
| 103 |
+
"mask_time_length": 10,
|
| 104 |
+
"mask_time_min_masks": 2,
|
| 105 |
+
"mask_time_prob": 0.0,
|
| 106 |
+
"model_type": "hubert",
|
| 107 |
+
"num_attention_heads": 12,
|
| 108 |
+
"num_conv_pos_embedding_groups": 16,
|
| 109 |
+
"num_conv_pos_embeddings": 128,
|
| 110 |
+
"num_feat_extract_layers": 7,
|
| 111 |
+
"num_hidden_layers": 12,
|
| 112 |
+
"pad_token_id": 0,
|
| 113 |
+
"use_weighted_layer_sum": false,
|
| 114 |
+
"vocab_size": 32
|
| 115 |
+
},
|
| 116 |
+
"semantic_sample_rate": 16000,
|
| 117 |
+
"strides": [
|
| 118 |
+
1,
|
| 119 |
+
1
|
| 120 |
+
],
|
| 121 |
+
"target_bandwidths": [
|
| 122 |
+
0.5,
|
| 123 |
+
1,
|
| 124 |
+
1.5,
|
| 125 |
+
2
|
| 126 |
+
],
|
| 127 |
+
"transformers_version": "5.3.0.dev0",
|
| 128 |
+
"unit_kernel_size": 3
|
| 129 |
+
}
|
audio_tokenizer/preprocessor_config.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"feature_extractor_type": "DacFeatureExtractor",
|
| 3 |
+
"feature_size": 1,
|
| 4 |
+
"hop_length": 960,
|
| 5 |
+
"padding_side": "right",
|
| 6 |
+
"padding_value": 0.0,
|
| 7 |
+
"return_attention_mask": true,
|
| 8 |
+
"sampling_rate": 24000
|
| 9 |
+
}
|
chat_template.jinja
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{%- if tools %}
|
| 2 |
+
{{- '<|im_start|>system\n' }}
|
| 3 |
+
{%- if messages[0].role == 'system' %}
|
| 4 |
+
{{- messages[0].content + '\n\n' }}
|
| 5 |
+
{%- endif %}
|
| 6 |
+
{{- "# 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>" }}
|
| 7 |
+
{%- for tool in tools %}
|
| 8 |
+
{{- "\n" }}
|
| 9 |
+
{{- tool | tojson }}
|
| 10 |
+
{%- endfor %}
|
| 11 |
+
{{- "\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" }}
|
| 12 |
+
{%- else %}
|
| 13 |
+
{%- if messages[0].role == 'system' %}
|
| 14 |
+
{{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
|
| 15 |
+
{%- endif %}
|
| 16 |
+
{%- endif %}
|
| 17 |
+
{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
|
| 18 |
+
{%- for message in messages[::-1] %}
|
| 19 |
+
{%- set index = (messages|length - 1) - loop.index0 %}
|
| 20 |
+
{%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
|
| 21 |
+
{%- set ns.multi_step_tool = false %}
|
| 22 |
+
{%- set ns.last_query_index = index %}
|
| 23 |
+
{%- endif %}
|
| 24 |
+
{%- endfor %}
|
| 25 |
+
{%- for message in messages %}
|
| 26 |
+
{%- if message.content is string %}
|
| 27 |
+
{%- set content = message.content %}
|
| 28 |
+
{%- else %}
|
| 29 |
+
{%- set content = '' %}
|
| 30 |
+
{%- endif %}
|
| 31 |
+
{%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
|
| 32 |
+
{{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
|
| 33 |
+
{%- elif message.role == "assistant" %}
|
| 34 |
+
{%- set reasoning_content = '' %}
|
| 35 |
+
{%- if message.reasoning_content is string %}
|
| 36 |
+
{%- set reasoning_content = message.reasoning_content %}
|
| 37 |
+
{%- else %}
|
| 38 |
+
{%- if '</think>' in content %}
|
| 39 |
+
{%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
|
| 40 |
+
{%- set content = content.split('</think>')[-1].lstrip('\n') %}
|
| 41 |
+
{%- endif %}
|
| 42 |
+
{%- endif %}
|
| 43 |
+
{%- if loop.index0 > ns.last_query_index %}
|
| 44 |
+
{%- if loop.last or (not loop.last and reasoning_content) %}
|
| 45 |
+
{{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
|
| 46 |
+
{%- else %}
|
| 47 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 48 |
+
{%- endif %}
|
| 49 |
+
{%- else %}
|
| 50 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 51 |
+
{%- endif %}
|
| 52 |
+
{%- if message.tool_calls %}
|
| 53 |
+
{%- for tool_call in message.tool_calls %}
|
| 54 |
+
{%- if (loop.first and content) or (not loop.first) %}
|
| 55 |
+
{{- '\n' }}
|
| 56 |
+
{%- endif %}
|
| 57 |
+
{%- if tool_call.function %}
|
| 58 |
+
{%- set tool_call = tool_call.function %}
|
| 59 |
+
{%- endif %}
|
| 60 |
+
{{- '<tool_call>\n{"name": "' }}
|
| 61 |
+
{{- tool_call.name }}
|
| 62 |
+
{{- '", "arguments": ' }}
|
| 63 |
+
{%- if tool_call.arguments is string %}
|
| 64 |
+
{{- tool_call.arguments }}
|
| 65 |
+
{%- else %}
|
| 66 |
+
{{- tool_call.arguments | tojson }}
|
| 67 |
+
{%- endif %}
|
| 68 |
+
{{- '}\n</tool_call>' }}
|
| 69 |
+
{%- endfor %}
|
| 70 |
+
{%- endif %}
|
| 71 |
+
{{- '<|im_end|>\n' }}
|
| 72 |
+
{%- elif message.role == "tool" %}
|
| 73 |
+
{%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
|
| 74 |
+
{{- '<|im_start|>user' }}
|
| 75 |
+
{%- endif %}
|
| 76 |
+
{{- '\n<tool_response>\n' }}
|
| 77 |
+
{{- content }}
|
| 78 |
+
{{- '\n</tool_response>' }}
|
| 79 |
+
{%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
|
| 80 |
+
{{- '<|im_end|>\n' }}
|
| 81 |
+
{%- endif %}
|
| 82 |
+
{%- endif %}
|
| 83 |
+
{%- endfor %}
|
| 84 |
+
{%- if add_generation_prompt %}
|
| 85 |
+
{{- '<|im_start|>assistant\n' }}
|
| 86 |
+
{%- if enable_thinking is defined and enable_thinking is false %}
|
| 87 |
+
{{- '<think>\n\n</think>\n\n' }}
|
| 88 |
+
{%- endif %}
|
| 89 |
+
{%- endif %}
|
chute_config.yml
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Vocence PromptTTS — k2-fsa/OmniVoice (diffusion LM TTS, voice design via `instruct`).
|
| 2 |
+
# Weights + tokenizer ship in the HF repo; miner maps free-form `instruction` → OmniVoice tags.
|
| 3 |
+
|
| 4 |
+
Image:
|
| 5 |
+
from_base: parachutes/base-python:3.12.9
|
| 6 |
+
run_command:
|
| 7 |
+
- pip install --no-cache-dir torch==2.10.0 torchaudio==2.10.0 --extra-index-url https://download.pytorch.org/whl/cu128
|
| 8 |
+
- pip install --no-cache-dir transformers accelerate safetensors soundfile scipy einops
|
| 9 |
+
- pip install --no-cache-dir omnivoice
|
| 10 |
+
- pip install --no-cache-dir numpy pyyaml huggingface_hub
|
| 11 |
+
|
| 12 |
+
NodeSelector:
|
| 13 |
+
gpu_count: 1
|
| 14 |
+
min_vram_gb_per_gpu: 48
|
| 15 |
+
include: ["pro_6000"]
|
| 16 |
+
exclude: []
|
| 17 |
+
|
| 18 |
+
Chute:
|
| 19 |
+
tagline: Sad-tts-v1 OmniVoice TTS (PromptTTS voice design, Vocence)
|
| 20 |
+
readme: NL instruction + text to WAV; Vocence SN78 Sad-tts-v1 miner.
|
| 21 |
+
boost: 1.32
|
| 22 |
+
shutdown_after_seconds: 86400
|
| 23 |
+
concurrency: 1
|
| 24 |
+
max_instances: 1
|
| 25 |
+
scaling_threshold: 0.5
|
| 26 |
+
tee: true
|
config.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"OmniVoice"
|
| 4 |
+
],
|
| 5 |
+
"audio_codebook_weights": [
|
| 6 |
+
8,
|
| 7 |
+
8,
|
| 8 |
+
6,
|
| 9 |
+
6,
|
| 10 |
+
4,
|
| 11 |
+
4,
|
| 12 |
+
2,
|
| 13 |
+
2
|
| 14 |
+
],
|
| 15 |
+
"audio_mask_id": 1024,
|
| 16 |
+
"audio_vocab_size": 1025,
|
| 17 |
+
"bos_token_id": null,
|
| 18 |
+
"dtype": "float32",
|
| 19 |
+
"eos_token_id": 151645,
|
| 20 |
+
"llm_config": {
|
| 21 |
+
"_name_or_path": "",
|
| 22 |
+
"architectures": [
|
| 23 |
+
"Qwen3ForCausalLM"
|
| 24 |
+
],
|
| 25 |
+
"attention_bias": false,
|
| 26 |
+
"attention_dropout": 0.0,
|
| 27 |
+
"bos_token_id": 151643,
|
| 28 |
+
"chunk_size_feed_forward": 0,
|
| 29 |
+
"dtype": "float32",
|
| 30 |
+
"eos_token_id": 151645,
|
| 31 |
+
"head_dim": 128,
|
| 32 |
+
"hidden_act": "silu",
|
| 33 |
+
"hidden_size": 1024,
|
| 34 |
+
"id2label": {
|
| 35 |
+
"0": "LABEL_0",
|
| 36 |
+
"1": "LABEL_1"
|
| 37 |
+
},
|
| 38 |
+
"initializer_range": 0.02,
|
| 39 |
+
"intermediate_size": 3072,
|
| 40 |
+
"is_encoder_decoder": false,
|
| 41 |
+
"label2id": {
|
| 42 |
+
"LABEL_0": 0,
|
| 43 |
+
"LABEL_1": 1
|
| 44 |
+
},
|
| 45 |
+
"layer_types": [
|
| 46 |
+
"full_attention",
|
| 47 |
+
"full_attention",
|
| 48 |
+
"full_attention",
|
| 49 |
+
"full_attention",
|
| 50 |
+
"full_attention",
|
| 51 |
+
"full_attention",
|
| 52 |
+
"full_attention",
|
| 53 |
+
"full_attention",
|
| 54 |
+
"full_attention",
|
| 55 |
+
"full_attention",
|
| 56 |
+
"full_attention",
|
| 57 |
+
"full_attention",
|
| 58 |
+
"full_attention",
|
| 59 |
+
"full_attention",
|
| 60 |
+
"full_attention",
|
| 61 |
+
"full_attention",
|
| 62 |
+
"full_attention",
|
| 63 |
+
"full_attention",
|
| 64 |
+
"full_attention",
|
| 65 |
+
"full_attention",
|
| 66 |
+
"full_attention",
|
| 67 |
+
"full_attention",
|
| 68 |
+
"full_attention",
|
| 69 |
+
"full_attention",
|
| 70 |
+
"full_attention",
|
| 71 |
+
"full_attention",
|
| 72 |
+
"full_attention",
|
| 73 |
+
"full_attention"
|
| 74 |
+
],
|
| 75 |
+
"max_position_embeddings": 40960,
|
| 76 |
+
"max_window_layers": 28,
|
| 77 |
+
"model_type": "qwen3",
|
| 78 |
+
"num_attention_heads": 16,
|
| 79 |
+
"num_hidden_layers": 28,
|
| 80 |
+
"num_key_value_heads": 8,
|
| 81 |
+
"output_attentions": false,
|
| 82 |
+
"output_hidden_states": false,
|
| 83 |
+
"pad_token_id": null,
|
| 84 |
+
"problem_type": null,
|
| 85 |
+
"return_dict": true,
|
| 86 |
+
"rms_norm_eps": 1e-06,
|
| 87 |
+
"rope_parameters": {
|
| 88 |
+
"rope_theta": 1000000,
|
| 89 |
+
"rope_type": "default"
|
| 90 |
+
},
|
| 91 |
+
"sliding_window": null,
|
| 92 |
+
"tie_word_embeddings": true,
|
| 93 |
+
"use_cache": true,
|
| 94 |
+
"use_sliding_window": false,
|
| 95 |
+
"vocab_size": 151676
|
| 96 |
+
},
|
| 97 |
+
"model_type": "omnivoice",
|
| 98 |
+
"num_audio_codebook": 8,
|
| 99 |
+
"pad_token_id": 151643,
|
| 100 |
+
"transformers_version": "5.3.0"
|
| 101 |
+
}
|
miner.py
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Vocence SN78 PromptTTS engine for OmniVoice (k2-fsa/OmniVoice).
|
| 3 |
+
|
| 4 |
+
OmniVoice voice-design mode only accepts whitelisted comma-separated attributes
|
| 5 |
+
in ``instruct``; free-form validator ``instruction`` is mapped to those tags.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
import re
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
from typing import Any, Mapping
|
| 13 |
+
|
| 14 |
+
import numpy as np
|
| 15 |
+
|
| 16 |
+
_VOCENCE_YAML = "vocence_config.yaml"
|
| 17 |
+
_ZH_RE = re.compile(r"[\u4e00-\u9fff]")
|
| 18 |
+
_WORD_RE = re.compile(r"\w+", re.UNICODE)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def _read_vocence_yaml(repo: Path) -> dict[str, Any]:
|
| 22 |
+
path = repo / _VOCENCE_YAML
|
| 23 |
+
if not path.is_file():
|
| 24 |
+
return {}
|
| 25 |
+
from yaml import safe_load
|
| 26 |
+
|
| 27 |
+
with path.open("r", encoding="utf-8") as fh:
|
| 28 |
+
data = safe_load(fh)
|
| 29 |
+
return data if isinstance(data, Mapping) else {}
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def _has_cjk(s: str) -> bool:
|
| 33 |
+
return bool(re.search(r"[\u3040-\u30ff\u3100-\u312f\u3400-\u9fff\uac00-\ud7af]", s))
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def _pick_language(text: str, instruction_lower: str, default_lang: str = "English") -> str | None:
|
| 37 |
+
t, ins = text or "", instruction_lower or ""
|
| 38 |
+
if "japanese" in ins or "日本" in t or re.search(r"[\u3040-\u30ff]", t):
|
| 39 |
+
return "Japanese"
|
| 40 |
+
if "korean" in ins or "한글" in t or re.search(r"[\uac00-\ud7af]", t):
|
| 41 |
+
return "Korean"
|
| 42 |
+
if _has_cjk(t) or "chinese" in ins or "mandarin" in ins or "cantonese" in ins:
|
| 43 |
+
return "Chinese"
|
| 44 |
+
if any(
|
| 45 |
+
w in ins
|
| 46 |
+
for w in (
|
| 47 |
+
"french",
|
| 48 |
+
"german",
|
| 49 |
+
"spanish",
|
| 50 |
+
"italian",
|
| 51 |
+
"portuguese",
|
| 52 |
+
"russian",
|
| 53 |
+
"arabic",
|
| 54 |
+
"hindi",
|
| 55 |
+
)
|
| 56 |
+
):
|
| 57 |
+
for name in (
|
| 58 |
+
"French",
|
| 59 |
+
"German",
|
| 60 |
+
"Spanish",
|
| 61 |
+
"Italian",
|
| 62 |
+
"Portuguese",
|
| 63 |
+
"Russian",
|
| 64 |
+
"Arabic",
|
| 65 |
+
"Hindi",
|
| 66 |
+
):
|
| 67 |
+
if name.lower() in ins:
|
| 68 |
+
return name
|
| 69 |
+
return default_lang if default_lang else None
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def _inject_natural_punctuation(text: str) -> str:
|
| 73 |
+
"""Light pacing hints for long unpunctuated Latin text (OmniVoice benefits from boundaries)."""
|
| 74 |
+
if not text or not text.strip():
|
| 75 |
+
return text
|
| 76 |
+
if _has_cjk(text):
|
| 77 |
+
return text
|
| 78 |
+
words = _WORD_RE.findall(text)
|
| 79 |
+
if len(words) < 22:
|
| 80 |
+
return text
|
| 81 |
+
if len(re.findall(r"[,.;:!?]", text)) >= max(2, len(words) // 14):
|
| 82 |
+
return text
|
| 83 |
+
parts: list[str] = []
|
| 84 |
+
breaks = ("and", "but", "or", "yet", "so", "while", "however", "therefore")
|
| 85 |
+
wix = 0
|
| 86 |
+
i = 0
|
| 87 |
+
n = len(text)
|
| 88 |
+
last_break_at = -10
|
| 89 |
+
while i < n:
|
| 90 |
+
ch = text[i]
|
| 91 |
+
if ch.isalnum():
|
| 92 |
+
j = i
|
| 93 |
+
while j < n and (text[j].isalnum() or text[j] == "'"):
|
| 94 |
+
j += 1
|
| 95 |
+
token = text[i:j]
|
| 96 |
+
low = token.lower()
|
| 97 |
+
if (
|
| 98 |
+
low in breaks
|
| 99 |
+
and wix > 0
|
| 100 |
+
and (wix - last_break_at) >= 8
|
| 101 |
+
):
|
| 102 |
+
while parts and parts[-1] == " ":
|
| 103 |
+
parts.pop()
|
| 104 |
+
parts.append(", ")
|
| 105 |
+
last_break_at = wix
|
| 106 |
+
parts.append(token)
|
| 107 |
+
wix += 1
|
| 108 |
+
i = j
|
| 109 |
+
else:
|
| 110 |
+
parts.append(ch)
|
| 111 |
+
i += 1
|
| 112 |
+
return "".join(parts)
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def _nl_to_omnivoice_instruct(
|
| 116 |
+
instruction: str,
|
| 117 |
+
text: str,
|
| 118 |
+
*,
|
| 119 |
+
default_instruct: str,
|
| 120 |
+
) -> str:
|
| 121 |
+
"""Map free-form NL to OmniVoice voice-design tags (English or Chinese dialect tokens)."""
|
| 122 |
+
raw = (instruction or "").strip()
|
| 123 |
+
t = text or ""
|
| 124 |
+
|
| 125 |
+
gender: str | None = None
|
| 126 |
+
age: str | None = None
|
| 127 |
+
pitch: str | None = None
|
| 128 |
+
style: str | None = None
|
| 129 |
+
accent: str | None = None
|
| 130 |
+
dialect_zh: str | None = None
|
| 131 |
+
|
| 132 |
+
s = raw.lower()
|
| 133 |
+
# Gender
|
| 134 |
+
female = any(
|
| 135 |
+
k in s
|
| 136 |
+
for k in (
|
| 137 |
+
"female",
|
| 138 |
+
"woman",
|
| 139 |
+
"girl",
|
| 140 |
+
"lady",
|
| 141 |
+
"mother",
|
| 142 |
+
"soprano",
|
| 143 |
+
"feminine",
|
| 144 |
+
"herself",
|
| 145 |
+
)
|
| 146 |
+
) or bool(re.search(r"\b(she|her)\b", s))
|
| 147 |
+
male = any(
|
| 148 |
+
k in s
|
| 149 |
+
for k in (
|
| 150 |
+
"male",
|
| 151 |
+
"man",
|
| 152 |
+
"boy",
|
| 153 |
+
"gentleman",
|
| 154 |
+
"father",
|
| 155 |
+
"baritone",
|
| 156 |
+
"masculine",
|
| 157 |
+
"himself",
|
| 158 |
+
)
|
| 159 |
+
) or bool(re.search(r"\b(he|his|him)\b", s))
|
| 160 |
+
if female and not male:
|
| 161 |
+
gender = "female"
|
| 162 |
+
elif male and not female:
|
| 163 |
+
gender = "male"
|
| 164 |
+
|
| 165 |
+
# Age
|
| 166 |
+
if any(k in s for k in ("child", "kid", "toddler")):
|
| 167 |
+
age = "child"
|
| 168 |
+
elif "teen" in s or "teenager" in s:
|
| 169 |
+
age = "teenager"
|
| 170 |
+
elif any(k in s for k in ("elderly", "old man", "old woman", "senior", "grandfather", "grandmother")):
|
| 171 |
+
age = "elderly"
|
| 172 |
+
elif any(k in s for k in ("middle-aged", "middle aged", "mature")):
|
| 173 |
+
age = "middle-aged"
|
| 174 |
+
elif any(k in s for k in ("young adult", "young woman", "young man", "adult")):
|
| 175 |
+
age = "young adult"
|
| 176 |
+
elif "young" in s and "young adult" not in s:
|
| 177 |
+
age = "young adult"
|
| 178 |
+
|
| 179 |
+
# Pitch
|
| 180 |
+
if any(k in s for k in ("very low", "very deep", "bass", "gravely low")):
|
| 181 |
+
pitch = "very low pitch"
|
| 182 |
+
elif any(k in s for k in ("low pitch", "deep voice", "low voice", "baritone")) or "deep" in s:
|
| 183 |
+
pitch = "low pitch"
|
| 184 |
+
elif any(k in s for k in ("very high", "shrill", "squeaky")):
|
| 185 |
+
pitch = "very high pitch"
|
| 186 |
+
elif any(k in s for k in ("high pitch", "high voice")) or "high-pitched" in s:
|
| 187 |
+
pitch = "high pitch"
|
| 188 |
+
elif any(k in s for k in ("moderate", "neutral", "mid", "mid-range", "normal pitch")):
|
| 189 |
+
pitch = "moderate pitch"
|
| 190 |
+
|
| 191 |
+
if "whisper" in s or "whispering" in s:
|
| 192 |
+
style = "whisper"
|
| 193 |
+
|
| 194 |
+
# English accents (mutually exclusive — first match wins)
|
| 195 |
+
accent_rules = (
|
| 196 |
+
("british", "british accent"),
|
| 197 |
+
("uk accent", "british accent"),
|
| 198 |
+
("scottish", "british accent"),
|
| 199 |
+
("american", "american accent"),
|
| 200 |
+
("us accent", "american accent"),
|
| 201 |
+
("australian", "australian accent"),
|
| 202 |
+
("indian accent", "indian accent"),
|
| 203 |
+
("indian english", "indian accent"),
|
| 204 |
+
("canadian", "canadian accent"),
|
| 205 |
+
("russian accent", "russian accent"),
|
| 206 |
+
("japanese accent", "japanese accent"),
|
| 207 |
+
("korean accent", "korean accent"),
|
| 208 |
+
("portuguese accent", "portuguese accent"),
|
| 209 |
+
("chinese accent", "chinese accent"),
|
| 210 |
+
)
|
| 211 |
+
for key, tag in accent_rules:
|
| 212 |
+
if key in s:
|
| 213 |
+
accent = tag
|
| 214 |
+
break
|
| 215 |
+
|
| 216 |
+
# Chinese dialects (Chinese chars / keywords)
|
| 217 |
+
zh_dialect = (
|
| 218 |
+
("四川", "四川话"),
|
| 219 |
+
("sichuan", "四川话"),
|
| 220 |
+
("东北", "东北话"),
|
| 221 |
+
("陕西", "陕西话"),
|
| 222 |
+
("河南", "河南话"),
|
| 223 |
+
("云南", "云南话"),
|
| 224 |
+
("贵州", "贵州话"),
|
| 225 |
+
("山东", "济南话"),
|
| 226 |
+
("青岛", "青岛话"),
|
| 227 |
+
("石家庄", "石家庄话"),
|
| 228 |
+
("甘肃", "甘肃话"),
|
| 229 |
+
("宁夏", "宁夏话"),
|
| 230 |
+
("桂林", "桂林话"),
|
| 231 |
+
("济南", "济南话"),
|
| 232 |
+
)
|
| 233 |
+
ins_or_t = raw + t
|
| 234 |
+
for key, tag in zh_dialect:
|
| 235 |
+
if key in ins_or_t:
|
| 236 |
+
dialect_zh = tag
|
| 237 |
+
break
|
| 238 |
+
|
| 239 |
+
parts: list[str] = []
|
| 240 |
+
if dialect_zh:
|
| 241 |
+
zh_bits: list[str] = []
|
| 242 |
+
if gender == "female":
|
| 243 |
+
zh_bits.append("女")
|
| 244 |
+
elif gender == "male":
|
| 245 |
+
zh_bits.append("男")
|
| 246 |
+
if age == "child":
|
| 247 |
+
zh_bits.append("儿童")
|
| 248 |
+
elif age == "teenager":
|
| 249 |
+
zh_bits.append("少年")
|
| 250 |
+
elif age in ("young adult", "middle-aged"):
|
| 251 |
+
zh_bits.append("青年" if age == "young adult" else "中年")
|
| 252 |
+
elif age == "elderly":
|
| 253 |
+
zh_bits.append("老年")
|
| 254 |
+
if pitch == "very low pitch":
|
| 255 |
+
zh_bits.append("极低音调")
|
| 256 |
+
elif pitch == "low pitch":
|
| 257 |
+
zh_bits.append("低音调")
|
| 258 |
+
elif pitch == "moderate pitch":
|
| 259 |
+
zh_bits.append("中音调")
|
| 260 |
+
elif pitch == "high pitch":
|
| 261 |
+
zh_bits.append("高音调")
|
| 262 |
+
elif pitch == "very high pitch":
|
| 263 |
+
zh_bits.append("极高音调")
|
| 264 |
+
if style == "whisper":
|
| 265 |
+
zh_bits.append("耳语")
|
| 266 |
+
zh_bits.append(dialect_zh)
|
| 267 |
+
return ",".join(zh_bits)
|
| 268 |
+
|
| 269 |
+
# English path
|
| 270 |
+
for x in (gender, age, pitch, style, accent):
|
| 271 |
+
if x:
|
| 272 |
+
parts.append(x)
|
| 273 |
+
if not parts:
|
| 274 |
+
return default_instruct.strip() or "young adult, moderate pitch, american accent"
|
| 275 |
+
|
| 276 |
+
# Omnivoice rejects mixing accent with Chinese dialect — we handled dialect above.
|
| 277 |
+
return ", ".join(parts)
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
def _speed_from_instruction(s: str) -> float | None:
|
| 281 |
+
s = (s or "").lower()
|
| 282 |
+
if any(w in s for w in ("very slow", "slowly", "unhurried")):
|
| 283 |
+
return 0.85
|
| 284 |
+
if "slow" in s:
|
| 285 |
+
return 0.93
|
| 286 |
+
if any(w in s for w in ("very fast", "rapid", "quickly", "hurried")):
|
| 287 |
+
return 1.12
|
| 288 |
+
if "fast" in s:
|
| 289 |
+
return 1.06
|
| 290 |
+
return None
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
def _to_mono_f32(segment: np.ndarray) -> np.ndarray:
|
| 294 |
+
arr = np.asarray(segment, dtype=np.float32)
|
| 295 |
+
if arr.ndim > 1:
|
| 296 |
+
arr = arr.mean(axis=-1)
|
| 297 |
+
return np.ascontiguousarray(arr, dtype=np.float32)
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
def _peak_normalize(wav: np.ndarray, ceiling: float = 0.38) -> np.ndarray:
|
| 301 |
+
if wav.size == 0:
|
| 302 |
+
return wav
|
| 303 |
+
p = float(np.max(np.abs(wav)))
|
| 304 |
+
if p <= 0 or p <= ceiling:
|
| 305 |
+
return wav
|
| 306 |
+
return (wav * (ceiling / p)).astype(np.float32, copy=False)
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
class Miner:
|
| 310 |
+
"""OmniVoice engine: NL ``instruction`` → voice-design ``instruct``; ``text`` → speech."""
|
| 311 |
+
|
| 312 |
+
def __init__(self, path_hf_repo: Path) -> None:
|
| 313 |
+
import torch
|
| 314 |
+
from omnivoice import OmniVoice
|
| 315 |
+
|
| 316 |
+
self._root = Path(path_hf_repo).resolve()
|
| 317 |
+
if not (self._root / "config.json").is_file():
|
| 318 |
+
raise FileNotFoundError(f"Missing config.json under {self._root}")
|
| 319 |
+
|
| 320 |
+
cfg = _read_vocence_yaml(self._root)
|
| 321 |
+
runtime = cfg.get("runtime") or {}
|
| 322 |
+
limits = cfg.get("limits") or {}
|
| 323 |
+
gen = cfg.get("generation") or {}
|
| 324 |
+
|
| 325 |
+
self._cap_instruction = int(limits.get("max_instruction_chars", 600))
|
| 326 |
+
self._cap_text = int(limits.get("max_text_chars", 2000))
|
| 327 |
+
self._max_seconds = float(gen.get("max_seconds", 30))
|
| 328 |
+
self._default_language = str(limits.get("default_language") or runtime.get("default_language", "English"))
|
| 329 |
+
self._default_instruct = str(
|
| 330 |
+
runtime.get("default_instruct") or "young adult, moderate pitch, american accent"
|
| 331 |
+
)
|
| 332 |
+
self._num_step = int(runtime.get("num_step", 24))
|
| 333 |
+
self._guidance_scale = float(runtime.get("guidance_scale", 2.0))
|
| 334 |
+
|
| 335 |
+
prefer_cuda = torch.cuda.is_available()
|
| 336 |
+
ckpt = str(self._root)
|
| 337 |
+
dtype = torch.float16 if prefer_cuda else torch.float32
|
| 338 |
+
map_kw: dict[str, Any] = {"dtype": dtype}
|
| 339 |
+
if prefer_cuda:
|
| 340 |
+
map_kw["device_map"] = "cuda:0"
|
| 341 |
+
else:
|
| 342 |
+
map_kw["device_map"] = "cpu"
|
| 343 |
+
|
| 344 |
+
self._torch = torch
|
| 345 |
+
self._model = OmniVoice.from_pretrained(ckpt, **map_kw)
|
| 346 |
+
|
| 347 |
+
def warmup(self) -> None:
|
| 348 |
+
_ = self.generate_wav(
|
| 349 |
+
"Speak clearly in a neutral American accent.",
|
| 350 |
+
"Warm-up.",
|
| 351 |
+
)
|
| 352 |
+
|
| 353 |
+
def generate_wav(self, instruction: str, text: str) -> tuple[np.ndarray, int]:
|
| 354 |
+
if not text or not str(text).strip():
|
| 355 |
+
raise ValueError("text must be non-empty")
|
| 356 |
+
|
| 357 |
+
inst_full = (instruction or "").strip()[: self._cap_instruction]
|
| 358 |
+
tts_text = _inject_natural_punctuation(str(text).strip()[: self._cap_text])
|
| 359 |
+
lang = _pick_language(tts_text, inst_full.lower(), self._default_language)
|
| 360 |
+
|
| 361 |
+
instruct = _nl_to_omnivoice_instruct(
|
| 362 |
+
inst_full, tts_text, default_instruct=self._default_instruct
|
| 363 |
+
)
|
| 364 |
+
speed = _speed_from_instruction(inst_full)
|
| 365 |
+
|
| 366 |
+
gen_kwargs: dict[str, Any] = dict(
|
| 367 |
+
num_step=self._num_step,
|
| 368 |
+
guidance_scale=self._guidance_scale,
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
audios = self._model.generate(
|
| 372 |
+
text=tts_text,
|
| 373 |
+
language=lang,
|
| 374 |
+
instruct=instruct,
|
| 375 |
+
speed=speed,
|
| 376 |
+
**gen_kwargs,
|
| 377 |
+
)
|
| 378 |
+
if not audios:
|
| 379 |
+
raise ValueError("OmniVoice returned no audio")
|
| 380 |
+
first = audios[0]
|
| 381 |
+
if first is None or first.size == 0:
|
| 382 |
+
raise ValueError("OmniVoice returned empty audio")
|
| 383 |
+
|
| 384 |
+
sr = int(getattr(self._model, "sampling_rate", None) or 24000)
|
| 385 |
+
wav = _peak_normalize(_to_mono_f32(first))
|
| 386 |
+
dur = float(wav.shape[0]) / float(sr)
|
| 387 |
+
if dur > self._max_seconds + 1e-3:
|
| 388 |
+
max_samples = int(self._max_seconds * sr)
|
| 389 |
+
wav = wav[:max_samples]
|
| 390 |
+
|
| 391 |
+
return wav, sr
|
tokenizer.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:408f669b7e2b045fdf54201d815bd364e6667dbd845115da81239c40bc6dcfd1
|
| 3 |
+
size 11423986
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": null,
|
| 5 |
+
"clean_up_tokenization_spaces": false,
|
| 6 |
+
"eos_token": "<|im_end|>",
|
| 7 |
+
"errors": "replace",
|
| 8 |
+
"extra_special_tokens": [
|
| 9 |
+
"<|denoise|>",
|
| 10 |
+
"<|lang_start|>",
|
| 11 |
+
"<|lang_end|>",
|
| 12 |
+
"<|instruct_start|>",
|
| 13 |
+
"<|instruct_end|>",
|
| 14 |
+
"<|text_start|>",
|
| 15 |
+
"<|text_end|>"
|
| 16 |
+
],
|
| 17 |
+
"is_local": true,
|
| 18 |
+
"model_max_length": 131072,
|
| 19 |
+
"pad_token": "<|endoftext|>",
|
| 20 |
+
"split_special_tokens": false,
|
| 21 |
+
"tokenizer_class": "Qwen2Tokenizer",
|
| 22 |
+
"unk_token": null
|
| 23 |
+
}
|
vocence_config.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Vocence PromptTTS — OmniVoice (voice design). See miner.py for NL → instruct mapping.
|
| 2 |
+
|
| 3 |
+
runtime:
|
| 4 |
+
adapter: "omnivoice_voice_design"
|
| 5 |
+
device_preference: "cuda"
|
| 6 |
+
dtype: "float16"
|
| 7 |
+
default_language: "English"
|
| 8 |
+
# When the NL instruction does not map to any OmniVoice attribute, use this valid instruct:
|
| 9 |
+
default_instruct: "young adult, moderate pitch, american accent"
|
| 10 |
+
# Optional generation overrides (passed to OmniVoice.generate)
|
| 11 |
+
num_step: 24
|
| 12 |
+
guidance_scale: 2.0
|
| 13 |
+
|
| 14 |
+
generation:
|
| 15 |
+
sample_rate: 24000
|
| 16 |
+
max_seconds: 30
|
| 17 |
+
|
| 18 |
+
limits:
|
| 19 |
+
max_text_chars: 2000
|
| 20 |
+
max_instruction_chars: 600
|
| 21 |
+
default_language: "English"
|