nodetool-mlx 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nodetool_mlx-0.7.0/.github/workflows/ci.yml +122 -0
- nodetool_mlx-0.7.0/.github/workflows/publish-wheel.yml +230 -0
- nodetool_mlx-0.7.0/.gitignore +56 -0
- nodetool_mlx-0.7.0/PKG-INFO +219 -0
- nodetool_mlx-0.7.0/README.md +191 -0
- nodetool_mlx-0.7.0/pyproject.toml +72 -0
- nodetool_mlx-0.7.0/requirements-dev.txt +13 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/__init__.py +5 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/flux_model_loader.py +445 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/mlx_provider.py +3015 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/LICENSE +21 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/NOTICE.md +23 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/__init__.py +24 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/__init__.py +0 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/dit_mlx.py +344 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/dit_mlx_medium.py +458 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/sa3_pipeline.py +199 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/same_l_decoder.py +345 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/same_l_encoder.py +146 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/same_s_decoder.py +294 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/same_s_encoder.py +161 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/defs/t5gemma_mlx.py +313 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/pipeline.py +386 -0
- nodetool_mlx-0.7.0/src/nodetool/mlx/stable_audio_3/weights.py +64 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/_hf_cache.py +55 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/automatic_speech_recognition.py +184 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/image_to_image.py +3199 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/image_to_text.py +219 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/speech_enhancement.py +252 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/speech_to_text.py +411 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/text_generation.py +245 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/text_to_audio.py +372 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/text_to_image.py +336 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/text_to_music.py +729 -0
- nodetool_mlx-0.7.0/src/nodetool/nodes/mlx/text_to_speech.py +1464 -0
- nodetool_mlx-0.7.0/src/nodetool/package_metadata/nodetool-mlx.json +10105 -0
- nodetool_mlx-0.7.0/tests/nodes/mlx/test_text_to_music.py +156 -0
- nodetool_mlx-0.7.0/tests/test_audio_nodes.py +533 -0
- nodetool_mlx-0.7.0/tests/test_image_nodes.py +214 -0
- nodetool_mlx-0.7.0/tests/test_package_metadata.py +84 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
# A new push to a PR makes the in-flight run obsolete.
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
lint:
|
|
20
|
+
name: Lint and format
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
timeout-minutes: 10
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-python@v6
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.11"
|
|
29
|
+
cache: pip
|
|
30
|
+
|
|
31
|
+
- name: Install linters
|
|
32
|
+
# Pinned: an unpinned linter turns an upstream release into a red build
|
|
33
|
+
# on an unrelated PR. Bump deliberately, fixing any new findings in the
|
|
34
|
+
# same change. Keep in sync with requirements-dev.txt.
|
|
35
|
+
run: pip install "ruff==0.15.8" "black==26.3.1"
|
|
36
|
+
|
|
37
|
+
- name: ruff
|
|
38
|
+
run: ruff check .
|
|
39
|
+
|
|
40
|
+
- name: black
|
|
41
|
+
run: black --check --diff .
|
|
42
|
+
|
|
43
|
+
# The MLX runtimes (mlx, mflux, mlx-audio, ...) are Apple Silicon only, so the
|
|
44
|
+
# bulk of the suite is written to run without them and this job installs the
|
|
45
|
+
# package with --no-deps. It is the fast signal on every push, and it also
|
|
46
|
+
# covers the "node modules import without the MLX stack" property that the
|
|
47
|
+
# package metadata scanner relies on.
|
|
48
|
+
test-linux:
|
|
49
|
+
name: Test (linux, no MLX runtime)
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
timeout-minutes: 20
|
|
52
|
+
strategy:
|
|
53
|
+
fail-fast: false
|
|
54
|
+
matrix:
|
|
55
|
+
python-version: ["3.11", "3.12"]
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v6
|
|
58
|
+
|
|
59
|
+
- uses: actions/setup-python@v6
|
|
60
|
+
with:
|
|
61
|
+
python-version: ${{ matrix.python-version }}
|
|
62
|
+
cache: pip
|
|
63
|
+
|
|
64
|
+
- name: Install nodetool-core and test dependencies
|
|
65
|
+
run: |
|
|
66
|
+
pip install --upgrade pip
|
|
67
|
+
pip install "nodetool-core>=0.7.0"
|
|
68
|
+
pip install pytest pytest-asyncio pytest-cov
|
|
69
|
+
|
|
70
|
+
- name: Install this package without the Apple-Silicon-only dependencies
|
|
71
|
+
run: pip install --no-deps -e .
|
|
72
|
+
|
|
73
|
+
- name: Run tests
|
|
74
|
+
# Tests needing mflux / mlx-audio skip themselves via importorskip.
|
|
75
|
+
run: pytest tests -q
|
|
76
|
+
|
|
77
|
+
# The real thing: Apple Silicon runners install the full dependency set, so
|
|
78
|
+
# nothing is skipped here. Slower and heavier, hence a single Python version.
|
|
79
|
+
test-macos:
|
|
80
|
+
name: Test (macOS, full MLX runtime)
|
|
81
|
+
runs-on: macos-14
|
|
82
|
+
timeout-minutes: 45
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@v6
|
|
85
|
+
|
|
86
|
+
- uses: actions/setup-python@v6
|
|
87
|
+
with:
|
|
88
|
+
python-version: "3.11"
|
|
89
|
+
cache: pip
|
|
90
|
+
|
|
91
|
+
- name: Install package with all dependencies
|
|
92
|
+
run: |
|
|
93
|
+
pip install --upgrade pip
|
|
94
|
+
pip install -e .
|
|
95
|
+
pip install pytest pytest-asyncio pytest-cov
|
|
96
|
+
|
|
97
|
+
- name: Show installed MLX stack
|
|
98
|
+
run: pip list | grep -Ei "^(mlx|mflux|nodetool)" || true
|
|
99
|
+
|
|
100
|
+
- name: Run tests
|
|
101
|
+
run: pytest tests -q
|
|
102
|
+
|
|
103
|
+
build:
|
|
104
|
+
name: Build wheel
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
timeout-minutes: 10
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v6
|
|
109
|
+
|
|
110
|
+
- uses: actions/setup-python@v6
|
|
111
|
+
with:
|
|
112
|
+
python-version: "3.11"
|
|
113
|
+
cache: pip
|
|
114
|
+
|
|
115
|
+
- name: Install build tooling
|
|
116
|
+
run: pip install --upgrade pip build twine
|
|
117
|
+
|
|
118
|
+
- name: Build sdist and wheel
|
|
119
|
+
run: python -m build
|
|
120
|
+
|
|
121
|
+
- name: Check distributions
|
|
122
|
+
run: twine check dist/*
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
name: Build and Publish Wheel
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# Trigger on version tags
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- "v*.*.*"
|
|
8
|
+
|
|
9
|
+
# Manual trigger for testing
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
version:
|
|
13
|
+
description: "Version to release (e.g., 0.6.0)"
|
|
14
|
+
required: true
|
|
15
|
+
type: string
|
|
16
|
+
prerelease:
|
|
17
|
+
description: "Mark as prerelease"
|
|
18
|
+
required: false
|
|
19
|
+
default: false
|
|
20
|
+
type: boolean
|
|
21
|
+
publish_pypi:
|
|
22
|
+
description: "Also publish to PyPI / TestPyPI"
|
|
23
|
+
required: false
|
|
24
|
+
default: "none"
|
|
25
|
+
type: choice
|
|
26
|
+
options:
|
|
27
|
+
- none
|
|
28
|
+
- testpypi
|
|
29
|
+
- pypi
|
|
30
|
+
|
|
31
|
+
env:
|
|
32
|
+
PACKAGE_NAME: ${{ github.event.repository.name }} # e.g., "nodetool-base"
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
validate:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
outputs:
|
|
38
|
+
version: ${{ steps.get-version.outputs.version }}
|
|
39
|
+
tag-name: ${{ steps.get-version.outputs.tag-name }}
|
|
40
|
+
is-prerelease: ${{ steps.get-version.outputs.is-prerelease }}
|
|
41
|
+
steps:
|
|
42
|
+
- name: Get version from tag or input
|
|
43
|
+
id: get-version
|
|
44
|
+
run: |
|
|
45
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
46
|
+
VERSION="${{ github.event.inputs.version }}"
|
|
47
|
+
TAG_NAME="v${VERSION}"
|
|
48
|
+
IS_PRERELEASE="${{ github.event.inputs.prerelease }}"
|
|
49
|
+
else
|
|
50
|
+
TAG_NAME="${{ github.ref_name }}"
|
|
51
|
+
VERSION="${TAG_NAME#v}"
|
|
52
|
+
IS_PRERELEASE="false"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
56
|
+
echo "tag-name=$TAG_NAME" >> $GITHUB_OUTPUT
|
|
57
|
+
echo "is-prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
|
|
58
|
+
|
|
59
|
+
echo "📋 Version: $VERSION"
|
|
60
|
+
echo "🏷️ Tag: $TAG_NAME"
|
|
61
|
+
echo "🔄 Prerelease: $IS_PRERELEASE"
|
|
62
|
+
|
|
63
|
+
build-wheel:
|
|
64
|
+
needs: validate
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
steps:
|
|
67
|
+
- name: Checkout code
|
|
68
|
+
uses: actions/checkout@v6
|
|
69
|
+
with:
|
|
70
|
+
ref: ${{ needs.validate.outputs.tag-name }}
|
|
71
|
+
|
|
72
|
+
- name: Set up Python
|
|
73
|
+
uses: actions/setup-python@v6
|
|
74
|
+
with:
|
|
75
|
+
python-version: "3.11"
|
|
76
|
+
|
|
77
|
+
- name: Install build dependencies
|
|
78
|
+
run: |
|
|
79
|
+
pip install --upgrade pip
|
|
80
|
+
pip install build hatchling twine
|
|
81
|
+
|
|
82
|
+
- name: Download build helper
|
|
83
|
+
run: |
|
|
84
|
+
curl -fsSL https://raw.githubusercontent.com/nodetool-ai/nodetool-core/main/build.py -o build.py
|
|
85
|
+
|
|
86
|
+
- name: Build wheel
|
|
87
|
+
run: |
|
|
88
|
+
echo "🏗️ Building wheel for ${{ env.PACKAGE_NAME }}"
|
|
89
|
+
python build.py build-wheel --expected-version "${{ needs.validate.outputs.version }}"
|
|
90
|
+
|
|
91
|
+
- name: Validate wheel
|
|
92
|
+
run: |
|
|
93
|
+
python build.py validate-wheel
|
|
94
|
+
|
|
95
|
+
- name: Upload wheel artifact
|
|
96
|
+
uses: actions/upload-artifact@v7
|
|
97
|
+
with:
|
|
98
|
+
name: wheel-${{ env.PACKAGE_NAME }}-${{ needs.validate.outputs.version }}
|
|
99
|
+
path: |
|
|
100
|
+
dist/*.whl
|
|
101
|
+
dist/*.whl.metadata
|
|
102
|
+
retention-days: 30
|
|
103
|
+
|
|
104
|
+
create-release:
|
|
105
|
+
needs: [validate, build-wheel]
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
permissions:
|
|
108
|
+
contents: write
|
|
109
|
+
steps:
|
|
110
|
+
- name: Checkout code
|
|
111
|
+
uses: actions/checkout@v6
|
|
112
|
+
with:
|
|
113
|
+
ref: ${{ needs.validate.outputs.tag-name }}
|
|
114
|
+
|
|
115
|
+
- name: Download build helper
|
|
116
|
+
run: |
|
|
117
|
+
curl -fsSL https://raw.githubusercontent.com/nodetool-ai/nodetool-core/main/build.py -o build.py
|
|
118
|
+
|
|
119
|
+
- name: Download wheel artifact
|
|
120
|
+
uses: actions/download-artifact@v8
|
|
121
|
+
with:
|
|
122
|
+
name: wheel-${{ env.PACKAGE_NAME }}-${{ needs.validate.outputs.version }}
|
|
123
|
+
path: dist/
|
|
124
|
+
|
|
125
|
+
- name: Generate release notes
|
|
126
|
+
run: |
|
|
127
|
+
python build.py release-notes \
|
|
128
|
+
--package "${{ env.PACKAGE_NAME }}" \
|
|
129
|
+
--version "${{ needs.validate.outputs.version }}" \
|
|
130
|
+
--tag "${{ needs.validate.outputs.tag-name }}" \
|
|
131
|
+
--repository "${{ github.repository }}" \
|
|
132
|
+
--server-url "${{ github.server_url }}"
|
|
133
|
+
|
|
134
|
+
- name: Create GitHub Release
|
|
135
|
+
uses: softprops/action-gh-release@v1
|
|
136
|
+
with:
|
|
137
|
+
tag_name: ${{ needs.validate.outputs.tag-name }}
|
|
138
|
+
name: "${{ env.PACKAGE_NAME }} v${{ needs.validate.outputs.version }}"
|
|
139
|
+
body_path: release_notes.md
|
|
140
|
+
files: |
|
|
141
|
+
dist/*.whl
|
|
142
|
+
dist/*.whl.metadata
|
|
143
|
+
draft: false
|
|
144
|
+
prerelease: ${{ needs.validate.outputs.is-prerelease }}
|
|
145
|
+
generate_release_notes: true
|
|
146
|
+
env:
|
|
147
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
148
|
+
|
|
149
|
+
- name: Notify registry
|
|
150
|
+
if: success()
|
|
151
|
+
env:
|
|
152
|
+
REGISTRY_UPDATE_TOKEN: ${{ secrets.REGISTRY_UPDATE_TOKEN }}
|
|
153
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
154
|
+
run: |
|
|
155
|
+
python build.py notify-registry \
|
|
156
|
+
--package "${{ env.PACKAGE_NAME }}" \
|
|
157
|
+
--version "${{ needs.validate.outputs.version }}" \
|
|
158
|
+
--tag "${{ needs.validate.outputs.tag-name }}" \
|
|
159
|
+
--repository "${{ github.repository }}" \
|
|
160
|
+
--server-url "${{ github.server_url }}"
|
|
161
|
+
|
|
162
|
+
- name: Create success summary
|
|
163
|
+
run: |
|
|
164
|
+
python build.py summary \
|
|
165
|
+
--package "${{ env.PACKAGE_NAME }}" \
|
|
166
|
+
--version "${{ needs.validate.outputs.version }}" \
|
|
167
|
+
--tag "${{ needs.validate.outputs.tag-name }}" \
|
|
168
|
+
--repository "${{ github.repository }}" \
|
|
169
|
+
--server-url "${{ github.server_url }}"
|
|
170
|
+
|
|
171
|
+
# Publish to PyPI via Trusted Publishing (OIDC). No stored tokens.
|
|
172
|
+
# Runs on every v*.*.* tag push, or a manual run with publish_pypi=pypi.
|
|
173
|
+
# PyPI pending publisher: workflow publish-wheel.yml, environment pypi.
|
|
174
|
+
publish-pypi:
|
|
175
|
+
needs: [validate, build-wheel]
|
|
176
|
+
if: github.event_name == 'push' || github.event.inputs.publish_pypi == 'pypi'
|
|
177
|
+
runs-on: ubuntu-latest
|
|
178
|
+
environment:
|
|
179
|
+
name: pypi
|
|
180
|
+
url: https://pypi.org/project/nodetool-mlx/
|
|
181
|
+
permissions:
|
|
182
|
+
id-token: write # required for OIDC trusted publishing
|
|
183
|
+
steps:
|
|
184
|
+
- name: Checkout code
|
|
185
|
+
uses: actions/checkout@v6
|
|
186
|
+
with:
|
|
187
|
+
ref: ${{ needs.validate.outputs.tag-name }}
|
|
188
|
+
|
|
189
|
+
- name: Install uv
|
|
190
|
+
uses: astral-sh/setup-uv@v5
|
|
191
|
+
with:
|
|
192
|
+
python-version: "3.11"
|
|
193
|
+
|
|
194
|
+
- name: Build sdist + wheel
|
|
195
|
+
run: uv build
|
|
196
|
+
|
|
197
|
+
- name: Validate distributions
|
|
198
|
+
run: uvx twine check dist/*
|
|
199
|
+
|
|
200
|
+
- name: Publish to PyPI
|
|
201
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
202
|
+
|
|
203
|
+
# Manual-only TestPyPI dry run (publish_pypi=testpypi).
|
|
204
|
+
publish-testpypi:
|
|
205
|
+
needs: [validate, build-wheel]
|
|
206
|
+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.publish_pypi == 'testpypi'
|
|
207
|
+
runs-on: ubuntu-latest
|
|
208
|
+
environment:
|
|
209
|
+
name: testpypi
|
|
210
|
+
url: https://test.pypi.org/project/nodetool-mlx/
|
|
211
|
+
permissions:
|
|
212
|
+
id-token: write
|
|
213
|
+
steps:
|
|
214
|
+
- name: Checkout code
|
|
215
|
+
uses: actions/checkout@v6
|
|
216
|
+
with:
|
|
217
|
+
ref: ${{ needs.validate.outputs.tag-name }}
|
|
218
|
+
|
|
219
|
+
- name: Install uv
|
|
220
|
+
uses: astral-sh/setup-uv@v5
|
|
221
|
+
with:
|
|
222
|
+
python-version: "3.11"
|
|
223
|
+
|
|
224
|
+
- name: Build sdist + wheel
|
|
225
|
+
run: uv build
|
|
226
|
+
|
|
227
|
+
- name: Publish to TestPyPI
|
|
228
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
229
|
+
with:
|
|
230
|
+
repository-url: https://test.pypi.org/legacy/
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
__pycache__
|
|
2
|
+
*.pyc
|
|
3
|
+
*.pyo
|
|
4
|
+
*.dmypy.json
|
|
5
|
+
*.jar
|
|
6
|
+
.mypy_cache
|
|
7
|
+
*.egg-info
|
|
8
|
+
*.egg
|
|
9
|
+
*.pth
|
|
10
|
+
*.torchscript
|
|
11
|
+
*.ckpt
|
|
12
|
+
*.gguf
|
|
13
|
+
*.pt
|
|
14
|
+
*.pth
|
|
15
|
+
*.safetensors
|
|
16
|
+
build/
|
|
17
|
+
dist/
|
|
18
|
+
electron/apps/build/
|
|
19
|
+
electron/dist/
|
|
20
|
+
electron/dist-web/
|
|
21
|
+
electron/dist-electron/
|
|
22
|
+
# Temporary build files
|
|
23
|
+
.tmp/
|
|
24
|
+
__notebooks/
|
|
25
|
+
package/
|
|
26
|
+
postgres_data/
|
|
27
|
+
.ipynb_checkpoints
|
|
28
|
+
.huggingface
|
|
29
|
+
|
|
30
|
+
.bin
|
|
31
|
+
.vite
|
|
32
|
+
.venv
|
|
33
|
+
node_modules
|
|
34
|
+
docs.chromadb
|
|
35
|
+
|
|
36
|
+
# Cache
|
|
37
|
+
.cache
|
|
38
|
+
.eslintcache
|
|
39
|
+
|
|
40
|
+
# Testing
|
|
41
|
+
/coverage
|
|
42
|
+
*.lcov
|
|
43
|
+
|
|
44
|
+
# Environment variables
|
|
45
|
+
*.override.env
|
|
46
|
+
|
|
47
|
+
# macOS
|
|
48
|
+
# https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
|
|
49
|
+
.DS_Store
|
|
50
|
+
|
|
51
|
+
.env
|
|
52
|
+
cert.pem
|
|
53
|
+
key.pem
|
|
54
|
+
.aider*
|
|
55
|
+
|
|
56
|
+
.codegpt
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: nodetool-mlx
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Apple Silicon MLX nodes for Nodetool
|
|
5
|
+
Author-email: Matthias Georgi <matti.georgi@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: huggingface-hub>=0.24.6
|
|
8
|
+
Requires-Dist: mflux>=0.18.1
|
|
9
|
+
Requires-Dist: mlx-audio>=0.4.4
|
|
10
|
+
Requires-Dist: mlx-lm>=0.31.3
|
|
11
|
+
Requires-Dist: mlx-vlm>=0.4.4
|
|
12
|
+
Requires-Dist: mlx-whisper>=0.4.3
|
|
13
|
+
Requires-Dist: mlx>=0.30
|
|
14
|
+
Requires-Dist: nodetool-core>=0.7.0
|
|
15
|
+
Requires-Dist: numba>=0.62.1
|
|
16
|
+
Requires-Dist: numpy>=1.26
|
|
17
|
+
Requires-Dist: sentencepiece>=0.2
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: black>=24.10.0; extra == 'dev'
|
|
20
|
+
Requires-Dist: mypy>=1.9.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest-asyncio>=0.23.5; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: ruff>=0.3.4; extra == 'dev'
|
|
25
|
+
Provides-Extra: stable
|
|
26
|
+
Requires-Dist: nodetool-core==0.7.0; extra == 'stable'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# nodetool-mlx
|
|
30
|
+
|
|
31
|
+
[](https://github.com/nodetool-ai/nodetool-mlx/actions/workflows/ci.yml)
|
|
32
|
+
|
|
33
|
+
High-performance MLX-native nodes for [Nodetool](https://github.com/nodetool-ai/nodetool) on Apple Silicon. This package wraps the community MLX implementations of Whisper, Kokoro/Sesame TTS, MFlux FLUX.1 image generation, and Stability AI's Stable Audio 3 so you can run state-of-the-art audio and vision workflows locally on macOS.
|
|
34
|
+
|
|
35
|
+
## Why nodetool-mlx?
|
|
36
|
+
|
|
37
|
+
- **Local-first** – keep data on-device by running speech, TTS, and image models without cloud calls
|
|
38
|
+
- **Optimised for Apple Silicon** – uses MLX kernels and quantized checkpoints to achieve strong throughput on M-series chips
|
|
39
|
+
- **Drop-in nodes** – integrates seamlessly with the Nodetool graph editor and `nodetool-core` runtime
|
|
40
|
+
|
|
41
|
+
## Provided Nodes
|
|
42
|
+
|
|
43
|
+
All nodes live under `src/nodetool/nodes/mlx`. Audio nodes wrap the
|
|
44
|
+
[`mlx-audio`](https://github.com/Blaizzy/mlx-audio) library.
|
|
45
|
+
|
|
46
|
+
### Text-to-Speech (`mlx.text_to_speech`)
|
|
47
|
+
|
|
48
|
+
- `KokoroTTS` – fast multilingual TTS with 54 voice presets
|
|
49
|
+
- `SesameTTS` – CSM voice cloning from a reference clip
|
|
50
|
+
- `SparkTTS` – controllable speed / pitch / gender presets
|
|
51
|
+
- `Qwen3TTS` – multilingual TTS with speaker voices and voice design
|
|
52
|
+
- `KittenTTS` – compact, edge-friendly English voices
|
|
53
|
+
- `DiaTTS` – dialogue TTS with `[S1]` / `[S2]` speaker tags
|
|
54
|
+
- `OuteTTS` – efficient multilingual TTS with optional cloning
|
|
55
|
+
- `OmniVoiceTTS` – zero-shot multilingual (646+ languages)
|
|
56
|
+
- `MeloTTS` – lightweight VITS2 English accents
|
|
57
|
+
- `VoxtralTTS` – Mistral's multilingual TTS with voice presets
|
|
58
|
+
- `ChatterboxTTS` – expressive TTS with exaggeration control and cloning
|
|
59
|
+
- `HiggsAudioTTS` – conversational TTS with zero-shot cloning
|
|
60
|
+
- `LongCatAudioTTS` – diffusion TTS with zero-shot cloning
|
|
61
|
+
- `MLXTextToSpeech` – generic node that runs any `mlx-audio` TTS repo id
|
|
62
|
+
|
|
63
|
+
### Speech-to-Text (`mlx.automatic_speech_recognition`, `mlx.speech_to_text`)
|
|
64
|
+
|
|
65
|
+
- `Whisper` – MLX Whisper transcription with optional word timestamps
|
|
66
|
+
- `Parakeet` – NVIDIA Parakeet high-accuracy multilingual ASR
|
|
67
|
+
- `Qwen3ASR` – Alibaba's multilingual ASR with long-form chunking
|
|
68
|
+
- `Qwen3ForcedAligner` – word-level timestamp alignment for a known transcript
|
|
69
|
+
- `MLXSpeechToText` – generic node that runs any `mlx-audio` STT repo id
|
|
70
|
+
|
|
71
|
+
### Speech Enhancement (`mlx.speech_enhancement`)
|
|
72
|
+
|
|
73
|
+
- `DeepFilterNet` – real-time noise suppression (v1/v2/v3) at 48 kHz
|
|
74
|
+
- `MossFormer2` – high-quality 48 kHz speech enhancement
|
|
75
|
+
|
|
76
|
+
### Image (`mlx.text_to_image`, `mlx.image_to_image`)
|
|
77
|
+
|
|
78
|
+
- `MFlux` and the `MFlux*` family – FLUX.1 / Qwen-Image / Z-Image / FIBO generation
|
|
79
|
+
and editing via the MFlux project (supports quantized models)
|
|
80
|
+
|
|
81
|
+
### Image-to-Text (`mlx.image_to_text`)
|
|
82
|
+
|
|
83
|
+
- `MLXVisionLanguage` – image captioning, visual Q&A, and OCR via MLX vision-language models (Qwen3-VL, Gemma 4)
|
|
84
|
+
|
|
85
|
+
### Text-to-Audio (`mlx.text_to_audio`)
|
|
86
|
+
|
|
87
|
+
- `StableAudio3` – text-to-audio music & sound effects with [Stable Audio 3](https://github.com/Stability-AI/stable-audio-3) (44.1 kHz stereo)
|
|
88
|
+
- `StableAudio3AudioToAudio` – prompt-guided variations of an input clip
|
|
89
|
+
- `StableAudio3Inpaint` – regenerate a time range inside an audio clip
|
|
90
|
+
|
|
91
|
+
### Text-to-Music (`mlx.text_to_music`)
|
|
92
|
+
|
|
93
|
+
- `ACEStepMusicGeneration` – local text-to-music generation with [ACE-Step 1.5](https://github.com/ace-step/ACE-Step-1.5) (prompt + lyrics → full songs)
|
|
94
|
+
- `ACEStepSongPlanner` – use the ACE-Step 5Hz language model to turn an idea into a caption, lyrics and musical metadata
|
|
95
|
+
|
|
96
|
+
### Text (`mlx.text_generation`)
|
|
97
|
+
|
|
98
|
+
- `TextGeneration` – local LLM text generation via `mlx-lm`
|
|
99
|
+
|
|
100
|
+
### Stable Audio 3
|
|
101
|
+
|
|
102
|
+
The Stable Audio 3 nodes run Stability AI's optimized MLX implementation (no PyTorch at
|
|
103
|
+
runtime), vendored under `nodetool.mlx.stable_audio_3` (MIT licensed — see that folder's
|
|
104
|
+
`LICENSE` and `NOTICE.md`). Three DiT variants are available via the **model** field:
|
|
105
|
+
|
|
106
|
+
- `sm-music` (50M) – fast music generation
|
|
107
|
+
- `sm-sfx` (50M) – sound effects
|
|
108
|
+
- `medium` (1.4B) – higher-fidelity music
|
|
109
|
+
|
|
110
|
+
Weights are pulled on demand from the Hugging Face repo
|
|
111
|
+
[`stabilityai/stable-audio-3-optimized`](https://huggingface.co/stabilityai/stable-audio-3-optimized)
|
|
112
|
+
(only the `MLX/*` files) and cached locally; you can also pre-download them from the
|
|
113
|
+
Models Manager.
|
|
114
|
+
|
|
115
|
+
### ACE-Step 1.5 (music generation)
|
|
116
|
+
|
|
117
|
+
The ACE-Step nodes wrap the official [ACE-Step 1.5](https://github.com/ace-step/ACE-Step-1.5)
|
|
118
|
+
project, which uses MLX for the diffusion transformer, VAE and language model on
|
|
119
|
+
Apple Silicon. ACE-Step 1.5 is **not** distributed on PyPI (the `ace-step` package
|
|
120
|
+
there is the older 1.0 release), so it must be installed separately:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git clone https://github.com/ace-step/ACE-Step-1.5.git
|
|
124
|
+
cd ACE-Step-1.5
|
|
125
|
+
uv sync # installs the macOS/MLX dependencies
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Install it into the same environment as `nodetool-mlx`. If the package is missing,
|
|
129
|
+
the nodes raise a clear error pointing back to the repository.
|
|
130
|
+
|
|
131
|
+
Checkpoints are downloaded automatically from HuggingFace on first use into
|
|
132
|
+
`~/.cache/nodetool/acestep/checkpoints` (override with the `ACESTEP_CHECKPOINTS_DIR`
|
|
133
|
+
environment variable). The main bundle `ACE-Step/Ace-Step1.5` includes the VAE, the
|
|
134
|
+
turbo DiT and the 1.7B planner LM; additional DiT and LM checkpoints are listed as
|
|
135
|
+
recommended models on each node.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## Requirements
|
|
139
|
+
|
|
140
|
+
- macOS 14+ on Apple Silicon (MLX currently supports Apple hardware only)
|
|
141
|
+
- Python 3.11
|
|
142
|
+
- [nodetool-core](https://github.com/nodetool-ai/nodetool-core) v0.6.0+
|
|
143
|
+
- Required MLX checkpoints managed via the Nodetool Models Manager (see [_Managing Models_](#managing-models))
|
|
144
|
+
|
|
145
|
+
## Installation
|
|
146
|
+
|
|
147
|
+
### From the Nodetool UI
|
|
148
|
+
|
|
149
|
+
1. Open Nodetool → **Tools ▸ Packages**
|
|
150
|
+
2. Install the `nodetool-mlx` pack from the package registry
|
|
151
|
+
3. Nodetool will handle dependencies and expose the MLX nodes in the graph editor once installed
|
|
152
|
+
|
|
153
|
+
### From source (development)
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
git clone https://github.com/nodetool-ai/nodetool-mlx.git
|
|
157
|
+
cd nodetool-mlx
|
|
158
|
+
uv pip install -e .
|
|
159
|
+
uv pip install -r requirements-dev.txt
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
If you prefer Poetry or pip, install the project the same way—just ensure dependencies are resolved against Python 3.11.
|
|
163
|
+
|
|
164
|
+
## Managing Models
|
|
165
|
+
|
|
166
|
+
All MLX nodes rely on locally cached checkpoints. The recommended way to download and update them is through the **Models Manager** built into Nodetool:
|
|
167
|
+
|
|
168
|
+
1. Open Nodetool → **Menu ▸ Models**
|
|
169
|
+
2. Select the `mlx` tab to view the recommended checkpoints for each node
|
|
170
|
+
3. Click **Download** for the models you plan to use; Nodetool stores them in the Hugging Face cache automatically
|
|
171
|
+
4. The UI will keep track of model availability and prompt you when updates are available
|
|
172
|
+
|
|
173
|
+
Advanced users can still seed the Hugging Face cache manually, but using the UI integration ensures consistent paths and avoids missing-model errors in workflows.
|
|
174
|
+
|
|
175
|
+
## Usage
|
|
176
|
+
|
|
177
|
+
1. Install `nodetool-core` and this package in the same environment
|
|
178
|
+
2. Run `nodetool-pkg scan --write --enrich` to generate package metadata
|
|
179
|
+
3. Build workflows in the Nodetool UI using the `mlx` nodes
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
Run tests and lint checks before submitting PRs:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
pytest -q
|
|
187
|
+
ruff check .
|
|
188
|
+
black --check .
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Most of the suite is written to run on any platform: the MLX runtimes are
|
|
192
|
+
imported lazily and the node logic is exercised against mocks. The handful of
|
|
193
|
+
tests that need `mflux` or `mlx-audio` skip themselves when those Apple Silicon
|
|
194
|
+
packages are unavailable, so a Linux run reports skips rather than failures.
|
|
195
|
+
|
|
196
|
+
If you change a node's `get_recommended_models()`, regenerate the committed
|
|
197
|
+
package metadata:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
nodetool-pkg scan --write --enrich
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`tests/test_package_metadata.py` fails when the two drift apart — the Nodetool
|
|
204
|
+
UI reads that file to populate the model picker, so a stale entry becomes a
|
|
205
|
+
model users cannot select or a download offer for a repository that no longer
|
|
206
|
+
exists.
|
|
207
|
+
|
|
208
|
+
### Continuous integration
|
|
209
|
+
|
|
210
|
+
`.github/workflows/ci.yml` runs on every pull request:
|
|
211
|
+
|
|
212
|
+
| Job | Runner | What it covers |
|
|
213
|
+
| --- | --- | --- |
|
|
214
|
+
| Lint and format | ubuntu | `ruff check .` and `black --check .` |
|
|
215
|
+
| Test (linux) | ubuntu, Python 3.11 + 3.12 | the platform-independent suite, installed with `--no-deps` |
|
|
216
|
+
| Test (macOS) | macos-14 (Apple Silicon) | the full suite against the real MLX stack |
|
|
217
|
+
| Build wheel | ubuntu | `python -m build` plus `twine check` |
|
|
218
|
+
|
|
219
|
+
Please open issues or pull requests for bug fixes, new MLX models, or performance improvements. Contributions are welcome!
|