Instructions to use kruatech/studio-mlx with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use kruatech/studio-mlx with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] hf download kruatech/studio-mlx --local-dir studio-mlx
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
Upload folder using huggingface_hub
Browse files- README.md +17 -50
- qwen3-tts-12hz-1.7b-base/README.md +132 -0
- qwen3-tts-12hz-1.7b-customvoice/README.md +132 -0
- qwen3-tts-12hz-1.7b-voicedesign/README.md +132 -0
README.md
CHANGED
|
@@ -19,7 +19,7 @@ tags:
|
|
| 19 |
|
| 20 |
**Image and music models converted for native MLX inference on Apple silicon**
|
| 21 |
|
| 22 |
-
   [](
|
| 23 |
|
| 24 |
</div>
|
| 25 |
|
|
@@ -34,60 +34,31 @@ Pick one line. The image models need the shared encoder, the music model does no
|
|
| 34 |
```bash
|
| 35 |
pip install "huggingface_hub[hf_xet]"
|
| 36 |
|
| 37 |
-
# Z-Image-Turbo - 6.14 GiB
|
| 38 |
-
hf download kruatech/studio-mlx --local-dir bundles \
|
| 39 |
-
--include "shared/qwen3-4b-text-encoder-q4/*" "z-image-turbo-q4/*"
|
| 40 |
-
|
| 41 |
-
# FLUX.2 [klein] 4B - 4.79 GiB
|
| 42 |
-
hf download kruatech/studio-mlx --local-dir bundles \
|
| 43 |
-
--include "shared/qwen3-4b-text-encoder-q4/*" "flux2-klein-4b-q4/*"
|
| 44 |
-
|
| 45 |
-
# ACE-Step 1.5 Turbo - 9.38 GiB
|
| 46 |
-
hf download kruatech/studio-mlx --local-dir bundles --include "ace-step-1.5-turbo/*"
|
| 47 |
-
|
| 48 |
```
|
| 49 |
|
| 50 |
The `-q4` folders sit at the top level rather than inside the bf16 ones, so an include pattern fetches one precision without dragging in the other.
|
| 51 |
|
| 52 |
## What is inside
|
| 53 |
|
| 54 |
-
| folder | what it does
|
| 55 |
-
|----------------------------------------------------------------------|------------------------------------------
|
| 56 |
-
| [`
|
| 57 |
-
| [`
|
| 58 |
-
| [`
|
| 59 |
-
| [`z-image-turbo-q4`](z-image-turbo-q4) | Text to image, 6B, 8 steps | `4-bit` | 3.55 GiB | Apache-2.0 |
|
| 60 |
-
| [`flux2-klein-4b`](flux2-klein-4b) | Text to image and multi-reference editing, 4B, 4 steps | `bf16` | 7.39 GiB | Apache-2.0 |
|
| 61 |
-
| [`flux2-klein-4b-q4`](flux2-klein-4b-q4) | Text to image and multi-reference editing, 4B, 4 steps | `4-bit` | 2.20 GiB | Apache-2.0 |
|
| 62 |
-
| [`ace-step-1.5-turbo`](ace-step-1.5-turbo) | Text to music, 48 kHz stereo | `bf16` | 9.38 GiB | MIT |
|
| 63 |
|
| 64 |
## bf16 or 4-bit
|
| 65 |
|
| 66 |
**Use the 4-bit folders.** Quantization is MLX affine: 4 bits per weight with a bf16 scale and bias for every group of 64, about 4.5 bits per weight and 28-30% of the bf16 size. Normalizations, modulations and the encoder's embedding table stay in bf16, and matrix multiplication still runs in bf16 - the gain is memory and load time, not integer arithmetic.
|
| 67 |
|
| 68 |
-
|
|
| 69 |
-
|---------------------
|
| 70 |
-
| Z-Image DiT
|
| 71 |
-
| klein DiT
|
| 72 |
-
| shared
|
| 73 |
-
|
| 74 |
-
The encoder ratio is higher on purpose: its 151936 x 2560 embedding table stays in bf16, because quantizing it moved the encoder output by 3e-01 in testing.
|
| 75 |
-
|
| 76 |
-
What that buys, on one klein run at 1024 px with 4 steps:
|
| 77 |
-
|
| 78 |
-
| phase | bf16 | 4-bit |
|
| 79 |
-
|-----------------------|-------|-------|
|
| 80 |
-
| read the text encoder | 40 s | 22 s |
|
| 81 |
-
| read the transformer | 58 s | 19 s |
|
| 82 |
-
| 4 diffusion steps | 35 s | 32 s |
|
| 83 |
-
| total | 170 s | 73 s |
|
| 84 |
-
|
| 85 |
-
The steps themselves barely change: multiplication still happens in bf16, the kernel unpacks each group of 64 weights on the fly. The saving is disk reading, which is why it depends on your storage - these figures come from an external volume at about 0.2 GiB/s.
|
| 86 |
|
| 87 |
Output quality was indistinguishable: the same prompt and seed gave two clean images that differ the way two seeds differ. The bf16 folders exist as the accuracy reference a port can be checked against.
|
| 88 |
|
| 89 |
-
`ace-step-1.5-turbo` has no 4-bit variant. It is published as converted upstream, and its own card reports that its DiT has to run in float32 - bf16 already fails accuracy at `rel_max 1.45e-01`, so quantizing further is not on the table.
|
| 90 |
-
|
| 91 |
## Bundle layout
|
| 92 |
|
| 93 |
```
|
|
@@ -184,15 +155,11 @@ Stages run one at a time and release their weights, so peak memory is set by the
|
|
| 184 |
|
| 185 |
Derivatives of three upstream models under two licences. Each folder carries the licence of its upstream model.
|
| 186 |
|
| 187 |
-
| folder | upstream
|
| 188 |
-
|-----------------------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------|
|
| 189 |
-
| `
|
| 190 |
-
| `
|
| 191 |
-
| `
|
| 192 |
-
| `z-image-turbo-q4` | [Tongyi-MAI/Z-Image-Turbo](https://huggingface.co/Tongyi-MAI/Z-Image-Turbo) | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
| 193 |
-
| `flux2-klein-4b` | [black-forest-labs/FLUX.2-klein-4B](https://huggingface.co/black-forest-labs/FLUX.2-klein-4B) | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
| 194 |
-
| `flux2-klein-4b-q4` | [black-forest-labs/FLUX.2-klein-4B](https://huggingface.co/black-forest-labs/FLUX.2-klein-4B) | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
| 195 |
-
| `ace-step-1.5-turbo` | [ACE-Step/Ace-Step1.5](https://huggingface.co/ACE-Step/Ace-Step1.5) | [MIT](https://opensource.org/license/mit) |
|
| 196 |
|
| 197 |
The shared text encoder is redistributed from inside the two image repositories, both Apache-2.0. Conversion tooling and these cards: MIT.
|
| 198 |
|
|
|
|
| 19 |
|
| 20 |
**Image and music models converted for native MLX inference on Apple silicon**
|
| 21 |
|
| 22 |
+
   [](LICENSES.md)
|
| 23 |
|
| 24 |
</div>
|
| 25 |
|
|
|
|
| 34 |
```bash
|
| 35 |
pip install "huggingface_hub[hf_xet]"
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
```
|
| 38 |
|
| 39 |
The `-q4` folders sit at the top level rather than inside the bf16 ones, so an include pattern fetches one precision without dragging in the other.
|
| 40 |
|
| 41 |
## What is inside
|
| 42 |
|
| 43 |
+
| folder | what it does | precision | size | licence |
|
| 44 |
+
|----------------------------------------------------------------------|------------------------------------------|-----------|----------|------------|
|
| 45 |
+
| [`qwen3-tts-12hz-1.7b-base`](qwen3-tts-12hz-1.7b-base) | Voice cloning from a reference recording | `bf16` | 4.23 GiB | Apache-2.0 |
|
| 46 |
+
| [`qwen3-tts-12hz-1.7b-customvoice`](qwen3-tts-12hz-1.7b-customvoice) | Nine preset voices, ten languages | `bf16` | 4.21 GiB | Apache-2.0 |
|
| 47 |
+
| [`qwen3-tts-12hz-1.7b-voicedesign`](qwen3-tts-12hz-1.7b-voicedesign) | Describe a voice in words and get it | `bf16` | 4.21 GiB | Apache-2.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
## bf16 or 4-bit
|
| 50 |
|
| 51 |
**Use the 4-bit folders.** Quantization is MLX affine: 4 bits per weight with a bf16 scale and bias for every group of 64, about 4.5 bits per weight and 28-30% of the bf16 size. Normalizations, modulations and the encoder's embedding table stay in bf16, and matrix multiplication still runs in bf16 - the gain is memory and load time, not integer arithmetic.
|
| 52 |
|
| 53 |
+
| | bf16 | 4-bit |
|
| 54 |
+
|-----------------------------------|-----------|----------|
|
| 55 |
+
| Z-Image DiT | 11.46 GiB | 3.40 GiB |
|
| 56 |
+
| klein DiT | 7.22 GiB | 2.03 GiB |
|
| 57 |
+
| shared encoder | 7.51 GiB | 2.58 GiB |
|
| 58 |
+
| klein 512 px, 4 steps, wall clock | 170 s | 73 s |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
Output quality was indistinguishable: the same prompt and seed gave two clean images that differ the way two seeds differ. The bf16 folders exist as the accuracy reference a port can be checked against.
|
| 61 |
|
|
|
|
|
|
|
| 62 |
## Bundle layout
|
| 63 |
|
| 64 |
```
|
|
|
|
| 155 |
|
| 156 |
Derivatives of three upstream models under two licences. Each folder carries the licence of its upstream model.
|
| 157 |
|
| 158 |
+
| folder | upstream | licence |
|
| 159 |
+
|-----------------------------------|-----------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
|
| 160 |
+
| `qwen3-tts-12hz-1.7b-base` | [Qwen/Qwen3-TTS-12Hz-1.7B-Base](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-Base) | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
| 161 |
+
| `qwen3-tts-12hz-1.7b-customvoice` | [Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice) | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
| 162 |
+
| `qwen3-tts-12hz-1.7b-voicedesign` | [Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign) | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
|
| 164 |
The shared text encoder is redistributed from inside the two image repositories, both Apache-2.0. Conversion tooling and these cards: MIT.
|
| 165 |
|
qwen3-tts-12hz-1.7b-base/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
library_name: mlx
|
| 4 |
+
tags:
|
| 5 |
+
- mlx
|
| 6 |
+
- mlx-swift
|
| 7 |
+
- apple-silicon
|
| 8 |
+
base_model:
|
| 9 |
+
- Qwen/Qwen3-TTS-12Hz-1.7B-Base
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
<div align="center">
|
| 13 |
+
|
| 14 |
+
# Qwen3-TTS 12 Hz 1.7B Base for MLX, bf16
|
| 15 |
+
|
| 16 |
+
**Voice cloning from a reference recording**
|
| 17 |
+
|
| 18 |
+
  [](https://www.apache.org/licenses/LICENSE-2.0) [](https://huggingface.co/kruatech/studio-mlx)
|
| 19 |
+
|
| 20 |
+
</div>
|
| 21 |
+
|
| 22 |
+
Text to speech at 24 kHz. A talker generates 16 codec codes per frame at 12 Hz - the first sampled directly, the remaining 15 filled in by a code predictor - and a codec turns those codes into a waveform.
|
| 23 |
+
|
| 24 |
+
Converted from [Qwen/Qwen3-TTS-12Hz-1.7B-Base](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-Base) for native MLX inference on Apple silicon.
|
| 25 |
+
|
| 26 |
+
## Download
|
| 27 |
+
|
| 28 |
+
Self-contained. It does not use the shared Qwen3-4B encoder that the image models share; its own text stack and codec are inside this folder.
|
| 29 |
+
|
| 30 |
+
```bash
|
| 31 |
+
pip install "huggingface_hub[hf_xet]"
|
| 32 |
+
|
| 33 |
+
hf download kruatech/studio-mlx --local-dir bundles \
|
| 34 |
+
--include "qwen3-tts-12hz-1.7b-base/*"
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## Files
|
| 38 |
+
|
| 39 |
+
| component | class | precision | tensors | size |
|
| 40 |
+
|------------------|----------------------------------|-----------|---------|----------|
|
| 41 |
+
| model | Qwen3TTSForConditionalGeneration | keep | 480 | 3.59 GiB |
|
| 42 |
+
| speech_tokenizer | Qwen3TTSTokenizerV2Model | keep | 496 | 651 MiB |
|
| 43 |
+
|
| 44 |
+
Folder total: **4.23 GiB**. `manifest.json` carries SHA-256, byte sizes and tensor counts for every file.
|
| 45 |
+
|
| 46 |
+
## How this model works in MLX
|
| 47 |
+
|
| 48 |
+
- Adds an ECAPA-TDNN speaker encoder (38 convolutions) on top of the talker, which the other two variants do not have. Clone a voice by supplying a reference recording and its transcript.
|
| 49 |
+
- `model` holds the talker and the code predictor; `speech_tokenizer` holds the codec, whose 52 Conv1d and 6 ConvTranspose1d weights are permuted to MLX layout.
|
| 50 |
+
- No 4-bit variant yet: quantization needs an MLX implementation of these modules, which does not exist at the time of writing.
|
| 51 |
+
|
| 52 |
+
<details>
|
| 53 |
+
<summary><b>Tensor layout</b></summary>
|
| 54 |
+
|
| 55 |
+
MLX convolutions expect channels last, PyTorch expects channels first, so convolution weights are permuted during conversion. Everything else keeps its upstream shape.
|
| 56 |
+
|
| 57 |
+
| kind | PyTorch | MLX |
|
| 58 |
+
|-----------------------------|---------------------|---------------------|
|
| 59 |
+
| `Conv2d.weight` | `(out, in, kH, kW)` | `(out, kH, kW, in)` |
|
| 60 |
+
| `Linear`, norms, embeddings | `(out, in)` | unchanged |
|
| 61 |
+
|
| 62 |
+
No `weight_norm` and no 3-D convolutions appear in these models, so no folding was needed. Parameter names match the upstream checkpoints, so weights load without remapping.
|
| 63 |
+
|
| 64 |
+
</details>
|
| 65 |
+
|
| 66 |
+
<details>
|
| 67 |
+
<summary><b>Verification numbers</b></summary>
|
| 68 |
+
|
| 69 |
+
Every module was compared against the upstream reference on fixed inputs in float32. The metric is `rel_max = max|a-b| / max|a|`.
|
| 70 |
+
|
| 71 |
+
| module | rel_max | reference |
|
| 72 |
+
|-------------------------------------------------|-----------|---------------------------------|
|
| 73 |
+
| Qwen3 encoder, hidden_states[-2] | 2.7e-07 | transformers |
|
| 74 |
+
| Qwen3 encoder, layers 9/18/27 with padding mask | 6.0e-07 | transformers |
|
| 75 |
+
| Z-Image DiT | 4.2e-06 | diffusers |
|
| 76 |
+
| Flux2 DiT | 3.7e-07 | diffusers |
|
| 77 |
+
| VAE decoder | 1.3e-05 | diffusers |
|
| 78 |
+
| VAE encoder | 5.3e-06 | diffusers |
|
| 79 |
+
| VAE tiled decode | 5.1e-06 | diffusers tiled_decode |
|
| 80 |
+
| sigma schedule, static shift | 3.2e-08 | FlowMatchEulerDiscreteScheduler |
|
| 81 |
+
| sigma schedule, exponential dynamic shift | 7.7e-08 | FlowMatchEulerDiscreteScheduler |
|
| 82 |
+
| position ids, latent packing, patchify | bit-exact | pipeline helpers |
|
| 83 |
+
|
| 84 |
+
A Swift MLX implementation was then checked against the Python one:
|
| 85 |
+
|
| 86 |
+
| module | rel_max | note |
|
| 87 |
+
|------------------------------|-----------------|------------------------------------------------|
|
| 88 |
+
| tokenization, both pipelines | bit-exact | same ids |
|
| 89 |
+
| Qwen3 encoder, bf16 | 2.2e-04 | Z-Image branch |
|
| 90 |
+
| Qwen3 encoder, bf16 | 4.6e-03 | klein branch, 512 tokens with mask |
|
| 91 |
+
| Qwen3 encoder, 4-bit | 3.0e-04 | proves the quantized layout is rebuilt exactly |
|
| 92 |
+
| Z-Image DiT, float32 | 3.7e-07 | 8 layers |
|
| 93 |
+
| Flux2 DiT, float32 | 1.0e-06 | 2 double + 2 single blocks |
|
| 94 |
+
| VAE decode / tiled / encode | 1e-05 or better | both VAE classes |
|
| 95 |
+
| VAE BatchNorm statistics | 0 | exact |
|
| 96 |
+
|
| 97 |
+
The bf16 figures for a full-depth DiT are larger - 2e-02 for both models - and that is rounding order, not a defect: at float32 the same code agrees to 1e-06, and the deviation grows with depth from a bf16-level 1e-04 per block. Comparing two bf16 implementations below 1e-02 is not meaningful for a 30-block network.
|
| 98 |
+
|
| 99 |
+
</details>
|
| 100 |
+
|
| 101 |
+
<details>
|
| 102 |
+
<summary><b>Performance on an M1 Max</b></summary>
|
| 103 |
+
|
| 104 |
+
Mac Studio, Apple M1 Max, 10-core CPU, 24-core GPU, 32 GB, macOS 26.5. Release build, 4-bit weights, batch 1, warm page cache.
|
| 105 |
+
|
| 106 |
+
| run | per step | VAE decode |
|
| 107 |
+
|--------------------------------------|----------|------------|
|
| 108 |
+
| Z-Image, 512 px, 4 steps | 2.6 s | 1.5 s |
|
| 109 |
+
| klein, 512 px, 4 steps | 2.3 s | 0.9 s |
|
| 110 |
+
| klein, 1024 px, 4 steps | 8.0 s | 0.2 s |
|
| 111 |
+
| klein, 512 px + one 512 px reference | 4.1 s | 0.9 s |
|
| 112 |
+
|
| 113 |
+
Reading the weights dominates a cold run and depends entirely on the storage: on an external volume delivering about 0.2 GiB/s, the 4-bit encoder took 22-32 s and a 4-bit DiT 18-35 s, against 60-107 s for the same weights in bf16. On internal storage expect these to be several times shorter. Compute is unaffected: the numbers above are steady state.
|
| 114 |
+
|
| 115 |
+
Stages run one at a time and release their weights, so peak memory is set by the largest single component rather than their sum. The 4-bit DiT is 2.03 GiB for klein and 3.40 GiB for Z-Image; activations at 1024 px add to that, and no separate peak measurement was made.
|
| 116 |
+
|
| 117 |
+
</details>
|
| 118 |
+
|
| 119 |
+
<details>
|
| 120 |
+
<summary><b>Limitations</b></summary>
|
| 121 |
+
|
| 122 |
+
- Seeds are not compatible with the upstream pipelines, which use `torch.Generator`. The same prompt gives comparable images, never the same file.
|
| 123 |
+
- Both models are distilled: CFG is not applied, and step counts are low by design (8 for Z-Image, 4 for klein).
|
| 124 |
+
- Z-Image's Omni mode is not covered: it needs a SigLIP encoder that is not part of this bundle.
|
| 125 |
+
- Tiled VAE decode is available for high resolutions and gives a result that differs slightly from a single pass, exactly as it does in diffusers.
|
| 126 |
+
- Batches larger than one are not implemented.
|
| 127 |
+
|
| 128 |
+
</details>
|
| 129 |
+
|
| 130 |
+
## Licence
|
| 131 |
+
|
| 132 |
+
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0), the licence of the upstream model. Conversion tooling and this card: MIT. The upstream card states usage restrictions that redistribution does not repeal.
|
qwen3-tts-12hz-1.7b-customvoice/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
library_name: mlx
|
| 4 |
+
tags:
|
| 5 |
+
- mlx
|
| 6 |
+
- mlx-swift
|
| 7 |
+
- apple-silicon
|
| 8 |
+
base_model:
|
| 9 |
+
- Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
<div align="center">
|
| 13 |
+
|
| 14 |
+
# Qwen3-TTS 12 Hz 1.7B Customvoice for MLX, bf16
|
| 15 |
+
|
| 16 |
+
**Nine preset voices, ten languages**
|
| 17 |
+
|
| 18 |
+
  [](https://www.apache.org/licenses/LICENSE-2.0) [](https://huggingface.co/kruatech/studio-mlx)
|
| 19 |
+
|
| 20 |
+
</div>
|
| 21 |
+
|
| 22 |
+
Text to speech at 24 kHz. A talker generates 16 codec codes per frame at 12 Hz - the first sampled directly, the remaining 15 filled in by a code predictor - and a codec turns those codes into a waveform.
|
| 23 |
+
|
| 24 |
+
Converted from [Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice) for native MLX inference on Apple silicon.
|
| 25 |
+
|
| 26 |
+
## Download
|
| 27 |
+
|
| 28 |
+
Self-contained. It does not use the shared Qwen3-4B encoder that the image models share; its own text stack and codec are inside this folder.
|
| 29 |
+
|
| 30 |
+
```bash
|
| 31 |
+
pip install "huggingface_hub[hf_xet]"
|
| 32 |
+
|
| 33 |
+
hf download kruatech/studio-mlx --local-dir bundles \
|
| 34 |
+
--include "qwen3-tts-12hz-1.7b-customvoice/*"
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## Files
|
| 38 |
+
|
| 39 |
+
| component | class | precision | tensors | size |
|
| 40 |
+
|------------------|----------------------------------|-----------|---------|----------|
|
| 41 |
+
| model | Qwen3TTSForConditionalGeneration | keep | 404 | 3.57 GiB |
|
| 42 |
+
| speech_tokenizer | Qwen3TTSTokenizerV2Model | keep | 496 | 651 MiB |
|
| 43 |
+
|
| 44 |
+
Folder total: **4.21 GiB**. `manifest.json` carries SHA-256, byte sizes and tensor counts for every file.
|
| 45 |
+
|
| 46 |
+
## How this model works in MLX
|
| 47 |
+
|
| 48 |
+
- Pick a speaker by name and optionally steer delivery with an instruction in plain language. The speaker and language tables live in `config/model.json`.
|
| 49 |
+
- `model` holds the talker and the code predictor; `speech_tokenizer` holds the codec, whose 52 Conv1d and 6 ConvTranspose1d weights are permuted to MLX layout.
|
| 50 |
+
- No 4-bit variant yet: quantization needs an MLX implementation of these modules, which does not exist at the time of writing.
|
| 51 |
+
|
| 52 |
+
<details>
|
| 53 |
+
<summary><b>Tensor layout</b></summary>
|
| 54 |
+
|
| 55 |
+
MLX convolutions expect channels last, PyTorch expects channels first, so convolution weights are permuted during conversion. Everything else keeps its upstream shape.
|
| 56 |
+
|
| 57 |
+
| kind | PyTorch | MLX |
|
| 58 |
+
|-----------------------------|---------------------|---------------------|
|
| 59 |
+
| `Conv2d.weight` | `(out, in, kH, kW)` | `(out, kH, kW, in)` |
|
| 60 |
+
| `Linear`, norms, embeddings | `(out, in)` | unchanged |
|
| 61 |
+
|
| 62 |
+
No `weight_norm` and no 3-D convolutions appear in these models, so no folding was needed. Parameter names match the upstream checkpoints, so weights load without remapping.
|
| 63 |
+
|
| 64 |
+
</details>
|
| 65 |
+
|
| 66 |
+
<details>
|
| 67 |
+
<summary><b>Verification numbers</b></summary>
|
| 68 |
+
|
| 69 |
+
Every module was compared against the upstream reference on fixed inputs in float32. The metric is `rel_max = max|a-b| / max|a|`.
|
| 70 |
+
|
| 71 |
+
| module | rel_max | reference |
|
| 72 |
+
|-------------------------------------------------|-----------|---------------------------------|
|
| 73 |
+
| Qwen3 encoder, hidden_states[-2] | 2.7e-07 | transformers |
|
| 74 |
+
| Qwen3 encoder, layers 9/18/27 with padding mask | 6.0e-07 | transformers |
|
| 75 |
+
| Z-Image DiT | 4.2e-06 | diffusers |
|
| 76 |
+
| Flux2 DiT | 3.7e-07 | diffusers |
|
| 77 |
+
| VAE decoder | 1.3e-05 | diffusers |
|
| 78 |
+
| VAE encoder | 5.3e-06 | diffusers |
|
| 79 |
+
| VAE tiled decode | 5.1e-06 | diffusers tiled_decode |
|
| 80 |
+
| sigma schedule, static shift | 3.2e-08 | FlowMatchEulerDiscreteScheduler |
|
| 81 |
+
| sigma schedule, exponential dynamic shift | 7.7e-08 | FlowMatchEulerDiscreteScheduler |
|
| 82 |
+
| position ids, latent packing, patchify | bit-exact | pipeline helpers |
|
| 83 |
+
|
| 84 |
+
A Swift MLX implementation was then checked against the Python one:
|
| 85 |
+
|
| 86 |
+
| module | rel_max | note |
|
| 87 |
+
|------------------------------|-----------------|------------------------------------------------|
|
| 88 |
+
| tokenization, both pipelines | bit-exact | same ids |
|
| 89 |
+
| Qwen3 encoder, bf16 | 2.2e-04 | Z-Image branch |
|
| 90 |
+
| Qwen3 encoder, bf16 | 4.6e-03 | klein branch, 512 tokens with mask |
|
| 91 |
+
| Qwen3 encoder, 4-bit | 3.0e-04 | proves the quantized layout is rebuilt exactly |
|
| 92 |
+
| Z-Image DiT, float32 | 3.7e-07 | 8 layers |
|
| 93 |
+
| Flux2 DiT, float32 | 1.0e-06 | 2 double + 2 single blocks |
|
| 94 |
+
| VAE decode / tiled / encode | 1e-05 or better | both VAE classes |
|
| 95 |
+
| VAE BatchNorm statistics | 0 | exact |
|
| 96 |
+
|
| 97 |
+
The bf16 figures for a full-depth DiT are larger - 2e-02 for both models - and that is rounding order, not a defect: at float32 the same code agrees to 1e-06, and the deviation grows with depth from a bf16-level 1e-04 per block. Comparing two bf16 implementations below 1e-02 is not meaningful for a 30-block network.
|
| 98 |
+
|
| 99 |
+
</details>
|
| 100 |
+
|
| 101 |
+
<details>
|
| 102 |
+
<summary><b>Performance on an M1 Max</b></summary>
|
| 103 |
+
|
| 104 |
+
Mac Studio, Apple M1 Max, 10-core CPU, 24-core GPU, 32 GB, macOS 26.5. Release build, 4-bit weights, batch 1, warm page cache.
|
| 105 |
+
|
| 106 |
+
| run | per step | VAE decode |
|
| 107 |
+
|--------------------------------------|----------|------------|
|
| 108 |
+
| Z-Image, 512 px, 4 steps | 2.6 s | 1.5 s |
|
| 109 |
+
| klein, 512 px, 4 steps | 2.3 s | 0.9 s |
|
| 110 |
+
| klein, 1024 px, 4 steps | 8.0 s | 0.2 s |
|
| 111 |
+
| klein, 512 px + one 512 px reference | 4.1 s | 0.9 s |
|
| 112 |
+
|
| 113 |
+
Reading the weights dominates a cold run and depends entirely on the storage: on an external volume delivering about 0.2 GiB/s, the 4-bit encoder took 22-32 s and a 4-bit DiT 18-35 s, against 60-107 s for the same weights in bf16. On internal storage expect these to be several times shorter. Compute is unaffected: the numbers above are steady state.
|
| 114 |
+
|
| 115 |
+
Stages run one at a time and release their weights, so peak memory is set by the largest single component rather than their sum. The 4-bit DiT is 2.03 GiB for klein and 3.40 GiB for Z-Image; activations at 1024 px add to that, and no separate peak measurement was made.
|
| 116 |
+
|
| 117 |
+
</details>
|
| 118 |
+
|
| 119 |
+
<details>
|
| 120 |
+
<summary><b>Limitations</b></summary>
|
| 121 |
+
|
| 122 |
+
- Seeds are not compatible with the upstream pipelines, which use `torch.Generator`. The same prompt gives comparable images, never the same file.
|
| 123 |
+
- Both models are distilled: CFG is not applied, and step counts are low by design (8 for Z-Image, 4 for klein).
|
| 124 |
+
- Z-Image's Omni mode is not covered: it needs a SigLIP encoder that is not part of this bundle.
|
| 125 |
+
- Tiled VAE decode is available for high resolutions and gives a result that differs slightly from a single pass, exactly as it does in diffusers.
|
| 126 |
+
- Batches larger than one are not implemented.
|
| 127 |
+
|
| 128 |
+
</details>
|
| 129 |
+
|
| 130 |
+
## Licence
|
| 131 |
+
|
| 132 |
+
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0), the licence of the upstream model. Conversion tooling and this card: MIT. The upstream card states usage restrictions that redistribution does not repeal.
|
qwen3-tts-12hz-1.7b-voicedesign/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
library_name: mlx
|
| 4 |
+
tags:
|
| 5 |
+
- mlx
|
| 6 |
+
- mlx-swift
|
| 7 |
+
- apple-silicon
|
| 8 |
+
base_model:
|
| 9 |
+
- Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
<div align="center">
|
| 13 |
+
|
| 14 |
+
# Qwen3-TTS 12 Hz 1.7B Voicedesign for MLX, bf16
|
| 15 |
+
|
| 16 |
+
**Describe a voice in words and get it**
|
| 17 |
+
|
| 18 |
+
  [](https://www.apache.org/licenses/LICENSE-2.0) [](https://huggingface.co/kruatech/studio-mlx)
|
| 19 |
+
|
| 20 |
+
</div>
|
| 21 |
+
|
| 22 |
+
Text to speech at 24 kHz. A talker generates 16 codec codes per frame at 12 Hz - the first sampled directly, the remaining 15 filled in by a code predictor - and a codec turns those codes into a waveform.
|
| 23 |
+
|
| 24 |
+
Converted from [Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign) for native MLX inference on Apple silicon.
|
| 25 |
+
|
| 26 |
+
## Download
|
| 27 |
+
|
| 28 |
+
Self-contained. It does not use the shared Qwen3-4B encoder that the image models share; its own text stack and codec are inside this folder.
|
| 29 |
+
|
| 30 |
+
```bash
|
| 31 |
+
pip install "huggingface_hub[hf_xet]"
|
| 32 |
+
|
| 33 |
+
hf download kruatech/studio-mlx --local-dir bundles \
|
| 34 |
+
--include "qwen3-tts-12hz-1.7b-voicedesign/*"
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## Files
|
| 38 |
+
|
| 39 |
+
| component | class | precision | tensors | size |
|
| 40 |
+
|------------------|----------------------------------|-----------|---------|----------|
|
| 41 |
+
| model | Qwen3TTSForConditionalGeneration | keep | 404 | 3.57 GiB |
|
| 42 |
+
| speech_tokenizer | Qwen3TTSTokenizerV2Model | keep | 496 | 651 MiB |
|
| 43 |
+
|
| 44 |
+
Folder total: **4.21 GiB**. `manifest.json` carries SHA-256, byte sizes and tensor counts for every file.
|
| 45 |
+
|
| 46 |
+
## How this model works in MLX
|
| 47 |
+
|
| 48 |
+
- No preset speakers: the voice itself is described in natural language.
|
| 49 |
+
- `model` holds the talker and the code predictor; `speech_tokenizer` holds the codec, whose 52 Conv1d and 6 ConvTranspose1d weights are permuted to MLX layout.
|
| 50 |
+
- No 4-bit variant yet: quantization needs an MLX implementation of these modules, which does not exist at the time of writing.
|
| 51 |
+
|
| 52 |
+
<details>
|
| 53 |
+
<summary><b>Tensor layout</b></summary>
|
| 54 |
+
|
| 55 |
+
MLX convolutions expect channels last, PyTorch expects channels first, so convolution weights are permuted during conversion. Everything else keeps its upstream shape.
|
| 56 |
+
|
| 57 |
+
| kind | PyTorch | MLX |
|
| 58 |
+
|-----------------------------|---------------------|---------------------|
|
| 59 |
+
| `Conv2d.weight` | `(out, in, kH, kW)` | `(out, kH, kW, in)` |
|
| 60 |
+
| `Linear`, norms, embeddings | `(out, in)` | unchanged |
|
| 61 |
+
|
| 62 |
+
No `weight_norm` and no 3-D convolutions appear in these models, so no folding was needed. Parameter names match the upstream checkpoints, so weights load without remapping.
|
| 63 |
+
|
| 64 |
+
</details>
|
| 65 |
+
|
| 66 |
+
<details>
|
| 67 |
+
<summary><b>Verification numbers</b></summary>
|
| 68 |
+
|
| 69 |
+
Every module was compared against the upstream reference on fixed inputs in float32. The metric is `rel_max = max|a-b| / max|a|`.
|
| 70 |
+
|
| 71 |
+
| module | rel_max | reference |
|
| 72 |
+
|-------------------------------------------------|-----------|---------------------------------|
|
| 73 |
+
| Qwen3 encoder, hidden_states[-2] | 2.7e-07 | transformers |
|
| 74 |
+
| Qwen3 encoder, layers 9/18/27 with padding mask | 6.0e-07 | transformers |
|
| 75 |
+
| Z-Image DiT | 4.2e-06 | diffusers |
|
| 76 |
+
| Flux2 DiT | 3.7e-07 | diffusers |
|
| 77 |
+
| VAE decoder | 1.3e-05 | diffusers |
|
| 78 |
+
| VAE encoder | 5.3e-06 | diffusers |
|
| 79 |
+
| VAE tiled decode | 5.1e-06 | diffusers tiled_decode |
|
| 80 |
+
| sigma schedule, static shift | 3.2e-08 | FlowMatchEulerDiscreteScheduler |
|
| 81 |
+
| sigma schedule, exponential dynamic shift | 7.7e-08 | FlowMatchEulerDiscreteScheduler |
|
| 82 |
+
| position ids, latent packing, patchify | bit-exact | pipeline helpers |
|
| 83 |
+
|
| 84 |
+
A Swift MLX implementation was then checked against the Python one:
|
| 85 |
+
|
| 86 |
+
| module | rel_max | note |
|
| 87 |
+
|------------------------------|-----------------|------------------------------------------------|
|
| 88 |
+
| tokenization, both pipelines | bit-exact | same ids |
|
| 89 |
+
| Qwen3 encoder, bf16 | 2.2e-04 | Z-Image branch |
|
| 90 |
+
| Qwen3 encoder, bf16 | 4.6e-03 | klein branch, 512 tokens with mask |
|
| 91 |
+
| Qwen3 encoder, 4-bit | 3.0e-04 | proves the quantized layout is rebuilt exactly |
|
| 92 |
+
| Z-Image DiT, float32 | 3.7e-07 | 8 layers |
|
| 93 |
+
| Flux2 DiT, float32 | 1.0e-06 | 2 double + 2 single blocks |
|
| 94 |
+
| VAE decode / tiled / encode | 1e-05 or better | both VAE classes |
|
| 95 |
+
| VAE BatchNorm statistics | 0 | exact |
|
| 96 |
+
|
| 97 |
+
The bf16 figures for a full-depth DiT are larger - 2e-02 for both models - and that is rounding order, not a defect: at float32 the same code agrees to 1e-06, and the deviation grows with depth from a bf16-level 1e-04 per block. Comparing two bf16 implementations below 1e-02 is not meaningful for a 30-block network.
|
| 98 |
+
|
| 99 |
+
</details>
|
| 100 |
+
|
| 101 |
+
<details>
|
| 102 |
+
<summary><b>Performance on an M1 Max</b></summary>
|
| 103 |
+
|
| 104 |
+
Mac Studio, Apple M1 Max, 10-core CPU, 24-core GPU, 32 GB, macOS 26.5. Release build, 4-bit weights, batch 1, warm page cache.
|
| 105 |
+
|
| 106 |
+
| run | per step | VAE decode |
|
| 107 |
+
|--------------------------------------|----------|------------|
|
| 108 |
+
| Z-Image, 512 px, 4 steps | 2.6 s | 1.5 s |
|
| 109 |
+
| klein, 512 px, 4 steps | 2.3 s | 0.9 s |
|
| 110 |
+
| klein, 1024 px, 4 steps | 8.0 s | 0.2 s |
|
| 111 |
+
| klein, 512 px + one 512 px reference | 4.1 s | 0.9 s |
|
| 112 |
+
|
| 113 |
+
Reading the weights dominates a cold run and depends entirely on the storage: on an external volume delivering about 0.2 GiB/s, the 4-bit encoder took 22-32 s and a 4-bit DiT 18-35 s, against 60-107 s for the same weights in bf16. On internal storage expect these to be several times shorter. Compute is unaffected: the numbers above are steady state.
|
| 114 |
+
|
| 115 |
+
Stages run one at a time and release their weights, so peak memory is set by the largest single component rather than their sum. The 4-bit DiT is 2.03 GiB for klein and 3.40 GiB for Z-Image; activations at 1024 px add to that, and no separate peak measurement was made.
|
| 116 |
+
|
| 117 |
+
</details>
|
| 118 |
+
|
| 119 |
+
<details>
|
| 120 |
+
<summary><b>Limitations</b></summary>
|
| 121 |
+
|
| 122 |
+
- Seeds are not compatible with the upstream pipelines, which use `torch.Generator`. The same prompt gives comparable images, never the same file.
|
| 123 |
+
- Both models are distilled: CFG is not applied, and step counts are low by design (8 for Z-Image, 4 for klein).
|
| 124 |
+
- Z-Image's Omni mode is not covered: it needs a SigLIP encoder that is not part of this bundle.
|
| 125 |
+
- Tiled VAE decode is available for high resolutions and gives a result that differs slightly from a single pass, exactly as it does in diffusers.
|
| 126 |
+
- Batches larger than one are not implemented.
|
| 127 |
+
|
| 128 |
+
</details>
|
| 129 |
+
|
| 130 |
+
## Licence
|
| 131 |
+
|
| 132 |
+
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0), the licence of the upstream model. Conversion tooling and this card: MIT. The upstream card states usage restrictions that redistribution does not repeal.
|