aiseosae commited on
Commit
87c19a6
·
verified ·
1 Parent(s): 758e465

Upload folder using huggingface_hub

Browse files
.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
README.md ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: cc-by-nc-sa-4.0
3
+ base_model: Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign
4
+ pipeline_tag: text-to-speech
5
+ library_name: transformers
6
+ language:
7
+ - en
8
+ tags:
9
+ - tts
10
+ - qwen3-tts
11
+ - voice-design
12
+ - prompttts
13
+ - vocence
14
+ - bittensor
15
+ ---
16
+
17
+
18
+
19
+ Inference uses **`qwen_tts.Qwen3TTSModel`**, loaded from the repo root via `from_pretrained(this_folder)`.
20
+
21
+ ## Layout
22
+
23
+ | Path | Role |
24
+ |------|------|
25
+ | `config.json`, weights, tokenizer, codec dirs | Qwen3-TTS snapshot (as shipped by the upstream model card) |
26
+ | `miner.py` | Vocence engine: `Miner`, `warmup()`, `generate_wav(instruction, text)` |
27
+ | `vocence_config.yaml` | Device, dtype, caps, language |
28
+ | `chute_config.yml` | Chutes image / GPU / scaling / TEE |
29
+ | `demo.py` | Optional local smoke test (if present) |
30
+
31
+ ## Vocence API
32
+
33
+ Validators call your deployed chute with JSON shaped like:
34
+
35
+ ```json
36
+ {
37
+ "text": "Words to speak.",
38
+ "instruction": "gender: male | pitch: mid | speed: normal | age_group: adult | emotion: neutral | tone: casual | accent: us"
39
+ }
40
+ ```
41
+
42
+ The miner forwards **`text`** → `generate_voice_design(..., text=...)` and **`instruction`** → `instruct=...`, using **`language`** from config (default English).
43
+
44
+ ## Configure (`vocence_config.yaml`)
45
+
46
+ | Area | Keys |
47
+ |------|------|
48
+ | Runtime | `device_preference` (`cuda` / `cpu`), `dtype` (`bfloat16` / `float32`), `use_flash_attention_2`, `default_language` |
49
+ | Generation | `sample_rate` (e.g. 24000), `max_seconds` |
50
+ | Limits | `max_text_chars`, `max_instruction_chars`, `default_language` |
51
+
52
+ Warmup runs one short `generate_voice_design` with a **180 s** timeout.
53
+
54
+ ## Local quick test
55
+
56
+ Install PyTorch (CUDA if available), then:
57
+
58
+ ```bash
59
+ pip install "qwen-tts" pyyaml soundfile numpy
60
+ ```
61
+
62
+ ```python
63
+ from pathlib import Path
64
+ from miner import Miner
65
+
66
+ miner = Miner(Path("."))
67
+ miner.warmup()
68
+ wave, sr = miner.generate_wav(
69
+ instruction="A calm, clear narrator, neutral US accent.",
70
+ text="Hello — this is a short synthesis check.",
71
+ )
72
+ ```
73
+
74
+ Or load the class directly from transformers-style layout:
75
+
76
+ ```python
77
+ from qwen_tts import Qwen3TTSModel
78
+
79
+ model = Qwen3TTSModel.from_pretrained(".") # or your HF repo id
80
+ wavs, sr = model.generate_voice_design(
81
+ text="Hello fellas.",
82
+ instruct="Cute voice.",
83
+ language="english",
84
+ )
85
+ ```
86
+
87
+ Replace `"."` with your HF repo id after upload, e.g. `"your-org/your-repo"`.
88
+
89
+ ## Chutes / Vocence deploy
90
+
91
+ 1. Push this layout to a Hugging Face **model** repo; pin a **commit SHA** for `VOCENCE_REVISION`.
92
+ 2. Render the canonical Vocence chute script with `VOCENCE_REPO`, `VOCENCE_REVISION`, `VOCENCE_CHUTES_USER`, `VOCENCE_CHUTE_ID`.
93
+ 3. `chutes build … --wait` then `chutes deploy … --accept-fee`.
94
+ 4. Commit on chain: `model_name`, `model_revision` (HF SHA), `chute_id` (UUID from Chutes).
95
+
96
+ Chute **name** must contain **`vocence`** (case-insensitive). See **`miner_sample/MINER_GUIDE.md`** in the Vocence repo.
97
+
98
+ ## Training / fine-tuning
99
+
100
+ Fine-tuning is done **outside** Chutes on your own GPU; export a full snapshot compatible with **`Qwen3TTSModel.from_pretrained(...)`**, then replace weights in this repo layout and push a new revision.
101
+
102
+ ## License
103
+
104
+ **CC BY-NC-SA 4.0** — see the license file in this repo. Respect upstream Qwen / Alibaba terms for the base checkpoint.
added_tokens.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "</think>": 151668,
3
+ "</tool_call>": 151658,
4
+ "</tool_response>": 151666,
5
+ "<think>": 151667,
6
+ "<tool_call>": 151657,
7
+ "<tool_response>": 151665,
8
+ "<tts_pad>": 151671,
9
+ "<tts_text_bos>": 151672,
10
+ "<tts_text_bos_single>": 151674,
11
+ "<tts_text_eod>": 151673,
12
+ "<|audio_end|>": 151670,
13
+ "<|audio_pad|>": 151675,
14
+ "<|audio_start|>": 151669,
15
+ "<|box_end|>": 151649,
16
+ "<|box_start|>": 151648,
17
+ "<|endoftext|>": 151643,
18
+ "<|file_sep|>": 151664,
19
+ "<|fim_middle|>": 151660,
20
+ "<|fim_pad|>": 151662,
21
+ "<|fim_prefix|>": 151659,
22
+ "<|fim_suffix|>": 151661,
23
+ "<|im_end|>": 151645,
24
+ "<|im_start|>": 151644,
25
+ "<|image_pad|>": 151655,
26
+ "<|object_ref_end|>": 151647,
27
+ "<|object_ref_start|>": 151646,
28
+ "<|quad_end|>": 151651,
29
+ "<|quad_start|>": 151650,
30
+ "<|repo_name|>": 151663,
31
+ "<|video_pad|>": 151656,
32
+ "<|vision_end|>": 151653,
33
+ "<|vision_pad|>": 151654,
34
+ "<|vision_start|>": 151652
35
+ }
chute_config.yml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Image + node + Chute for Vocence deploy. Required in the HF repo at build time.
2
+
3
+ Image:
4
+ from_base: parachutes/python:3.12
5
+ run_command:
6
+ - pip install torch torchaudio transformers accelerate huggingface_hub pyyaml soundfile librosa
7
+ - pip install -U qwen-tts
8
+ set_workdir: /app
9
+
10
+ NodeSelector:
11
+ gpu_count: 1
12
+ min_vram_gb_per_gpu: 24
13
+ include: ["pro_6000"]
14
+ exclude: []
15
+
16
+ Chute:
17
+ tagline: Vocence TTS — Qwen3 PromptTTS (weights in repo)
18
+ readme: Qwen3 12Hz TTS snapshot + miner.py for Vocence
19
+ shutdown_after_seconds: 86400
20
+ concurrency: 1
21
+ max_instances: 2
22
+ scaling_threshold: 0.5
23
+ tee: true
config.json ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3TTSForConditionalGeneration"
4
+ ],
5
+ "assistant_token_id": 77091,
6
+ "im_end_token_id": 151645,
7
+ "im_start_token_id": 151644,
8
+ "tts_bos_token_id": 151672,
9
+ "tts_eos_token_id": 151673,
10
+ "tts_pad_token_id": 151671,
11
+ "model_type": "qwen3_tts",
12
+ "tokenizer_type": "qwen3_tts_tokenizer_12hz",
13
+ "tts_model_size": "1b7",
14
+ "tts_model_type": "voice_design",
15
+ "talker_config": {
16
+ "attention_bias": false,
17
+ "attention_dropout": 0,
18
+ "code_predictor_config": {
19
+ "_name_or_path": "",
20
+ "add_cross_attention": false,
21
+ "architectures": null,
22
+ "attention_bias": false,
23
+ "attention_dropout": 0,
24
+ "bad_words_ids": null,
25
+ "begin_suppress_tokens": null,
26
+ "bos_token_id": null,
27
+ "chunk_size_feed_forward": 0,
28
+ "cross_attention_hidden_size": null,
29
+ "decoder_start_token_id": null,
30
+ "diversity_penalty": 0.0,
31
+ "do_sample": false,
32
+ "early_stopping": false,
33
+ "encoder_no_repeat_ngram_size": 0,
34
+ "eos_token_id": null,
35
+ "exponential_decay_length_penalty": null,
36
+ "finetuning_task": null,
37
+ "forced_bos_token_id": null,
38
+ "forced_eos_token_id": null,
39
+ "head_dim": 128,
40
+ "hidden_act": "silu",
41
+ "hidden_size": 1024,
42
+ "id2label": {
43
+ "0": "LABEL_0",
44
+ "1": "LABEL_1"
45
+ },
46
+ "initializer_range": 0.02,
47
+ "intermediate_size": 3072,
48
+ "is_decoder": false,
49
+ "is_encoder_decoder": false,
50
+ "label2id": {
51
+ "LABEL_0": 0,
52
+ "LABEL_1": 1
53
+ },
54
+ "layer_types": [
55
+ "full_attention",
56
+ "full_attention",
57
+ "full_attention",
58
+ "full_attention",
59
+ "full_attention"
60
+ ],
61
+ "length_penalty": 1.0,
62
+ "max_length": 20,
63
+ "max_position_embeddings": 65536,
64
+ "max_window_layers": 28,
65
+ "min_length": 0,
66
+ "model_type": "qwen3_tts_talker_code_predictor",
67
+ "no_repeat_ngram_size": 0,
68
+ "num_attention_heads": 16,
69
+ "num_beam_groups": 1,
70
+ "num_beams": 1,
71
+ "num_code_groups": 16,
72
+ "num_hidden_layers": 5,
73
+ "num_key_value_heads": 8,
74
+ "num_return_sequences": 1,
75
+ "output_attentions": false,
76
+ "output_hidden_states": false,
77
+ "output_scores": false,
78
+ "pad_token_id": null,
79
+ "prefix": null,
80
+ "problem_type": null,
81
+ "pruned_heads": {},
82
+ "remove_invalid_values": false,
83
+ "repetition_penalty": 1.0,
84
+ "return_dict": true,
85
+ "return_dict_in_generate": false,
86
+ "rms_norm_eps": 1e-06,
87
+ "rope_scaling": null,
88
+ "rope_theta": 1000000,
89
+ "sep_token_id": null,
90
+ "sliding_window": null,
91
+ "suppress_tokens": null,
92
+ "task_specific_params": null,
93
+ "temperature": 1.0,
94
+ "tf_legacy_loss": false,
95
+ "tie_encoder_decoder": false,
96
+ "tie_word_embeddings": false,
97
+ "tokenizer_class": null,
98
+ "top_k": 50,
99
+ "top_p": 1.0,
100
+ "dtype": null,
101
+ "torchscript": false,
102
+ "typical_p": 1.0,
103
+ "use_bfloat16": false,
104
+ "use_cache": true,
105
+ "use_sliding_window": false,
106
+ "vocab_size": 2048
107
+ },
108
+ "codec_bos_id": 2149,
109
+ "codec_eos_token_id": 2150,
110
+ "codec_think_id": 2154,
111
+ "codec_language_id": {
112
+ "chinese": 2055,
113
+ "english": 2050,
114
+ "german": 2053,
115
+ "italian": 2070,
116
+ "portuguese": 2071,
117
+ "spanish": 2054,
118
+ "japanese": 2058,
119
+ "korean": 2064,
120
+ "french": 2061,
121
+ "russian": 2069
122
+ },
123
+ "codec_nothink_id": 2155,
124
+ "codec_pad_id": 2148,
125
+ "codec_think_bos_id": 2156,
126
+ "codec_think_eos_id": 2157,
127
+ "spk_id": {
128
+ },
129
+ "spk_is_dialect": {
130
+ },
131
+ "head_dim": 128,
132
+ "hidden_act": "silu",
133
+ "hidden_size": 2048,
134
+ "initializer_range": 0.02,
135
+ "intermediate_size": 6144,
136
+ "max_position_embeddings": 32768,
137
+ "model_type": "qwen3_tts_talker",
138
+ "num_attention_heads": 16,
139
+ "num_code_groups": 16,
140
+ "num_hidden_layers": 28,
141
+ "num_key_value_heads": 8,
142
+ "position_id_per_seconds": 13,
143
+ "rms_norm_eps": 1e-06,
144
+ "rope_scaling": {
145
+ "interleaved": true,
146
+ "mrope_section": [
147
+ 24,
148
+ 20,
149
+ 20
150
+ ],
151
+ "rope_type": "default",
152
+ "type": "default"
153
+ },
154
+ "rope_theta": 1000000,
155
+ "sliding_window": null,
156
+ "text_hidden_size": 2048,
157
+ "text_vocab_size": 151936,
158
+ "use_cache": true,
159
+ "use_sliding_window": false,
160
+ "vocab_size": 3072
161
+ },
162
+ "transformers_version": "4.57.3"
163
+ }
generation_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "do_sample": true,
3
+ "repetition_penalty": 1.05,
4
+ "temperature": 0.9,
5
+ "top_p": 1.0,
6
+ "top_k": 50,
7
+ "subtalker_dosample": true,
8
+ "subtalker_temperature": 0.9,
9
+ "subtalker_top_p": 1.0,
10
+ "subtalker_top_k": 50,
11
+ "max_new_tokens": 8192
12
+ }
merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
miner.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from concurrent.futures import ThreadPoolExecutor, TimeoutError as FutureTimeout
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ import numpy as np
8
+
9
+
10
+ VOCENCE_CONFIG = "vocence_config.yaml"
11
+ QWEN_ANCHOR = "config.json"
12
+ WARMUP_SECONDS = 180.0
13
+
14
+ # Vocence validators split prompts into speakable `text` and trait `instruction`.
15
+ # Scoring weights script heavily (WER vs transcript) and compares extracted voice
16
+ # traits to these keys — enrich instructions so Qwen voice-design follows them.
17
+
18
+
19
+ def _trait_phrase(key: str, val: str) -> str | None:
20
+ k, v = key.strip().lower(), val.strip().lower()
21
+ if not v:
22
+ return None
23
+ if k == "gender":
24
+ return {
25
+ "male": "male speaker",
26
+ "female": "female speaker",
27
+ "neutral": "gender-neutral voice",
28
+ }.get(v, f"{v} gender presentation")
29
+ if k == "pitch":
30
+ return {"low": "low pitch", "mid": "mid pitch", "high": "high pitch"}.get(v, f"{v} pitch")
31
+ if k == "speed":
32
+ return {"slow": "slow pacing", "normal": "normal pacing", "fast": "fast pacing"}.get(
33
+ v, f"{v} speed"
34
+ )
35
+ if k == "age_group":
36
+ return {
37
+ "child": "childlike voice",
38
+ "young_adult": "young adult voice",
39
+ "adult": "adult voice",
40
+ "senior": "older adult voice",
41
+ }.get(v, f"{v} age character")
42
+ if k == "emotion":
43
+ return f"{v} emotional tone"
44
+ if k == "tone":
45
+ return f"{v} speaking tone"
46
+ if k == "accent":
47
+ return {
48
+ "us": "American English accent",
49
+ "uk": "British English accent",
50
+ "au": "Australian English accent",
51
+ "in": "Indian English accent",
52
+ "neutral": "neutral accent",
53
+ "other": "clear intelligible accent",
54
+ }.get(v, f"{v} accent")
55
+ return f"{k.replace('_', ' ')}: {v}"
56
+
57
+
58
+ def _expand_vocence_instruction(raw: str) -> str:
59
+ """Turn `gender: x | pitch: y | ...` into fluent voice-design text for Qwen3."""
60
+ s = (raw or "").strip()
61
+ if not s:
62
+ return "Neutral, clear, natural speech."
63
+
64
+ # Vocence trait lines use pipes and key: value pairs (see README).
65
+ if "|" in s and ":" in s:
66
+ phrases: list[str] = []
67
+ for chunk in s.split("|"):
68
+ chunk = chunk.strip()
69
+ if ":" in chunk:
70
+ key, _, val = chunk.partition(":")
71
+ p = _trait_phrase(key, val)
72
+ if p:
73
+ phrases.append(p)
74
+ elif chunk:
75
+ phrases.append(chunk)
76
+ if phrases:
77
+ return (
78
+ "Voice design — "
79
+ + "; ".join(phrases)
80
+ + ". Deliver the script naturally with clear articulation and human-like prosody."
81
+ )
82
+
83
+ return s
84
+
85
+
86
+ def _load_yaml(path: Path) -> dict[str, Any]:
87
+ if not path.is_file():
88
+ return {}
89
+ from yaml import safe_load
90
+ with path.open("r", encoding="utf-8") as fh:
91
+ return safe_load(fh) or {}
92
+
93
+
94
+ def _select_device(prefer_cuda: bool):
95
+ import torch
96
+ has_cuda = torch.cuda.is_available()
97
+ device = "cuda:0" if (prefer_cuda and has_cuda) else "cpu"
98
+ return device, torch, has_cuda
99
+
100
+
101
+ def _select_dtype(torch_mod, want_bf16: bool, has_cuda: bool):
102
+ return torch_mod.bfloat16 if (want_bf16 and has_cuda) else torch_mod.float32
103
+
104
+
105
+ def _build_qwen(snapshot: Path, device: str, dtype: Any, attn: str):
106
+ from qwen_tts import Qwen3TTSModel
107
+ return Qwen3TTSModel.from_pretrained(
108
+ pretrained_model_name_or_path=str(snapshot),
109
+ device_map=device,
110
+ dtype=dtype,
111
+ attn_implementation=attn,
112
+ )
113
+
114
+
115
+ def _attn_order(prefer_flash: bool) -> tuple[str, ...]:
116
+ return ("flash_attention_2", "sdpa") if prefer_flash else ("sdpa",)
117
+
118
+
119
+ def _mono_pcm(arr: Any) -> np.ndarray:
120
+ wave = np.asarray(arr, dtype=np.float32)
121
+ return wave.mean(axis=1) if wave.ndim > 1 else wave
122
+
123
+
124
+ def _settings(snapshot: Path) -> dict[str, Any]:
125
+ raw = _load_yaml(snapshot / VOCENCE_CONFIG)
126
+ rt = raw.get("runtime") or {}
127
+ gen = raw.get("generation") or {}
128
+ lim = raw.get("limits") or {}
129
+ return {
130
+ "language": str(lim.get("default_language") or rt.get("default_language") or "English"),
131
+ "sample_rate": int(gen.get("sample_rate", 24000)),
132
+ "cap_instruct": int(lim.get("max_instruction_chars", 600)),
133
+ "cap_text": int(lim.get("max_text_chars", 2000)),
134
+ "prefer_cuda": str(rt.get("device_preference", "cuda")).lower() == "cuda",
135
+ "prefer_bf16": str(rt.get("dtype", "bfloat16")).lower() == "bfloat16",
136
+ "prefer_flash": bool(rt.get("use_flash_attention_2", False)),
137
+ # If True, rewrite trait pipes into richer English for the instruct field.
138
+ "expand_instruction": bool(rt.get("expand_vocence_instruction", True)),
139
+ }
140
+
141
+
142
+ class Miner:
143
+
144
+ def __init__(self, path_hf_repo: Path) -> None:
145
+ snapshot = Path(path_hf_repo).resolve()
146
+ if not (snapshot / QWEN_ANCHOR).is_file():
147
+ raise FileNotFoundError(f"snapshot missing {QWEN_ANCHOR}: {snapshot}")
148
+ self.snapshot = snapshot
149
+ self.cfg = _settings(snapshot)
150
+
151
+ device, torch_mod, has_cuda = _select_device(self.cfg["prefer_cuda"])
152
+ dtype = _select_dtype(torch_mod, self.cfg["prefer_bf16"], has_cuda)
153
+
154
+ last_err: BaseException | None = None
155
+ engine = None
156
+ for attn in _attn_order(self.cfg["prefer_flash"]):
157
+ try:
158
+ engine = _build_qwen(snapshot, device, dtype, attn)
159
+ tag = "bf16" if self.cfg["prefer_bf16"] and has_cuda else "fp32"
160
+ print(f"[Miner] qwen3-tts ready: device={device} dtype={tag} attn={attn}")
161
+ break
162
+ except Exception as exc:
163
+ last_err = exc
164
+ if engine is None:
165
+ raise RuntimeError(f"qwen3-tts load failed: {last_err!r}")
166
+ self.engine = engine
167
+
168
+ def __repr__(self) -> str:
169
+ return f"<Miner snapshot={self.snapshot.name} lang={self.cfg['language']!r}>"
170
+
171
+ def warmup(self) -> None:
172
+ instruct = (
173
+ "Voice design — male speaker; mid pitch; normal pacing; adult voice; "
174
+ "neutral emotional tone; casual speaking tone; American English accent. "
175
+ "Deliver naturally with clear articulation."
176
+ )
177
+ with ThreadPoolExecutor(max_workers=1) as pool:
178
+ future = pool.submit(self.generate_wav, instruct, "Warmup phrase for inference.")
179
+ try:
180
+ future.result(timeout=WARMUP_SECONDS)
181
+ except FutureTimeout:
182
+ raise RuntimeError(f"Miner warmup exceeded {WARMUP_SECONDS}s")
183
+
184
+ def generate_wav(self, instruction: str, text: str) -> tuple[np.ndarray, int]:
185
+ """Synthesize mono float32 PCM.
186
+
187
+ **Do not rewrite `text`** — Vocence scores script via word error rate vs the
188
+ requested transcript. Only `instruction` guides voice traits and naturalness.
189
+ """
190
+ cap_i = self.cfg["cap_instruct"]
191
+ cap_t = self.cfg["cap_text"]
192
+ raw_instr = instruction[:cap_i] if cap_i > 0 else instruction
193
+ if self.cfg.get("expand_instruction", True):
194
+ expanded = _expand_vocence_instruction(raw_instr)
195
+ prompt = expanded[:cap_i] if cap_i > 0 else expanded
196
+ else:
197
+ prompt = raw_instr
198
+
199
+ body = text[:cap_t] if cap_t > 0 else text
200
+
201
+ wavs, sr = self.engine.generate_voice_design(
202
+ text=body,
203
+ instruct=prompt,
204
+ language=self.cfg["language"],
205
+ )
206
+ if not wavs or wavs[0] is None:
207
+ raise ValueError("qwen3-tts returned no audio")
208
+ return _mono_pcm(wavs[0]), int(sr)
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e4d4433151c6b6dd291818a3c7116cea1b2082542fbb70ce22e5ffb937c488fe
3
+ size 3833402644
preprocessor_config.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "padding_side": "left",
3
+ "padding_value": 0.0,
4
+ "processor_class": "Qwen3TTSProcessor",
5
+ "return_attention_mask": true
6
+ }
special_tokens_map.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ "<|im_start|>",
4
+ "<|im_end|>",
5
+ "<|object_ref_start|>",
6
+ "<|object_ref_end|>",
7
+ "<|box_start|>",
8
+ "<|box_end|>",
9
+ "<|quad_start|>",
10
+ "<|quad_end|>",
11
+ "<|vision_start|>",
12
+ "<|vision_end|>",
13
+ "<|vision_pad|>",
14
+ "<|image_pad|>",
15
+ "<|video_pad|>",
16
+ "<|audio_start|>",
17
+ "<|audio_end|>",
18
+ "<tts_pad>",
19
+ "<tts_text_bos>",
20
+ "<tts_text_bos_single>",
21
+ "<|audio_pad|>"
22
+ ],
23
+ "audio_bos_token": "<|audio_start|>",
24
+ "audio_eos_token": "<|audio_end|>",
25
+ "audio_token": "<|audio_pad|>",
26
+ "eos_token": {
27
+ "content": "<|im_end|>",
28
+ "lstrip": false,
29
+ "normalized": false,
30
+ "rstrip": false,
31
+ "single_word": false
32
+ },
33
+ "image_token": "<|image_pad|>",
34
+ "pad_token": {
35
+ "content": "<|endoftext|>",
36
+ "lstrip": false,
37
+ "normalized": false,
38
+ "rstrip": false,
39
+ "single_word": false
40
+ },
41
+ "video_token": "<|video_pad|>",
42
+ "vision_bos_token": "<|vision_start|>",
43
+ "vision_eos_token": "<|vision_end|>"
44
+ }
speech_tokenizer/config.json ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3TTSTokenizerV2Model"
4
+ ],
5
+ "model_type": "qwen3_tts_tokenizer_12hz",
6
+ "encoder_valid_num_quantizers": 16,
7
+ "input_sample_rate": 24000,
8
+ "output_sample_rate": 24000,
9
+ "decode_upsample_rate": 1920,
10
+ "encode_downsample_rate": 1920,
11
+ "decoder_config": {
12
+ "attention_bias": false,
13
+ "attention_dropout": 0.0,
14
+ "latent_dim": 1024,
15
+ "codebook_dim": 512,
16
+ "codebook_size": 2048,
17
+ "decoder_dim": 1536,
18
+ "hidden_act": "silu",
19
+ "hidden_size": 512,
20
+ "intermediate_size": 1024,
21
+ "layer_scale_initial_scale": 0.01,
22
+ "max_position_embeddings": 8000,
23
+ "head_dim": 64,
24
+ "num_attention_heads": 16,
25
+ "num_hidden_layers": 8,
26
+ "num_key_value_heads": 16,
27
+ "num_quantizers": 16,
28
+ "num_semantic_quantizers": 1,
29
+ "rms_norm_eps": 1e-05,
30
+ "rope_theta": 10000,
31
+ "semantic_codebook_size": 4096,
32
+ "sliding_window": 72,
33
+ "upsample_rates": [
34
+ 8,
35
+ 5,
36
+ 4,
37
+ 3
38
+ ],
39
+ "upsampling_ratios": [
40
+ 2,
41
+ 2
42
+ ],
43
+ "vector_quantization_hidden_dimension": 512
44
+ },
45
+ "encoder_config": {
46
+ "_frame_rate": 12.5,
47
+ "attention_bias": false,
48
+ "attention_dropout": 0.0,
49
+ "audio_channels": 1,
50
+ "codebook_dim": 256,
51
+ "codebook_size": 2048,
52
+ "compress": 2,
53
+ "dilation_growth_rate": 2,
54
+ "dtype": "float32",
55
+ "head_dim": 64,
56
+ "hidden_act": "gelu",
57
+ "hidden_size": 512,
58
+ "initializer_range": 0.02,
59
+ "intermediate_size": 2048,
60
+ "kernel_size": 7,
61
+ "last_kernel_size": 3,
62
+ "layer_scale_initial_scale": 0.01,
63
+ "max_position_embeddings": 8000,
64
+ "norm_eps": 1e-05,
65
+ "normalize": false,
66
+ "num_attention_heads": 8,
67
+ "num_filters": 64,
68
+ "num_hidden_layers": 8,
69
+ "num_key_value_heads": 8,
70
+ "num_quantizers": 32,
71
+ "num_residual_layers": 1,
72
+ "num_semantic_quantizers": 1,
73
+ "pad_mode": "constant",
74
+ "residual_kernel_size": 3,
75
+ "rope_theta": 10000.0,
76
+ "sampling_rate": 24000,
77
+ "sliding_window": 250,
78
+ "transformers_version": "4.57.0.dev0",
79
+ "trim_right_ratio": 1.0,
80
+ "upsample_groups": 512,
81
+ "upsampling_ratios": [
82
+ 8,
83
+ 6,
84
+ 5,
85
+ 4
86
+ ],
87
+ "use_cache": false,
88
+ "use_causal_conv": true,
89
+ "use_conv_shortcut": false,
90
+ "use_streaming": false,
91
+ "vector_quantization_hidden_dimension": 256
92
+ },
93
+ "transformers_version": "4.57.3"
94
+ }
speech_tokenizer/configuration.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"framework": "pytorch", "task": "feature-extraction", "allow_remote": true}
speech_tokenizer/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:836b7b357f5ea43e889936a3709af68dfe3751881acefe4ecf0dbd30ba571258
3
+ size 682293092
speech_tokenizer/preprocessor_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "chunk_length_s": null,
3
+ "feature_extractor_type": "EncodecFeatureExtractor",
4
+ "feature_size": 1,
5
+ "overlap": null,
6
+ "padding_side": "right",
7
+ "padding_value": 0.0,
8
+ "return_attention_mask": true,
9
+ "sampling_rate": 24000
10
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:09267689b8362020b9763b65dd5be7e086b31e28d72e02837a9e781de9a91bc7
3
+ size 11423986
tokenizer_config.json ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_bos_token": false,
3
+ "add_prefix_space": false,
4
+ "added_tokens_decoder": {
5
+ "151643": {
6
+ "content": "<|endoftext|>",
7
+ "lstrip": false,
8
+ "normalized": false,
9
+ "rstrip": false,
10
+ "single_word": false,
11
+ "special": true
12
+ },
13
+ "151644": {
14
+ "content": "<|im_start|>",
15
+ "lstrip": false,
16
+ "normalized": false,
17
+ "rstrip": false,
18
+ "single_word": false,
19
+ "special": true
20
+ },
21
+ "151645": {
22
+ "content": "<|im_end|>",
23
+ "lstrip": false,
24
+ "normalized": false,
25
+ "rstrip": false,
26
+ "single_word": false,
27
+ "special": true
28
+ },
29
+ "151646": {
30
+ "content": "<|object_ref_start|>",
31
+ "lstrip": false,
32
+ "normalized": false,
33
+ "rstrip": false,
34
+ "single_word": false,
35
+ "special": true
36
+ },
37
+ "151647": {
38
+ "content": "<|object_ref_end|>",
39
+ "lstrip": false,
40
+ "normalized": false,
41
+ "rstrip": false,
42
+ "single_word": false,
43
+ "special": true
44
+ },
45
+ "151648": {
46
+ "content": "<|box_start|>",
47
+ "lstrip": false,
48
+ "normalized": false,
49
+ "rstrip": false,
50
+ "single_word": false,
51
+ "special": true
52
+ },
53
+ "151649": {
54
+ "content": "<|box_end|>",
55
+ "lstrip": false,
56
+ "normalized": false,
57
+ "rstrip": false,
58
+ "single_word": false,
59
+ "special": true
60
+ },
61
+ "151650": {
62
+ "content": "<|quad_start|>",
63
+ "lstrip": false,
64
+ "normalized": false,
65
+ "rstrip": false,
66
+ "single_word": false,
67
+ "special": true
68
+ },
69
+ "151651": {
70
+ "content": "<|quad_end|>",
71
+ "lstrip": false,
72
+ "normalized": false,
73
+ "rstrip": false,
74
+ "single_word": false,
75
+ "special": true
76
+ },
77
+ "151652": {
78
+ "content": "<|vision_start|>",
79
+ "lstrip": false,
80
+ "normalized": false,
81
+ "rstrip": false,
82
+ "single_word": false,
83
+ "special": true
84
+ },
85
+ "151653": {
86
+ "content": "<|vision_end|>",
87
+ "lstrip": false,
88
+ "normalized": false,
89
+ "rstrip": false,
90
+ "single_word": false,
91
+ "special": true
92
+ },
93
+ "151654": {
94
+ "content": "<|vision_pad|>",
95
+ "lstrip": false,
96
+ "normalized": false,
97
+ "rstrip": false,
98
+ "single_word": false,
99
+ "special": true
100
+ },
101
+ "151655": {
102
+ "content": "<|image_pad|>",
103
+ "lstrip": false,
104
+ "normalized": false,
105
+ "rstrip": false,
106
+ "single_word": false,
107
+ "special": true
108
+ },
109
+ "151656": {
110
+ "content": "<|video_pad|>",
111
+ "lstrip": false,
112
+ "normalized": false,
113
+ "rstrip": false,
114
+ "single_word": false,
115
+ "special": true
116
+ },
117
+ "151657": {
118
+ "content": "<tool_call>",
119
+ "lstrip": false,
120
+ "normalized": false,
121
+ "rstrip": false,
122
+ "single_word": false,
123
+ "special": false
124
+ },
125
+ "151658": {
126
+ "content": "</tool_call>",
127
+ "lstrip": false,
128
+ "normalized": false,
129
+ "rstrip": false,
130
+ "single_word": false,
131
+ "special": false
132
+ },
133
+ "151659": {
134
+ "content": "<|fim_prefix|>",
135
+ "lstrip": false,
136
+ "normalized": false,
137
+ "rstrip": false,
138
+ "single_word": false,
139
+ "special": false
140
+ },
141
+ "151660": {
142
+ "content": "<|fim_middle|>",
143
+ "lstrip": false,
144
+ "normalized": false,
145
+ "rstrip": false,
146
+ "single_word": false,
147
+ "special": false
148
+ },
149
+ "151661": {
150
+ "content": "<|fim_suffix|>",
151
+ "lstrip": false,
152
+ "normalized": false,
153
+ "rstrip": false,
154
+ "single_word": false,
155
+ "special": false
156
+ },
157
+ "151662": {
158
+ "content": "<|fim_pad|>",
159
+ "lstrip": false,
160
+ "normalized": false,
161
+ "rstrip": false,
162
+ "single_word": false,
163
+ "special": false
164
+ },
165
+ "151663": {
166
+ "content": "<|repo_name|>",
167
+ "lstrip": false,
168
+ "normalized": false,
169
+ "rstrip": false,
170
+ "single_word": false,
171
+ "special": false
172
+ },
173
+ "151664": {
174
+ "content": "<|file_sep|>",
175
+ "lstrip": false,
176
+ "normalized": false,
177
+ "rstrip": false,
178
+ "single_word": false,
179
+ "special": false
180
+ },
181
+ "151665": {
182
+ "content": "<tool_response>",
183
+ "lstrip": false,
184
+ "normalized": false,
185
+ "rstrip": false,
186
+ "single_word": false,
187
+ "special": false
188
+ },
189
+ "151666": {
190
+ "content": "</tool_response>",
191
+ "lstrip": false,
192
+ "normalized": false,
193
+ "rstrip": false,
194
+ "single_word": false,
195
+ "special": false
196
+ },
197
+ "151667": {
198
+ "content": "<think>",
199
+ "lstrip": false,
200
+ "normalized": false,
201
+ "rstrip": false,
202
+ "single_word": false,
203
+ "special": false
204
+ },
205
+ "151668": {
206
+ "content": "</think>",
207
+ "lstrip": false,
208
+ "normalized": false,
209
+ "rstrip": false,
210
+ "single_word": false,
211
+ "special": false
212
+ },
213
+ "151669": {
214
+ "content": "<|audio_start|>",
215
+ "lstrip": false,
216
+ "normalized": false,
217
+ "rstrip": false,
218
+ "single_word": false,
219
+ "special": true
220
+ },
221
+ "151670": {
222
+ "content": "<|audio_end|>",
223
+ "lstrip": false,
224
+ "normalized": false,
225
+ "rstrip": false,
226
+ "single_word": false,
227
+ "special": true
228
+ },
229
+ "151671": {
230
+ "content": "<tts_pad>",
231
+ "lstrip": false,
232
+ "normalized": false,
233
+ "rstrip": false,
234
+ "single_word": false,
235
+ "special": true
236
+ },
237
+ "151672": {
238
+ "content": "<tts_text_bos>",
239
+ "lstrip": false,
240
+ "normalized": false,
241
+ "rstrip": false,
242
+ "single_word": false,
243
+ "special": true
244
+ },
245
+ "151673": {
246
+ "content": "<tts_text_eod>",
247
+ "lstrip": false,
248
+ "normalized": false,
249
+ "rstrip": false,
250
+ "single_word": false,
251
+ "special": true
252
+ },
253
+ "151674": {
254
+ "content": "<tts_text_bos_single>",
255
+ "lstrip": false,
256
+ "normalized": false,
257
+ "rstrip": false,
258
+ "single_word": false,
259
+ "special": true
260
+ },
261
+ "151675": {
262
+ "content": "<|audio_pad|>",
263
+ "lstrip": false,
264
+ "normalized": false,
265
+ "rstrip": false,
266
+ "single_word": false,
267
+ "special": true
268
+ }
269
+ },
270
+ "additional_special_tokens": [
271
+ "<|im_start|>",
272
+ "<|im_end|>",
273
+ "<|object_ref_start|>",
274
+ "<|object_ref_end|>",
275
+ "<|box_start|>",
276
+ "<|box_end|>",
277
+ "<|quad_start|>",
278
+ "<|quad_end|>",
279
+ "<|vision_start|>",
280
+ "<|vision_end|>",
281
+ "<|vision_pad|>",
282
+ "<|image_pad|>",
283
+ "<|video_pad|>",
284
+ "<|audio_start|>",
285
+ "<|audio_end|>",
286
+ "<tts_pad>",
287
+ "<tts_text_bos>",
288
+ "<tts_text_bos_single>",
289
+ "<|audio_pad|>"
290
+ ],
291
+ "audio_bos_token": "<|audio_start|>",
292
+ "audio_eos_token": "<|audio_end|>",
293
+ "audio_token": "<|audio_pad|>",
294
+ "bos_token": null,
295
+ "clean_up_tokenization_spaces": false,
296
+ "eos_token": "<|im_end|>",
297
+ "errors": "replace",
298
+ "extra_special_tokens": {
299
+ "audio_bos_token": "<|audio_start|>",
300
+ "audio_eos_token": "<|audio_end|>",
301
+ "audio_token": "<|audio_pad|>",
302
+ "image_token": "<|image_pad|>",
303
+ "video_token": "<|video_pad|>",
304
+ "vision_bos_token": "<|vision_start|>",
305
+ "vision_eos_token": "<|vision_end|>"
306
+ },
307
+ "fix_mistral_regex": true,
308
+ "image_token": "<|image_pad|>",
309
+ "model_max_length": 131072,
310
+ "pad_token": "<|endoftext|>",
311
+ "processor_class": "Qwen3TTSProcessor",
312
+ "split_special_tokens": false,
313
+ "tokenizer_class": "Qwen2Tokenizer",
314
+ "unk_token": null,
315
+ "video_token": "<|video_pad|>",
316
+ "vision_bos_token": "<|vision_start|>",
317
+ "vision_eos_token": "<|vision_end|>"
318
+ }
vocab.json ADDED
The diff for this file is too large to render. See raw diff
 
vocence_config.yaml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ runtime:
3
+ adapter: "qwen3_tts_repo_snapshot"
4
+ device_preference: "cuda"
5
+ dtype: "bfloat16"
6
+ default_language: "English"
7
+ use_flash_attention_2: false
8
+
9
+ generation:
10
+ sample_rate: 24000
11
+ max_seconds: 30
12
+
13
+ limits:
14
+ max_text_chars: 2000
15
+ max_instruction_chars: 600
16
+ default_language: "English"