Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions .github/workflows/mlx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ on:
- examples/models/gemma4_31b/**
- examples/models/muse-glimmer/**
- examples/models/parakeet/**
- examples/models/supertonic/**
- examples/models/voxtral_realtime/**
- examples/models/qwen3_5_moe/**
workflow_dispatch:
Expand Down Expand Up @@ -115,6 +116,93 @@ jobs:
done
echo "::endgroup::"

test-mlx-supertonic:
needs: run-decision
if: |
github.event_name == 'pull_request' ||
needs.run-decision.outputs.is-full-run == 'true'
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
with:
default-packages: ""
job-name: test-mlx-supertonic
runner: macos-14-xlarge
python-version: "3.12"
submodules: recursive
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
timeout: 90
script: |
set -eux

echo "::group::Install ExecuTorch and Supertonic requirements"
${CONDA_RUN} python install_executorch.py > /dev/null
${CONDA_RUN} pip install -r examples/models/supertonic/requirements.txt
echo "::endgroup::"

echo "::group::Run asset-independent Supertonic Python tests"
${CONDA_RUN} python -m pytest examples/models/supertonic/tests -v
echo "::endgroup::"

echo "::group::Download pinned Supertonic assets"
SUPERTONIC_ASSETS=/tmp/supertonic-3
${CONDA_RUN} python - <<'PY'
from huggingface_hub import snapshot_download

snapshot_download(
"Supertone/supertonic-3",
revision="3cadd1ee6394adea1bd021217a0e650ede09a323",
allow_patterns=(
"onnx/tts.json",
"onnx/duration_predictor.onnx",
"onnx/text_encoder.onnx",
"onnx/vector_estimator.onnx",
"onnx/vocoder.onnx",
"onnx/unicode_indexer.json",
"voice_styles/F1.json",
"LICENSE",
),
local_dir="/tmp/supertonic-3",
)
PY
echo "::endgroup::"

echo "::group::Run published-model parity tests"
SUPERTONIC_MODEL_DIR="${SUPERTONIC_ASSETS}" \
${CONDA_RUN} python -m pytest \
examples/models/supertonic/tests/test_checkpoint_loader.py \
examples/models/supertonic/tests/test_stage_parity.py \
-v
echo "::endgroup::"

echo "::group::Export the Supertonic PTE"
SUPERTONIC_PTE="${SUPERTONIC_ASSETS}/supertonic_fp16_mlx.pte"
${CONDA_RUN} python -m examples.models.supertonic.export.export_supertonic \
--asset-dir "${SUPERTONIC_ASSETS}" \
--output "${SUPERTONIC_PTE}" \
--max-text-length 512 \
--max-latent-length 512 \
--flow-steps 5
echo "::endgroup::"

echo "::group::Build ExecuTorch and Supertonic with MLX"
${CONDA_RUN} make supertonic-mlx
echo "::endgroup::"

echo "::group::Run Supertonic native tests"
pushd examples/models/supertonic
${CONDA_RUN} cmake --preset supertonic-mlx \
-DSUPERTONIC_INTEGRATION_PTE="${SUPERTONIC_PTE}" \
-DSUPERTONIC_INTEGRATION_ASSET_DIR="${SUPERTONIC_ASSETS}" \
-DSUPERTONIC_INTEGRATION_STYLE="${SUPERTONIC_ASSETS}/voice_styles/F1.json"
${CONDA_RUN} ctest --preset supertonic-mlx
popd
echo "::endgroup::"

echo "::group::Verify the Supertonic runner and MLX metallib"
RUNNER=cmake-out/examples/models/supertonic/supertonic_runner
test -x "${RUNNER}"
test -f "$(dirname "${RUNNER}")/mlx.metallib"
echo "::endgroup::"

test-mlx-qwen35-moe:
needs: run-decision
if: |
Expand Down
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# - whisper: Speech recognition model (CPU, CUDA, Metal)
# - parakeet: Speech recognition model (CPU, CUDA, Metal, MLX)
# - sortformer: Speaker diarization model (CPU, CUDA)
# - supertonic: Text-to-speech model (MLX)
# - silero_vad: Voice activity detection model (CPU)
# - llama: Text generation model (CPU)
# - llava: Vision + language model (CPU)
Expand Down Expand Up @@ -91,7 +92,7 @@
#
# ==============================================================================

.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
.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

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

supertonic-mlx:
@echo "==> Building and installing ExecuTorch with MLX..."
cmake --workflow --preset mlx-release
@echo "==> Building Supertonic runner with MLX..."
cd examples/models/supertonic && cmake --workflow --preset supertonic-mlx
@echo ""
@echo "✓ Build complete!"
@echo " Binary: cmake-out/examples/models/supertonic/supertonic_runner"

voxtral_realtime-cpu:
@echo "==> Building and installing ExecuTorch..."
cmake --workflow --preset llm-release
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ ExecuTorch powers on-device AI at scale across Meta's family of apps, VR/AR devi

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

**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 -->
**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 -->

**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 -->

Expand Down
143 changes: 143 additions & 0 deletions examples/models/supertonic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

cmake_minimum_required(VERSION 3.24)
project(supertonic_runner)

include(GNUInstallDirs)

if(NOT APPLE)
message(FATAL_ERROR "The Supertonic MLX runner is supported only on Darwin.")
endif()

set(_supertonic_target_processor "${CMAKE_OSX_ARCHITECTURES}")
if(NOT _supertonic_target_processor)
set(_supertonic_target_processor "${CMAKE_SYSTEM_PROCESSOR}")
endif()
if(NOT _supertonic_target_processor STREQUAL "arm64")
message(
FATAL_ERROR
"The Supertonic MLX runner requires an arm64 Darwin target; detected '${_supertonic_target_processor}'."
)
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(EXECUTORCH_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
include(${EXECUTORCH_SOURCE_ROOT}/tools/cmake/Utils.cmake)

set(_json_include
${EXECUTORCH_SOURCE_ROOT}/extension/llm/tokenizers/third-party/json/single_include
)
find_library(COREFOUNDATION_FRAMEWORK CoreFoundation REQUIRED)

set(_helper_sources runtime/supertonic_runner.cpp runtime/text_processor.cpp
runtime/style_loader.cpp runtime/wav_writer.cpp
)

enable_testing()
add_executable(
supertonic_runtime_test runtime/tests/supertonic_runtime_test.cpp
${_helper_sources}
)
target_compile_definitions(
supertonic_runtime_test PRIVATE SUPERTONIC_PURE_HELPERS_ONLY
)
target_include_directories(
supertonic_runtime_test PRIVATE runtime ${_json_include}
)
target_link_libraries(
supertonic_runtime_test PRIVATE ${COREFOUNDATION_FRAMEWORK}
)
add_test(NAME supertonic_runtime_helpers COMMAND supertonic_runtime_test)

set(gflags_DIR ${CMAKE_CURRENT_BINARY_DIR}/../../../third-party/gflags)
find_package(gflags REQUIRED)

list(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_CURRENT_BINARY_DIR}/../../..)
find_package(executorch CONFIG REQUIRED FIND_ROOT_PATH_BOTH)
executorch_target_link_options_shared_lib(executorch)

if(NOT TARGET mlxdelegate OR NOT TARGET mlx)
message(
FATAL_ERROR
"ExecuTorch must be installed with the MLX delegate and runtime targets."
)
endif()

foreach(required_target extension_module extension_data_loader extension_tensor
extension_flat_tensor
)
if(NOT TARGET ${required_target})
message(
FATAL_ERROR
"ExecuTorch installation is missing required target ${required_target}."
)
endif()
endforeach()

add_executable(supertonic_runner runtime/main.cpp ${_helper_sources})
target_compile_definitions(supertonic_runner PRIVATE EXECUTORCH_BUILD_MLX)
target_include_directories(
supertonic_runner PRIVATE ${EXECUTORCH_SOURCE_ROOT}/.. runtime
${_json_include}
)
target_link_libraries(
supertonic_runner
PRIVATE executorch
extension_module
extension_data_loader
extension_tensor
extension_flat_tensor
mlxdelegate
mlx
gflags
${COREFOUNDATION_FRAMEWORK}
)
executorch_target_link_options_shared_lib(mlxdelegate)
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_options_gc_sections(supertonic_runner)
endif()
set(EXECUTORCH_BUILD_MLX ON)
if(NOT DEFINED MLX_METALLIB_PATH OR NOT EXISTS "${MLX_METALLIB_PATH}")
message(FATAL_ERROR "The installed MLX package did not provide mlx.metallib.")
endif()
executorch_target_copy_mlx_metallib(supertonic_runner)
install(TARGETS supertonic_runner RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(
FILES "${MLX_METALLIB_PATH}"
DESTINATION ${CMAKE_INSTALL_BINDIR}
RENAME mlx.metallib
)

set(SUPERTONIC_INTEGRATION_PTE
""
CACHE FILEPATH "Optional Supertonic PTE for the integration test."
)
set(SUPERTONIC_INTEGRATION_ASSET_DIR
""
CACHE PATH "Optional published Supertonic asset directory for integration."
)
set(SUPERTONIC_INTEGRATION_STYLE
""
CACHE FILEPATH "Optional published voice-style JSON for integration."
)
add_test(
NAME supertonic_integration
COMMAND
${CMAKE_COMMAND} -DRUNNER=$<TARGET_FILE:supertonic_runner>
-DPTE=${SUPERTONIC_INTEGRATION_PTE}
-DASSET_DIR=${SUPERTONIC_INTEGRATION_ASSET_DIR}
-DSTYLE=${SUPERTONIC_INTEGRATION_STYLE}
-DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/supertonic-integration.wav -P
${CMAKE_CURRENT_SOURCE_DIR}/runtime/tests/run_integration.cmake
)
set_tests_properties(
supertonic_integration
PROPERTIES TIMEOUT 1800 SKIP_REGULAR_EXPRESSION
"SKIP: Supertonic integration assets are unavailable"
)
68 changes: 68 additions & 0 deletions examples/models/supertonic/CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"version": 6,
"configurePresets": [
{
"name": "supertonic-base",
"hidden": true,
"binaryDir": "${sourceDir}/../../../cmake-out/examples/models/supertonic",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_STANDARD": "17",
"CMAKE_FIND_ROOT_PATH": "${sourceDir}/../../../cmake-out",
"CMAKE_PREFIX_PATH": "${sourceDir}/../../../cmake-out"
}
},
{
"name": "supertonic-mlx",
"displayName": "Supertonic runner (MLX)",
"inherits": ["supertonic-base"],
"cacheVariables": {
"EXECUTORCH_BUILD_MLX": "ON"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
}
],
"buildPresets": [
{
"name": "supertonic-mlx",
"displayName": "Build Supertonic runner and tests",
"configurePreset": "supertonic-mlx",
"configuration": "Release",
"targets": [
"supertonic_runner",
"supertonic_runtime_test"
]
}
],
"testPresets": [
{
"name": "supertonic-mlx",
"displayName": "Test Supertonic runner",
"configurePreset": "supertonic-mlx",
"configuration": "Release",
"output": {
"outputOnFailure": true
}
}
],
"workflowPresets": [
{
"name": "supertonic-mlx",
"displayName": "Configure and build Supertonic runner (MLX)",
"steps": [
{
"type": "configure",
"name": "supertonic-mlx"
},
{
"type": "build",
"name": "supertonic-mlx"
}
]
}
]
}
31 changes: 31 additions & 0 deletions examples/models/supertonic/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Supertonic upstream attribution
===============================

The Supertonic architecture and portions of this example are adapted from:

https://github.com/supertone-inc/supertonic
Revision: 7e2804f96016a7028cb1ed627353c61c1e9dd281

The upstream source is provided under the following license:

MIT License

Copyright (c) 2025 Supertone Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading