Skip to content

Commit 061be12

Browse files
committed
Add Supertonic FP16 MLX export and runner
1 parent d5fd03f commit 061be12

49 files changed

Lines changed: 9247 additions & 2 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/mlx.yml‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ on:
1616
- examples/models/gemma4_31b/**
1717
- examples/models/muse-glimmer/**
1818
- examples/models/parakeet/**
19+
- examples/models/supertonic/**
1920
- examples/models/voxtral_realtime/**
2021
- examples/models/qwen3_5_moe/**
2122
workflow_dispatch:
@@ -115,6 +116,94 @@ jobs:
115116
done
116117
echo "::endgroup::"
117118
119+
test-mlx-supertonic:
120+
needs: run-decision
121+
if: |
122+
github.event_name == 'pull_request' ||
123+
needs.run-decision.outputs.is-full-run == 'true'
124+
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
125+
with:
126+
default-packages: ""
127+
job-name: test-mlx-supertonic
128+
runner: macos-14-xlarge
129+
python-version: "3.12"
130+
submodules: recursive
131+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
132+
timeout: 90
133+
script: |
134+
set -eux
135+
136+
echo "::group::Install ExecuTorch and Supertonic requirements"
137+
${CONDA_RUN} python install_executorch.py > /dev/null
138+
${CONDA_RUN} pip install -r examples/models/supertonic/requirements.txt
139+
echo "::endgroup::"
140+
141+
echo "::group::Run asset-independent Supertonic Python tests"
142+
${CONDA_RUN} python -m pytest examples/models/supertonic/tests -v
143+
echo "::endgroup::"
144+
145+
echo "::group::Download pinned Supertonic assets"
146+
SUPERTONIC_ASSETS=/tmp/supertonic-3
147+
${CONDA_RUN} python - <<'PY'
148+
from huggingface_hub import snapshot_download
149+
150+
snapshot_download(
151+
"Supertone/supertonic-3",
152+
revision="3cadd1ee6394adea1bd021217a0e650ede09a323",
153+
allow_patterns=(
154+
"onnx/tts.json",
155+
"onnx/duration_predictor.onnx",
156+
"onnx/text_encoder.onnx",
157+
"onnx/vector_estimator.onnx",
158+
"onnx/vocoder.onnx",
159+
"onnx/unicode_indexer.json",
160+
"voice_styles/F1.json",
161+
"LICENSE",
162+
),
163+
local_dir="/tmp/supertonic-3",
164+
)
165+
PY
166+
echo "::endgroup::"
167+
168+
echo "::group::Run published-model parity tests"
169+
SUPERTONIC_MODEL_DIR="${SUPERTONIC_ASSETS}" \
170+
${CONDA_RUN} python -m pytest \
171+
examples/models/supertonic/tests/test_checkpoint_loader.py \
172+
examples/models/supertonic/tests/test_stage_parity.py \
173+
-v
174+
echo "::endgroup::"
175+
176+
echo "::group::Export the Supertonic PTE"
177+
SUPERTONIC_PTE="${SUPERTONIC_ASSETS}/supertonic_fp16_mlx.pte"
178+
${CONDA_RUN} python -m examples.models.supertonic.export.export_supertonic \
179+
--asset-dir "${SUPERTONIC_ASSETS}" \
180+
--output "${SUPERTONIC_PTE}" \
181+
--max-text-length 512 \
182+
--max-latent-length 512 \
183+
--flow-steps 5
184+
echo "::endgroup::"
185+
186+
echo "::group::Build ExecuTorch and Supertonic with MLX"
187+
${CONDA_RUN} make supertonic-mlx
188+
echo "::endgroup::"
189+
190+
echo "::group::Run Supertonic native tests"
191+
pushd examples/models/supertonic
192+
${CONDA_RUN} cmake --preset supertonic-mlx \
193+
-DSUPERTONIC_INTEGRATION_PTE="${SUPERTONIC_PTE}" \
194+
-DSUPERTONIC_INTEGRATION_ASSET_DIR="${SUPERTONIC_ASSETS}" \
195+
-DSUPERTONIC_INTEGRATION_STYLE="${SUPERTONIC_ASSETS}/voice_styles/F1.json"
196+
${CONDA_RUN} ctest --preset supertonic-mlx
197+
popd
198+
echo "::endgroup::"
199+
200+
echo "::group::Verify the Supertonic runner and MLX metallib"
201+
RUNNER=cmake-out/examples/models/supertonic/supertonic_runner
202+
test -x "${RUNNER}"
203+
test -f "$(dirname "${RUNNER}")/mlx.metallib"
204+
"${RUNNER}" --helpshort > /dev/null
205+
echo "::endgroup::"
206+
118207
test-mlx-qwen35-moe:
119208
needs: run-decision
120209
if: |

‎Makefile‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# - whisper: Speech recognition model (CPU, CUDA, Metal)
2020
# - parakeet: Speech recognition model (CPU, CUDA, Metal, MLX)
2121
# - sortformer: Speaker diarization model (CPU, CUDA)
22+
# - supertonic: Text-to-speech model (MLX)
2223
# - silero_vad: Voice activity detection model (CPU)
2324
# - llama: Text generation model (CPU)
2425
# - llava: Vision + language model (CPU)
@@ -91,7 +92,7 @@
9192
#
9293
# ==============================================================================
9394

94-
.PHONY: voxtral-cuda voxtral-cpu voxtral-metal voxtral-mlx voxtral_realtime-cuda voxtral_realtime-rocm voxtral_realtime-cpu voxtral_realtime-metal voxtral_realtime-mlx voxtral_tts-cpu voxtral_tts-cuda whisper-cuda whisper-cuda-debug whisper-cpu whisper-metal parakeet-cuda parakeet-cuda-debug parakeet-cpu parakeet-metal parakeet-mlx parakeet-vulkan dinov2-cuda dinov2-cuda-debug sortformer-cuda sortformer-cpu silero-vad-cpu llama-cuda llama-cuda-debug llama-cpu lfm_2_5-mlx llava-cpu gemma3-cuda gemma3-cpu gemma4_31b-cuda gemma4_31b-mlx muse-glimmer-cuda muse-glimmer-mlx qwen3_5_moe-cuda qwen3_5_moe-metal qwen3_5_moe-mlx clean help
95+
.PHONY: voxtral-cuda voxtral-cpu voxtral-metal voxtral-mlx voxtral_realtime-cuda voxtral_realtime-rocm voxtral_realtime-cpu voxtral_realtime-metal voxtral_realtime-mlx voxtral_tts-cpu voxtral_tts-cuda whisper-cuda whisper-cuda-debug whisper-cpu whisper-metal parakeet-cuda parakeet-cuda-debug parakeet-cpu parakeet-metal parakeet-mlx parakeet-vulkan dinov2-cuda dinov2-cuda-debug sortformer-cuda sortformer-cpu supertonic-mlx silero-vad-cpu llama-cuda llama-cuda-debug llama-cpu lfm_2_5-mlx llava-cpu gemma3-cuda gemma3-cpu gemma4_31b-cuda gemma4_31b-mlx muse-glimmer-cuda muse-glimmer-mlx qwen3_5_moe-cuda qwen3_5_moe-metal qwen3_5_moe-mlx clean help
9596

9697
help:
9798
@echo "This Makefile adds targets to build runners for various models on various backends. Run using \`make <target>\`. Available targets:"
@@ -120,6 +121,7 @@ help:
120121
@echo " dinov2-cuda-debug - Build DINOv2 runner with CUDA backend (debug mode)"
121122
@echo " sortformer-cuda - Build Sortformer runner with CUDA backend"
122123
@echo " sortformer-cpu - Build Sortformer runner with CPU backend"
124+
@echo " supertonic-mlx - Build Supertonic runner with MLX backend"
123125
@echo " silero-vad-cpu - Build Silero VAD runner with CPU backend"
124126
@echo " llama-cuda - Build Llama runner with CUDA backend"
125127
@echo " llama-cuda-debug - Build Llama runner with CUDA backend (debug mode)"
@@ -300,6 +302,15 @@ sortformer-cpu:
300302
@echo "✓ Build complete!"
301303
@echo " Binary: cmake-out/examples/models/sortformer/sortformer_runner"
302304

305+
supertonic-mlx:
306+
@echo "==> Building and installing ExecuTorch with MLX..."
307+
cmake --workflow --preset mlx-release
308+
@echo "==> Building Supertonic runner with MLX..."
309+
cd examples/models/supertonic && cmake --workflow --preset supertonic-mlx
310+
@echo ""
311+
@echo "✓ Build complete!"
312+
@echo " Binary: cmake-out/examples/models/supertonic/supertonic_runner"
313+
303314
voxtral_realtime-cpu:
304315
@echo "==> Building and installing ExecuTorch..."
305316
cmake --workflow --preset llm-release

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ ExecuTorch powers on-device AI at scale across Meta's family of apps, VR/AR devi
204204

205205
**Multimodal:** [Llava](examples/models/llava/README.md) (vision-language), [Voxtral](examples/models/voxtral/README.md) (audio-language), [Gemma](examples/models/gemma3) (vision-language)
206206

207-
**Vision/Speech:** [MobileNetV2](https://github.com/meta-pytorch/executorch-examples/tree/main/mv2), [DeepLabV3](https://github.com/meta-pytorch/executorch-examples/tree/main/dl3), [YOLO26](examples/models/yolo26/README.md), [Whisper](examples/models/whisper/README.md) <!-- @lint-ignore -->
207+
**Vision/Speech:** [MobileNetV2](https://github.com/meta-pytorch/executorch-examples/tree/main/mv2), [DeepLabV3](https://github.com/meta-pytorch/executorch-examples/tree/main/dl3), [YOLO26](examples/models/yolo26/README.md), [Whisper](examples/models/whisper/README.md), [Supertonic](examples/models/supertonic/README.md) <!-- @lint-ignore -->
208208

209209
**Resources:** [`examples/`](examples/) directory • [executorch-examples](https://github.com/meta-pytorch/executorch-examples) out-of-tree demos • [Optimum-ExecuTorch](https://github.com/huggingface/optimum-executorch) for HuggingFace models • [Unsloth](https://docs.unsloth.ai/new/deploy-llms-phone) for fine-tuned LLM deployment <!-- @lint-ignore -->
210210

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
cmake_minimum_required(VERSION 3.24)
8+
project(supertonic_runner)
9+
10+
include(GNUInstallDirs)
11+
12+
if(NOT APPLE)
13+
message(FATAL_ERROR "The Supertonic MLX runner is supported only on Darwin.")
14+
endif()
15+
16+
set(_supertonic_target_processor "${CMAKE_OSX_ARCHITECTURES}")
17+
if(NOT _supertonic_target_processor)
18+
set(_supertonic_target_processor "${CMAKE_SYSTEM_PROCESSOR}")
19+
endif()
20+
if(NOT _supertonic_target_processor STREQUAL "arm64")
21+
message(
22+
FATAL_ERROR
23+
"The Supertonic MLX runner requires an arm64 Darwin target; detected '${_supertonic_target_processor}'."
24+
)
25+
endif()
26+
27+
set(CMAKE_CXX_STANDARD 17)
28+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
29+
30+
set(EXECUTORCH_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
31+
include(${EXECUTORCH_SOURCE_ROOT}/tools/cmake/Utils.cmake)
32+
33+
set(_json_include
34+
${EXECUTORCH_SOURCE_ROOT}/extension/llm/tokenizers/third-party/json/single_include
35+
)
36+
find_library(COREFOUNDATION_FRAMEWORK CoreFoundation REQUIRED)
37+
38+
set(_helper_sources runtime/supertonic_runner.cpp runtime/text_processor.cpp
39+
runtime/style_loader.cpp runtime/wav_writer.cpp
40+
)
41+
42+
enable_testing()
43+
add_executable(
44+
supertonic_runtime_test runtime/tests/supertonic_runtime_test.cpp
45+
${_helper_sources}
46+
)
47+
target_compile_definitions(
48+
supertonic_runtime_test PRIVATE SUPERTONIC_PURE_HELPERS_ONLY
49+
)
50+
target_include_directories(
51+
supertonic_runtime_test PRIVATE runtime ${_json_include}
52+
)
53+
target_link_libraries(
54+
supertonic_runtime_test PRIVATE ${COREFOUNDATION_FRAMEWORK}
55+
)
56+
add_test(NAME supertonic_runtime_helpers COMMAND supertonic_runtime_test)
57+
58+
set(gflags_DIR ${CMAKE_CURRENT_BINARY_DIR}/../../../third-party/gflags)
59+
find_package(gflags REQUIRED)
60+
61+
list(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_CURRENT_BINARY_DIR}/../../..)
62+
find_package(executorch CONFIG REQUIRED FIND_ROOT_PATH_BOTH)
63+
executorch_target_link_options_shared_lib(executorch)
64+
65+
if(NOT TARGET mlxdelegate OR NOT TARGET mlx)
66+
message(
67+
FATAL_ERROR
68+
"ExecuTorch must be installed with the MLX delegate and runtime targets."
69+
)
70+
endif()
71+
72+
foreach(required_target extension_module extension_data_loader extension_tensor
73+
extension_flat_tensor
74+
)
75+
if(NOT TARGET ${required_target})
76+
message(
77+
FATAL_ERROR
78+
"ExecuTorch installation is missing required target ${required_target}."
79+
)
80+
endif()
81+
endforeach()
82+
83+
add_executable(supertonic_runner runtime/main.cpp ${_helper_sources})
84+
target_compile_definitions(supertonic_runner PRIVATE EXECUTORCH_BUILD_MLX)
85+
target_include_directories(
86+
supertonic_runner PRIVATE ${EXECUTORCH_SOURCE_ROOT}/.. runtime
87+
${_json_include}
88+
)
89+
target_link_libraries(
90+
supertonic_runner
91+
PRIVATE executorch
92+
extension_module
93+
extension_data_loader
94+
extension_tensor
95+
extension_flat_tensor
96+
mlxdelegate
97+
mlx
98+
gflags
99+
${COREFOUNDATION_FRAMEWORK}
100+
)
101+
executorch_target_link_options_shared_lib(mlxdelegate)
102+
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
103+
target_link_options_gc_sections(supertonic_runner)
104+
endif()
105+
set(EXECUTORCH_BUILD_MLX ON)
106+
if(NOT DEFINED MLX_METALLIB_PATH OR NOT EXISTS "${MLX_METALLIB_PATH}")
107+
message(FATAL_ERROR "The installed MLX package did not provide mlx.metallib.")
108+
endif()
109+
executorch_target_copy_mlx_metallib(supertonic_runner)
110+
install(TARGETS supertonic_runner RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
111+
install(
112+
FILES "${MLX_METALLIB_PATH}"
113+
DESTINATION ${CMAKE_INSTALL_BINDIR}
114+
RENAME mlx.metallib
115+
)
116+
117+
set(SUPERTONIC_INTEGRATION_PTE
118+
""
119+
CACHE FILEPATH "Optional Supertonic PTE for the integration test."
120+
)
121+
set(SUPERTONIC_INTEGRATION_ASSET_DIR
122+
""
123+
CACHE PATH "Optional published Supertonic asset directory for integration."
124+
)
125+
set(SUPERTONIC_INTEGRATION_STYLE
126+
""
127+
CACHE FILEPATH "Optional published voice-style JSON for integration."
128+
)
129+
add_test(
130+
NAME supertonic_integration
131+
COMMAND
132+
${CMAKE_COMMAND} -DRUNNER=$<TARGET_FILE:supertonic_runner>
133+
-DPTE=${SUPERTONIC_INTEGRATION_PTE}
134+
-DASSET_DIR=${SUPERTONIC_INTEGRATION_ASSET_DIR}
135+
-DSTYLE=${SUPERTONIC_INTEGRATION_STYLE}
136+
-DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/supertonic-integration.wav -P
137+
${CMAKE_CURRENT_SOURCE_DIR}/runtime/tests/run_integration.cmake
138+
)
139+
set_tests_properties(
140+
supertonic_integration
141+
PROPERTIES TIMEOUT 1800 SKIP_REGULAR_EXPRESSION
142+
"SKIP: Supertonic integration assets are unavailable"
143+
)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"version": 6,
3+
"configurePresets": [
4+
{
5+
"name": "supertonic-base",
6+
"hidden": true,
7+
"binaryDir": "${sourceDir}/../../../cmake-out/examples/models/supertonic",
8+
"cacheVariables": {
9+
"CMAKE_BUILD_TYPE": "Release",
10+
"CMAKE_CXX_STANDARD": "17",
11+
"CMAKE_FIND_ROOT_PATH": "${sourceDir}/../../../cmake-out",
12+
"CMAKE_PREFIX_PATH": "${sourceDir}/../../../cmake-out"
13+
}
14+
},
15+
{
16+
"name": "supertonic-mlx",
17+
"displayName": "Supertonic runner (MLX)",
18+
"inherits": ["supertonic-base"],
19+
"cacheVariables": {
20+
"EXECUTORCH_BUILD_MLX": "ON"
21+
},
22+
"condition": {
23+
"type": "equals",
24+
"lhs": "${hostSystemName}",
25+
"rhs": "Darwin"
26+
}
27+
}
28+
],
29+
"buildPresets": [
30+
{
31+
"name": "supertonic-mlx",
32+
"displayName": "Build Supertonic runner and tests",
33+
"configurePreset": "supertonic-mlx",
34+
"configuration": "Release",
35+
"targets": [
36+
"supertonic_runner",
37+
"supertonic_runtime_test"
38+
]
39+
}
40+
],
41+
"testPresets": [
42+
{
43+
"name": "supertonic-mlx",
44+
"displayName": "Test Supertonic runner",
45+
"configurePreset": "supertonic-mlx",
46+
"configuration": "Release",
47+
"output": {
48+
"outputOnFailure": true
49+
}
50+
}
51+
],
52+
"workflowPresets": [
53+
{
54+
"name": "supertonic-mlx",
55+
"displayName": "Configure and build Supertonic runner (MLX)",
56+
"steps": [
57+
{
58+
"type": "configure",
59+
"name": "supertonic-mlx"
60+
},
61+
{
62+
"type": "build",
63+
"name": "supertonic-mlx"
64+
}
65+
]
66+
}
67+
]
68+
}

‎examples/models/supertonic/NOTICE‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Supertonic upstream attribution
2+
===============================
3+
4+
The Supertonic architecture and portions of this example are adapted from:
5+
6+
https://github.com/supertone-inc/supertonic
7+
Revision: 7e2804f96016a7028cb1ed627353c61c1e9dd281
8+
9+
The upstream source is provided under the following license:
10+
11+
MIT License
12+
13+
Copyright (c) 2025 Supertone Inc.
14+
15+
Permission is hereby granted, free of charge, to any person obtaining a copy
16+
of this software and associated documentation files (the "Software"), to deal
17+
in the Software without restriction, including without limitation the rights
18+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19+
copies of the Software, and to permit persons to whom the Software is
20+
furnished to do so, subject to the following conditions:
21+
22+
The above copyright notice and this permission notice shall be included in all
23+
copies or substantial portions of the Software.
24+
25+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31+
SOFTWARE.

0 commit comments

Comments
 (0)