Skip to content
Merged
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
9 changes: 6 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ test/
# Student CLAP training (not needed in production)
student_clap/

# macOS and Linux standalone app: source trees (PyInstaller spec / nfpm config,
# vendored redis/pg binaries, assets) and build artifacts. None of it is used by
# the Linux container, so keep it out of the image.
# Native standalone app (macOS/Linux/Windows): the per-platform source trees
# (vendored redis/pg binaries, assets, nfpm config, runtime launchers), the shared
# PyInstaller spec + build tooling, and build artifacts. None of it is used by the
# Linux container, so keep it out of the image.
macos/
linux/
windows/
AudioMuse-AI.spec
scripts/standalone/
build/
dist/

Expand Down
97 changes: 4 additions & 93 deletions .github/workflows/build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#
# The small native build inputs (redis-server, the unaccent/pg_trgm contrib
# modules) are built from source in this workflow (linux/vendor/*) rather than
# committed, then baked into the bundle by linux/AudioMuse-AI.spec.
# committed, then baked into the bundle by the shared AudioMuse-AI.spec.
#
# The ~5 GB of models are NOT in git. This workflow assembles ./model from the
# same GitHub releases the Dockerfile/macOS build use, INCLUDING the HuggingFace
Expand Down Expand Up @@ -146,105 +146,16 @@ jobs:
- name: Assemble ./model (mirrors the Dockerfile/macOS models stage)
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir -p model

echo "==> musicnn + CLAP text models (from ${MODEL_RELEASE})"
gh release download "$MODEL_RELEASE" -R "$GITHUB_REPOSITORY" -D model --clobber \
-p musicnn_embedding.onnx \
-p musicnn_prediction.onnx \
-p clap_text_model.onnx

echo "==> DCLAP audio model (from ${DCLAP_RELEASE} in the -DCLAP repo)"
gh release download "$DCLAP_RELEASE" -R NeptuneHub/AudioMuse-AI-DCLAP -D model --clobber \
-p model_epoch_36.onnx \
-p model_epoch_36.onnx.data

echo "==> HuggingFace cache (roberta/bert/bart) -- HF_HOME points at model/huggingface"
tmp_hf="$(mktemp -d)"
gh release download "$MODEL_RELEASE" -R "$GITHUB_REPOSITORY" -D "$tmp_hf" --clobber \
-p huggingface_models.tar.gz
mkdir -p model/huggingface
tar -xzf "$tmp_hf/huggingface_models.tar.gz" -C model/huggingface
rm -rf "$tmp_hf"

echo "==> Trim HF cache to just the roberta-base tokenizer (~1.4 GB saved)"
# The app's ONLY runtime HF dependency is the roberta-base *tokenizer*
# (tasks/clap_analyzer.py: AutoTokenizer.from_pretrained("roberta-base")).
# bert-base-uncased and bart-base are never loaded by the app, and a
# tokenizer does not need model weights. Dropping them keeps the release
# assets under the 2 GB GitHub limit without removing any model the app
# uses. (This prunes only this bundle copy -- the shared release tarball
# and the Docker build are unaffected.)
hf="model/huggingface/hub"
rm -rf "$hf/models--bert-base-uncased" "$hf/models--facebook--bart-base"
rb="$hf/models--roberta-base"
if [ -d "$rb" ]; then
find "$rb/blobs" -type f -size +10M -delete
find "$rb/snapshots" \( -name "model.safetensors" -o -name "pytorch_model.bin" \) -delete
du -sh "$rb"
fi

echo "==> lyrics bundles (whisper / silero / gte)"
tmp="$(mktemp -d)"
gh release download "$MODEL_RELEASE" -R "$GITHUB_REPOSITORY" -D "$tmp" --clobber \
-p lyrics_model_whisper.tar.gz \
-p lyrics_model_silero_vad.tar.gz \
-p lyrics_model_gte_vnni.tar.gz
for t in lyrics_model_whisper lyrics_model_silero_vad lyrics_model_gte_vnni; do
tar -xzf "$tmp/$t.tar.gz" -C model
done
rm -rf "$tmp"
run: python3 scripts/standalone/assemble_model.py

- name: Verify the assembled model/ is complete
run: |
set -euo pipefail
required=(
model/musicnn_embedding.onnx
model/musicnn_prediction.onnx
model/clap_text_model.onnx
model/model_epoch_36.onnx
model/model_epoch_36.onnx.data
model/huggingface/hub/models--roberta-base/snapshots
model/silero_vad.onnx
model/gte-multilingual-base-int8.onnx
model/whisper-small-onnx/encoder_model.onnx
model/whisper-small-onnx/decoder_model_merged.onnx
model/gte-multilingual-base/tokenizer.json
)
missing=0
for f in "${required[@]}"; do
# Flag a file that is missing OR a zero-byte/truncated download. The
# size test only applies to regular files (directory entries in the
# list pass on existence alone).
if [ ! -e "$f" ] || { [ -f "$f" ] && [ ! -s "$f" ]; }; then
echo "::error::Missing or empty: $f"; missing=1
fi
done
if [ -z "$(find model/huggingface/hub/models--roberta-base -name tokenizer.json -print -quit)" ]; then
echo "::error::roberta-base tokenizer.json missing after HF-cache prune"; missing=1
fi
[ "$missing" -eq 0 ] || { echo "::error::Refusing to build an incomplete bundle."; exit 1; }
du -sh model
run: python3 scripts/standalone/assemble_model.py --verify

- name: Build the packages (.deb + .rpm)
run: |
set -euo pipefail
source .venv-linux/bin/activate
# Derive a package-manager-safe version. On a tag push github.ref_name
# is `vX.Y.Z` -> `X.Y.Z`; on a PR it is `<num>/merge` (and on dispatch a
# branch name), neither of which is a valid deb/rpm version, so use a
# placeholder for non-tag builds.
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then
PKG_VERSION="${GITHUB_REF_NAME#v}"
else
PKG_VERSION="0.0.0"
fi
PKG_VERSION="$PKG_VERSION" bash linux/build.sh
env:
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_REF_TYPE: ${{ github.ref_type }}
python scripts/standalone/build.py --platform linux

- name: Upload .deb as a workflow artifact
uses: actions/upload-artifact@v4
Expand Down
81 changes: 3 additions & 78 deletions .github/workflows/build-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,85 +104,10 @@ jobs:
- name: Assemble ./model (mirrors the Dockerfile models stage)
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir -p model

echo "==> musicnn + CLAP text models (from ${MODEL_RELEASE})"
gh release download "$MODEL_RELEASE" -R "$GITHUB_REPOSITORY" -D model --clobber \
-p musicnn_embedding.onnx \
-p musicnn_prediction.onnx \
-p clap_text_model.onnx

echo "==> DCLAP audio model (from ${DCLAP_RELEASE} in the -DCLAP repo)"
gh release download "$DCLAP_RELEASE" -R NeptuneHub/AudioMuse-AI-DCLAP -D model --clobber \
-p model_epoch_36.onnx \
-p model_epoch_36.onnx.data

echo "==> HuggingFace cache (roberta/bert/bart) — HF_HOME points at model/huggingface"
tmp_hf="$(mktemp -d)"
gh release download "$MODEL_RELEASE" -R "$GITHUB_REPOSITORY" -D "$tmp_hf" --clobber \
-p huggingface_models.tar.gz
mkdir -p model/huggingface
tar -xzf "$tmp_hf/huggingface_models.tar.gz" -C model/huggingface
rm -rf "$tmp_hf"

echo "==> Trim HF cache to just the roberta-base tokenizer (~1.4 GB saved)"
# The macOS app's ONLY runtime HF dependency is the roberta-base *tokenizer*
# (tasks/clap_analyzer.py: AutoTokenizer.from_pretrained("roberta-base")).
# bert-base-uncased and bart-base are never loaded by the app, and a tokenizer
# does not need model weights. Dropping them keeps the release zip under the
# 2 GB GitHub release-asset limit without removing any model the app uses.
# Note: this prunes only the macOS bundle copy — the shared release tarball
# and the Docker build are unaffected.
hf="model/huggingface/hub"
rm -rf "$hf/models--bert-base-uncased" "$hf/models--facebook--bart-base"
rb="$hf/models--roberta-base"
if [ -d "$rb" ]; then
# Drop the ~476 MB weight blob; AutoTokenizer reads only the tiny
# tokenizer.json/vocab.json/merges.txt/config files (all < 2 MB).
find "$rb/blobs" -type f -size +10M -delete
find "$rb/snapshots" \( -name "model.safetensors" -o -name "pytorch_model.bin" \) -delete
du -sh "$rb"
fi

echo "==> lyrics bundles (whisper / silero / gte) — downloaded then extracted into ./model"
tmp="$(mktemp -d)"
gh release download "$MODEL_RELEASE" -R "$GITHUB_REPOSITORY" -D "$tmp" --clobber \
-p lyrics_model_whisper.tar.gz \
-p lyrics_model_silero_vad.tar.gz \
-p lyrics_model_gte_vnni.tar.gz
for t in lyrics_model_whisper lyrics_model_silero_vad lyrics_model_gte_vnni; do
tar -xzf "$tmp/$t.tar.gz" -C model
done
rm -rf "$tmp"
run: python3 scripts/standalone/assemble_model.py

- name: Verify the assembled model/ is complete
run: |
set -euo pipefail
required=(
model/musicnn_embedding.onnx
model/musicnn_prediction.onnx
model/clap_text_model.onnx
model/model_epoch_36.onnx
model/model_epoch_36.onnx.data
model/huggingface/hub/models--roberta-base/snapshots
model/silero_vad.onnx
model/gte-multilingual-base-int8.onnx
model/whisper-small-onnx/encoder_model.onnx
model/whisper-small-onnx/decoder_model_merged.onnx
model/gte-multilingual-base/tokenizer.json
)
missing=0
for f in "${required[@]}"; do
if [ ! -e "$f" ]; then echo "::error::Missing or empty: $f"; missing=1; fi
done
# The roberta tokenizer files must survive the HF-cache prune above.
if [ -z "$(find model/huggingface/hub/models--roberta-base -name tokenizer.json -print -quit)" ]; then
echo "::error::roberta-base tokenizer.json missing after HF-cache prune"; missing=1
fi
[ "$missing" -eq 0 ] || { echo "::error::Refusing to build an incomplete bundle."; exit 1; }
du -sh model
run: python3 scripts/standalone/assemble_model.py --verify

- name: Install Python dependencies
run: |
Expand All @@ -196,7 +121,7 @@ jobs:
run: |
set -euo pipefail
source .venv-macos/bin/activate
bash macos/build.sh
python scripts/standalone/build.py --platform macos

- name: Upload zip as a workflow artifact
uses: actions/upload-artifact@v4
Expand Down
88 changes: 4 additions & 84 deletions .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# The small native build inputs (redis-server.exe, the unaccent/pg_trgm contrib
# modules) are built or downloaded in this workflow, then baked into the bundle
# by windows/AudioMuse-AI.spec.
# by the shared AudioMuse-AI.spec.
#
# The ~5 GB of models are NOT in git. This workflow assembles ./model from the
# same GitHub releases the Dockerfile/macOS/Linux builds use, INCLUDING the
Expand Down Expand Up @@ -103,95 +103,15 @@ jobs:
shell: powershell
env:
GH_TOKEN: ${{ github.token }}
run: |
New-Item -ItemType Directory -Force -Path model | Out-Null
$modelRelease = "$env:MODEL_RELEASE"
$dclapRelease = "$env:DCLAP_RELEASE"

Write-Host "==> musicnn + CLAP text models (from $modelRelease)"
gh release download $modelRelease -R $env:GITHUB_REPOSITORY -D model --clobber `
-p musicnn_embedding.onnx `
-p musicnn_prediction.onnx `
-p clap_text_model.onnx

Write-Host "==> DCLAP audio model (from $dclapRelease in the -DCLAP repo)"
gh release download $dclapRelease -R NeptuneHub/AudioMuse-AI-DCLAP -D model --clobber `
-p model_epoch_36.onnx `
-p model_epoch_36.onnx.data

Write-Host "==> HuggingFace cache (roberta/bert/bart)"
$tmp_hf = Join-Path $env:RUNNER_TEMP "hf_models"
New-Item -ItemType Directory -Force -Path $tmp_hf | Out-Null
gh release download $modelRelease -R $env:GITHUB_REPOSITORY -D $tmp_hf --clobber `
-p huggingface_models.tar.gz
New-Item -ItemType Directory -Force -Path model\huggingface | Out-Null
tar -xzf "$tmp_hf\huggingface_models.tar.gz" -C model\huggingface
if ($LASTEXITCODE -ne 0) { Write-Error "tar failed extracting huggingface models"; exit 1 }
Remove-Item -Recurse -Force $tmp_hf

Write-Host "==> Trim HF cache to just the roberta-base tokenizer (~1.4 GB saved)"
$hf = "model\huggingface\hub"
if (Test-Path "$hf\models--bert-base-uncased") { Remove-Item -Recurse -Force "$hf\models--bert-base-uncased" }
if (Test-Path "$hf\models--facebook--bart-base") { Remove-Item -Recurse -Force "$hf\models--facebook--bart-base" }
$rb = "$hf\models--roberta-base"
if (Test-Path $rb) {
Get-ChildItem -Recurse -File "$rb\blobs" | Where-Object { $_.Length -gt 10MB } | Remove-Item -Force
Get-ChildItem -Recurse "$rb\snapshots" -Include "model.safetensors","pytorch_model.bin" | Remove-Item -Force
}

Write-Host "==> lyrics bundles (whisper / silero / gte)"
$tmp = Join-Path $env:RUNNER_TEMP "lyrics_models"
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
gh release download $modelRelease -R $env:GITHUB_REPOSITORY -D $tmp --clobber `
-p lyrics_model_whisper.tar.gz `
-p lyrics_model_silero_vad.tar.gz `
-p lyrics_model_gte_vnni.tar.gz
foreach ($t in @("lyrics_model_whisper", "lyrics_model_silero_vad", "lyrics_model_gte_vnni")) {
tar -xzf "$tmp\$t.tar.gz" -C model
if ($LASTEXITCODE -ne 0) { Write-Error "tar failed extracting $t"; exit 1 }
}
Remove-Item -Recurse -Force $tmp
run: python scripts/standalone/assemble_model.py

- name: Verify the assembled model/ is complete
shell: powershell
run: |
$required = @(
"model\musicnn_embedding.onnx",
"model\musicnn_prediction.onnx",
"model\clap_text_model.onnx",
"model\model_epoch_36.onnx",
"model\model_epoch_36.onnx.data",
"model\huggingface\hub\models--roberta-base\snapshots",
"model\silero_vad.onnx",
"model\gte-multilingual-base-int8.onnx",
"model\whisper-small-onnx\encoder_model.onnx",
"model\whisper-small-onnx\decoder_model_merged.onnx",
"model\gte-multilingual-base\tokenizer.json"
)
$missing = 0
foreach ($f in $required) {
if (-not (Test-Path $f)) {
Write-Error "Missing or empty: $f"
$missing = 1
}
}
if ($missing -ne 0) { Write-Error "Refusing to build an incomplete bundle."; exit 1 }
Write-Host "Model assembly verified."
run: python scripts/standalone/assemble_model.py --verify

- name: Build the bundle
shell: powershell
run: |
.venv-windows\Scripts\activate
if ($env:GITHUB_REF_TYPE -eq "tag") {
$ver = $env:GITHUB_REF_NAME -replace '^v', ''
} else {
$ver = "0.0.0"
}
$env:PKG_VERSION = $ver
cmd /c windows\build.bat
env:
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_REF_TYPE: ${{ github.ref_type }}
run: .venv-windows\Scripts\python scripts\standalone\build.py --platform windows

- name: Upload zip as a workflow artifact
uses: actions/upload-artifact@v4
Expand Down
Loading
Loading