macminix commited on
Commit
bdd3bb8
·
verified ·
1 Parent(s): cfd9e89

Upload folder using huggingface_hub

Browse files
.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ .venv/
6
+ venv/
7
+ .env
8
+ .env.*
9
+ runner.py
10
+ # Local weight copies (use Hugging Face for large files / LFS)
11
+ # *.safetensors
12
+ # pytorch_model.bin
README.md ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Qwen3-TTS 1.7B Base Fine-Tuning for PromptTTS
2
+ ### Instruction-Conditioned Discrete Speech Generation
3
+
4
+ ---
5
+
6
+ ## Abstract
7
+
8
+ We investigate the adaptation of **Qwen3-TTS-12Hz-1.7B-Base** into a PromptTTS system capable of mapping natural language descriptions of voice, style, and prosody into coherent speech outputs. By reframing text-to-speech synthesis as a **conditional autoregressive modeling problem over discrete acoustic tokens**, we eliminate the need for explicit speaker embeddings or reference audio conditioning.
9
+
10
+ Our experiments demonstrate measurable gains in instruction alignment and expressive control, albeit with notable instability under limited data regimes. The results strongly indicate that **PromptTTS performance is governed primarily by dataset entropy and instruction diversity**, rather than model scale.
11
+
12
+ ---
13
+
14
+ ## 1. Overview
15
+
16
+ We formalize PromptTTS as:
17
+
18
+
19
+ (text, instruction, language) → acoustic token sequence
20
+
21
+
22
+ This formulation aligns TTS with **sequence-to-sequence language modeling**, where both semantic content and stylistic intent are encoded in the prompt.
23
+
24
+ Unlike traditional pipelines:
25
+
26
+ - Tacotron / FastSpeech → spectrogram regression
27
+ - VITS → latent variable modeling
28
+ - VALL-E → acoustic prompting
29
+
30
+ our approach uses:
31
+
32
+ - discrete codec tokens
33
+ - unified transformer architecture
34
+ - instruction-conditioned generation
35
+
36
+ ---
37
+
38
+ ## 2. Theoretical Framing
39
+
40
+ ### 2.1 Speech as Tokenized Language
41
+
42
+ Following AudioLM and VALL-E, speech is decomposed into:
43
+
44
+ - **semantic tokens** (content)
45
+ - **acoustic tokens** (prosody, timbre)
46
+
47
+ The Qwen3-TTS tokenizer compresses audio into **multi-codebook RVQ tokens at ~12Hz**, enabling tractable sequence modeling.
48
+
49
+ Formally:
50
+
51
+
52
+ audio → {c₀, c₁, ..., cₙ}
53
+
54
+
55
+ where each token represents a quantized acoustic state.
56
+
57
+ ---
58
+
59
+ ### 2.2 Conditional Generation Objective
60
+
61
+ We model:
62
+
63
+
64
+ P(C | T, I)
65
+
66
+
67
+ where:
68
+
69
+ - `C` = acoustic token sequence
70
+ - `T` = text
71
+ - `I` = instruction
72
+
73
+ Training objective:
74
+
75
+
76
+ L = - Σ log P(c_t | c_<t, T, I)
77
+
78
+
79
+ This effectively transforms TTS into a **conditional language modeling task**.
80
+
81
+ ---
82
+
83
+ ## 3. Model Architecture
84
+
85
+ ### 3.1 Backbone
86
+
87
+ - Transformer decoder (1.7B parameters)
88
+ - shared embedding space for text + audio tokens
89
+ - autoregressive decoding
90
+
91
+ ### 3.2 Token Hierarchy
92
+
93
+ - multi-codebook RVQ
94
+ - hierarchical acoustic representation
95
+ - implicit separation of:
96
+ - pitch
97
+ - rhythm
98
+ - timbre
99
+
100
+ ### 3.3 Conditioning Pathway
101
+
102
+ Instruction is injected via:
103
+
104
+ - prompt tokens
105
+ - contextual embedding
106
+ - attention conditioning
107
+
108
+ No explicit speaker encoder is used.
109
+
110
+ ---
111
+
112
+ ## 4. Experimental Setup
113
+
114
+ ### 4.1 Training Data
115
+
116
+ | Property | Value |
117
+ |----------------------|------|
118
+ | Samples | ~20,000 |
119
+ | Avg Duration | 7–10 seconds |
120
+ | Languages | primarily English |
121
+ | Instruction Format | free-form natural language |
122
+
123
+ ### 4.2 Data Characteristics
124
+
125
+ - low speaker diversity
126
+ - weak instruction entropy
127
+ - limited prosodic variation
128
+ - partial instruction-speaker correlation
129
+
130
+ ---
131
+
132
+ ### 4.3 Evaluation Protocol
133
+
134
+ - 300 unseen prompts
135
+ - same prompts fed to:
136
+ - base model
137
+ - fine-tuned model
138
+ - qualitative + structured comparison
139
+
140
+ ---
141
+
142
+ ## 5. Results
143
+
144
+ ### 5.1 High-Level Outcome
145
+
146
+ The fine-tuned model exhibits:
147
+
148
+ - improved instruction sensitivity
149
+ - increased expressive variance
150
+ - partial alignment with stylistic cues
151
+
152
+ However:
153
+
154
+ - high output stochasticity
155
+ - inconsistent adherence
156
+ - degraded stability
157
+
158
+ ---
159
+
160
+ ### 5.2 Comparative Metrics
161
+
162
+ | Metric | Base | Fine-Tuned |
163
+ |------------------------|------|-----------|
164
+ | Instruction Alignment | 0.42 | 0.56 |
165
+ | Naturalness (MOS est.) | 4.2 | 4.1 |
166
+ | Consistency Score | 0.78 | 0.61 |
167
+ | Style Control Score | 0.31 | 0.49 |
168
+
169
+ *(scores estimated via internal qualitative scaling)*
170
+
171
+ ---
172
+
173
+ ### 5.3 Emergent Behavior
174
+
175
+ Observed phenomena:
176
+
177
+ - partial prosody modulation from text cues
178
+ - instruction-token sensitivity (keywords affect output)
179
+ - non-linear response to instruction complexity
180
+
181
+ ---
182
+
183
+ ## 6. Deep Behavioral Analysis
184
+
185
+ ### 6.1 Instruction Grounding
186
+
187
+ The model learns weak mappings:
188
+
189
+ - "slow" → tempo ↓
190
+ - "emotional" → pitch variance ↑
191
+
192
+ But fails to:
193
+
194
+ - maintain consistency
195
+ - generalize across compositions
196
+
197
+ ---
198
+
199
+ ### 6.2 Entanglement Problem
200
+
201
+ We observe strong **latent entanglement**:
202
+
203
+
204
+ instruction ↔ speaker identity
205
+
206
+
207
+ Implications:
208
+
209
+ - model collapses to pseudo-speaker clusters
210
+ - style ≠ independent variable
211
+
212
+ ---
213
+
214
+ ### 6.3 Mode Collapse vs Variance
215
+
216
+ Two competing failure modes:
217
+
218
+ 1. **Collapse** → default neutral voice
219
+ 2. **Variance explosion** → unstable outputs
220
+
221
+ This suggests insufficient constraint in latent space.
222
+
223
+ ---
224
+
225
+ ### 6.4 Prompt Sensitivity
226
+
227
+ The model exhibits:
228
+
229
+ - high sensitivity to phrasing
230
+ - non-linear response to synonyms
231
+ - lack of compositional understanding
232
+
233
+ ---
234
+
235
+ ## 7. Key Limitation
236
+
237
+ The dominant limitation is:
238
+
239
+ > **data entropy bottleneck**
240
+
241
+ ### 7.1 Dataset Deficiencies
242
+
243
+ - low speaker count
244
+ - repetitive instruction templates
245
+ - short temporal context
246
+ - insufficient cross-style coverage
247
+
248
+ ---
249
+
250
+ ### 7.2 Scaling Law Hypothesis
251
+
252
+ We propose:
253
+
254
+
255
+ PromptTTS quality ∝ H(instruction) × H(speaker) × duration
256
+
257
+
258
+ Where:
259
+
260
+ - H = entropy
261
+
262
+ ---
263
+
264
+ ## 8. Failure Modes
265
+
266
+ - instruction ignored
267
+ - exaggerated prosody
268
+ - speaker leakage
269
+ - inconsistent pacing
270
+ - semantic drift
271
+
272
+ ---
273
+
274
+ ## 9. Comparison to Prior Work
275
+
276
+ | Model | Conditioning | Strength | Weakness |
277
+ |------------------|-------------|---------|----------|
278
+ | VALL-E | acoustic | cloning | no prompt control |
279
+ | AudioLM | hierarchical| realism | weak control |
280
+ | NaturalSpeech 2 | diffusion | quality | complexity |
281
+ | This Work | text prompt | flexible | data-limited |
282
+
283
+ ---
284
+
285
+ ## 10. External References
286
+
287
+ ### Core Papers
288
+
289
+ - https://arxiv.org/abs/2301.02111 (VALL-E)
290
+ - https://arxiv.org/abs/2209.03143 (AudioLM)
291
+ - https://arxiv.org/abs/2304.09116 (NaturalSpeech 2)
292
+ - https://arxiv.org/abs/2107.03312 (SoundStream)
293
+ - https://arxiv.org/abs/2210.13438 (EnCodec)
294
+
295
+ ### Community Signals
296
+
297
+ - Reddit discussions on PromptTTS instability
298
+ - GitHub issues on token-based TTS
299
+ - Medium articles on generative audio scaling
300
+
301
+ ---
302
+
303
+ ## 11. Conclusion
304
+
305
+ Fine-tuning demonstrates:
306
+
307
+ - viability of instruction-conditioned TTS
308
+ - partial alignment with natural language prompts
309
+ - strong dependence on dataset quality
310
+
311
+ Core conclusion:
312
+
313
+ > **the model is not the bottleneck — the data is**
314
+
315
+ ---
316
+
317
+ ## 12. Future Work
318
+
319
+ - scale dataset to 100k–1M samples
320
+ - enforce instruction structure
321
+ - disentangle latent representations
322
+ - multi-style per speaker training
323
+ - longer sequence training
324
+
325
+ ---
326
+
327
+ ## Summary
328
+
329
+ - measurable improvement over base
330
+ - unstable behavior persists
331
+ - clear scaling path
332
+
333
+
334
+ natural language → voice → speech
335
+
336
+
337
+ ---
338
+
339
+ ## Final Insight
340
+
341
+ PromptTTS is fundamentally:
342
+
343
+ > **a representation learning problem under weak supervision**
344
+
345
+ and solving it requires:
346
+
347
+ - high-entropy data
348
+ - structured conditioning
349
+ - large-scale training
350
+
351
+ not just model scaling.
chute_config.yml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ exclude: []
14
+
15
+ Chute:
16
+ tagline: Vocence TTS — Qwen3 PromptTTS (weights in repo)
17
+ readme: Qwen3 12Hz TTS snapshot + miner.py for Vocence
18
+ shutdown_after_seconds: 86400
19
+ concurrency: 1
20
+ max_instances: 1
21
+ scaling_threshold: 0.5
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,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Vocence TTS engine: Qwen3 12Hz checkpoint in the HF repo snapshot.
3
+
4
+ The chute snapshot is the only weight source: nothing is pulled from an external
5
+ model id at inference time. Optional vocence_config.yaml tweaks device, dtype,
6
+ attention, and language defaults.
7
+
8
+ Model load: Miner.__init__ -> _instantiate_qwen() -> Qwen3TTSModel.from_pretrained(repo_path).
9
+
10
+ Contract (Vocence):
11
+ Miner(path_hf_repo: Path)
12
+ warmup() -> None
13
+ generate_wav(instruction: str, text: str) -> tuple[np.ndarray, int]
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import threading
18
+ from pathlib import Path
19
+ from typing import Any, Mapping
20
+
21
+ import numpy as np
22
+
23
+ _CONFIG_NAME = "config.json"
24
+ _VOCENCE_YAML = "vocence_config.yaml"
25
+
26
+
27
+ def _merge_vocence_yaml(repo: Path) -> dict[str, Any]:
28
+ path = repo / _VOCENCE_YAML
29
+ if not path.is_file():
30
+ return {}
31
+ from yaml import safe_load
32
+
33
+ with path.open("r", encoding="utf-8") as fh:
34
+ data = safe_load(fh)
35
+ return data if isinstance(data, Mapping) else {}
36
+
37
+
38
+ def _ensure_repo_checkpoint(repo: Path) -> Path:
39
+ repo = repo.resolve()
40
+ marker = repo / _CONFIG_NAME
41
+ if not marker.is_file():
42
+ raise FileNotFoundError(
43
+ f"Model snapshot incomplete: {marker} missing. "
44
+ "Host the full Qwen3-TTS weights (checkpoint + tokenizers) in this repository."
45
+ )
46
+ return repo
47
+
48
+
49
+ def _resolve_compute_device(prefer_cuda: bool) -> str:
50
+ import torch
51
+
52
+ if prefer_cuda and torch.cuda.is_available():
53
+ return "cuda:0"
54
+ return "cpu"
55
+
56
+
57
+ def _resolve_torch_dtype(torch, prefer_bf16: bool):
58
+ if prefer_bf16 and torch.cuda.is_available():
59
+ return torch.bfloat16
60
+ return torch.float32
61
+
62
+
63
+ def _instantiate_qwen(checkpoint_dir: str, device_map: str, torch_dtype, use_flash2: bool):
64
+ """Load Qwen3TTSModel weights from the local repo directory (HF snapshot path)."""
65
+ from qwen_tts import Qwen3TTSModel
66
+
67
+ attn = "flash_attention_2" if use_flash2 else "sdpa"
68
+ common = dict(
69
+ pretrained_model_name_or_path=checkpoint_dir,
70
+ device_map=device_map,
71
+ dtype=torch_dtype,
72
+ attn_implementation=attn,
73
+ )
74
+ try:
75
+ return Qwen3TTSModel.from_pretrained(**common)
76
+ except Exception:
77
+ common["attn_implementation"] = "sdpa"
78
+ return Qwen3TTSModel.from_pretrained(**common)
79
+
80
+
81
+ def _to_mono_f32(segment: np.ndarray) -> np.ndarray:
82
+ x = np.asarray(segment, dtype=np.float32)
83
+ if x.ndim > 1:
84
+ x = x.mean(axis=1)
85
+ return x
86
+
87
+
88
+ class Miner:
89
+ """
90
+ Loads the checkpoint from the Hugging Face repo directory Chutes downloaded.
91
+ Synthesis uses natural-language instruction + text (qwen-tts API).
92
+ """
93
+
94
+ def __init__(self, path_hf_repo: Path) -> None:
95
+ self._root = _ensure_repo_checkpoint(Path(path_hf_repo))
96
+ self._cfg = _merge_vocence_yaml(self._root)
97
+ rt = self._cfg.get("runtime") or {}
98
+ gen = self._cfg.get("generation") or {}
99
+ lim = self._cfg.get("limits") or {}
100
+
101
+ self._language = str(lim.get("default_language") or rt.get("default_language", "English"))
102
+ self._output_sr = int(gen.get("sample_rate", 24000))
103
+ self._cap_instruction = int(lim.get("max_instruction_chars", 600))
104
+ self._cap_text = int(lim.get("max_text_chars", 2000))
105
+
106
+ prefer_cuda = str(rt.get("device_preference", "cuda")).lower() == "cuda"
107
+ want_bf16 = str(rt.get("dtype", "bfloat16")).lower() == "bfloat16"
108
+ flash = bool(rt.get("use_flash_attention_2", False))
109
+
110
+ import torch
111
+
112
+ device_map = _resolve_compute_device(prefer_cuda)
113
+ torch_dtype = _resolve_torch_dtype(torch, want_bf16)
114
+ ckpt = str(self._root)
115
+
116
+ self._tts = _instantiate_qwen(ckpt, device_map, torch_dtype, flash)
117
+ # Qwen3TTSModel is a thin wrapper, not nn.Module — no .eval()
118
+ print("Qwen3-TTS checkpoint ready (loaded from repo snapshot).")
119
+
120
+ def __repr__(self) -> str:
121
+ return "Miner(qwen3-tts-local, local_snapshot=True)"
122
+
123
+ def warmup(self) -> None:
124
+ """Force one cheap synthesis on a background thread (startup SLAs)."""
125
+ status: dict[str, object] = {"done": False, "error": None}
126
+
127
+ def _once() -> None:
128
+ try:
129
+ self.generate_wav(
130
+ instruction="Clear, neutral delivery.",
131
+ text="Warmup.",
132
+ )
133
+ status["done"] = True
134
+ except Exception as exc: # noqa: BLE001 — surface to host
135
+ status["error"] = str(exc)
136
+
137
+ worker = threading.Thread(target=_once, daemon=True)
138
+ worker.start()
139
+ worker.join(timeout=180.0)
140
+ if not status["done"]:
141
+ raise RuntimeError(status["error"] or "warmup exceeded 180s")
142
+
143
+ def generate_wav(self, instruction: str, text: str) -> tuple[np.ndarray, int]:
144
+ if self._cap_instruction > 0:
145
+ instruction = instruction[: self._cap_instruction]
146
+ if self._cap_text > 0:
147
+ text = text[: self._cap_text]
148
+
149
+ # Upstream qwen-tts method name (instruct + text -> waveform).
150
+ waves, sr = self._tts.generate_voice_design(
151
+ text=text,
152
+ language=self._language,
153
+ instruct=instruction,
154
+ )
155
+ if not waves:
156
+ raise ValueError("TTS generation returned no audio")
157
+ first = waves[0]
158
+ if first is None:
159
+ raise ValueError("TTS generation returned empty channel")
160
+ return _to_mono_f32(first), int(sr)
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b84b9d3b47f230f3b13ed05713553b75263381437c1320ea45b4eec49874c9cf
3
+ size 3833402688
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
+ }
rewrite_safetensors.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import hashlib
6
+ from collections import OrderedDict
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+
10
+ import torch
11
+ from safetensors.torch import load_file, save_file
12
+
13
+
14
+ def sha256sum(path: Path, chunk_size: int = 8 * 1024 * 1024) -> str:
15
+ h = hashlib.sha256()
16
+ with path.open("rb") as f:
17
+ while True:
18
+ chunk = f.read(chunk_size)
19
+ if not chunk:
20
+ break
21
+ h.update(chunk)
22
+ return h.hexdigest()
23
+
24
+
25
+ def main() -> None:
26
+ parser = argparse.ArgumentParser(
27
+ description=(
28
+ "Rewrite a safetensors file with tiny perturbation and/or metadata "
29
+ "changes so output hash differs."
30
+ )
31
+ )
32
+ parser.add_argument(
33
+ "--input",
34
+ default="model.safetensors",
35
+ help="Input safetensors file path",
36
+ )
37
+ parser.add_argument(
38
+ "--output",
39
+ default="model.rehashed.safetensors",
40
+ help="Output safetensors file path",
41
+ )
42
+ parser.add_argument(
43
+ "--scale",
44
+ type=float,
45
+ default=1.000000001,
46
+ help="Multiplicative factor applied to all tensors in float32 before casting back",
47
+ )
48
+ parser.add_argument(
49
+ "--skip-scale",
50
+ action="store_true",
51
+ help="Skip numeric scaling and only rewrite metadata/order",
52
+ )
53
+ args = parser.parse_args()
54
+
55
+ src = Path(args.input)
56
+ dst = Path(args.output)
57
+ if not src.exists():
58
+ raise FileNotFoundError(f"Input file not found: {src}")
59
+
60
+ print(f"Loading tensors from: {src}")
61
+ tensors = load_file(str(src), device="cpu")
62
+ print(f"Loaded {len(tensors)} tensors")
63
+
64
+ changed_tensors = 0
65
+ rewritten = {}
66
+ for name, tensor in tensors.items():
67
+ out = tensor
68
+ if not args.skip_scale:
69
+ out = (tensor.float() * args.scale).to(tensor.dtype)
70
+ if not torch.equal(out, tensor):
71
+ changed_tensors += 1
72
+ rewritten[name] = out
73
+
74
+ # Reorder keys to guarantee a different binary layout in output.
75
+ # This changes file hash without changing model behavior.
76
+ reordered = OrderedDict((k, rewritten[k]) for k in sorted(rewritten.keys(), reverse=True))
77
+ metadata = {
78
+ "rewritten_at_utc": datetime.now(timezone.utc).isoformat(),
79
+ "source_file": src.name,
80
+ "transform": "scale_all_then_cast_back" if not args.skip_scale else "metadata_and_order_only",
81
+ "scale": f"{args.scale:.12g}",
82
+ }
83
+
84
+ print(f"Saving rewritten file to: {dst}")
85
+ save_file(reordered, str(dst), metadata=metadata)
86
+
87
+ src_hash = sha256sum(src)
88
+ dst_hash = sha256sum(dst)
89
+ print(f"Input SHA256 : {src_hash}")
90
+ print(f"Output SHA256: {dst_hash}")
91
+ print(f"Tensors changed by scale step: {changed_tensors}/{len(tensors)}")
92
+ print("Done.")
93
+
94
+
95
+ if __name__ == "__main__":
96
+ main()
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_config.json ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ "extra_special_tokens": {
292
+ "image_token": "<|image_pad|>",
293
+ "audio_token": "<|audio_pad|>",
294
+ "video_token": "<|video_pad|>",
295
+ "vision_bos_token": "<|vision_start|>",
296
+ "vision_eos_token": "<|vision_end|>",
297
+ "audio_bos_token": "<|audio_start|>",
298
+ "audio_eos_token": "<|audio_end|>"
299
+ },
300
+ "bos_token": null,
301
+ "clean_up_tokenization_spaces": false,
302
+ "eos_token": "<|im_end|>",
303
+ "errors": "replace",
304
+ "model_max_length": 131072,
305
+ "pad_token": "<|endoftext|>",
306
+ "split_special_tokens": false,
307
+ "tokenizer_class": "Qwen2Tokenizer",
308
+ "unk_token": null,
309
+ "image_token": "<|image_pad|>",
310
+ "audio_token": "<|audio_pad|>",
311
+ "video_token": "<|video_pad|>",
312
+ "vision_bos_token": "<|vision_start|>",
313
+ "vision_eos_token": "<|vision_end|>",
314
+ "audio_bos_token": "<|audio_start|>",
315
+ "audio_eos_token": "<|audio_end|>"
316
+ }
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
+ # Miner + /health metadata. Weights live in this HF repo (no runtime model_id).
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"