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
23 changes: 23 additions & 0 deletions .github/actions/setup-light/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Set up a light job
description: >-
Python from config/versions.env and the pipeline's plain requirements, for jobs that only read
Hub metadata and do arithmetic (the targets jobs). The Namespace runner's system Python
refuses pip installs (PEP 668: externally-managed-environment), so these jobs need their own.

runs:
using: composite
steps:
- name: Read versions
id: versions
shell: bash
run: grep -E '^[A-Z_]+=' config/versions.env >>"$GITHUB_OUTPUT"

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ steps.versions.outputs.PYTHON_VERSION }}
cache: pip
cache-dependency-path: requirements/dev.txt

- name: Install
shell: bash
run: python -m pip install --quiet -r requirements/dev.txt
28 changes: 28 additions & 0 deletions .github/actions/setup-modal/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Set up a Modal-driven job
description: >-
The light toolchain for a job whose heavy step runs on Modal (pipeline/remote.py): Python,
the pipeline's plain requirements and the Modal client, no torch. The step itself runs in a
Sandbox sized to it; this job only sends it, waits, and publishes what comes back.

runs:
using: composite
steps:
- name: Read versions
id: versions
shell: bash
run: grep -E '^[A-Z_]+=' config/versions.env >>"$GITHUB_OUTPUT"

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ steps.versions.outputs.PYTHON_VERSION }}
cache: pip
cache-dependency-path: |
requirements/dev.txt
requirements/modal.txt

- name: Install
shell: bash
run: |
python -m pip install -r requirements/dev.txt -r requirements/modal.txt
echo "WORK_DIR=$RUNNER_TEMP/exe-expo-work" >>"$GITHUB_ENV"
mkdir -p "$RUNNER_TEMP/exe-expo-work"
3 changes: 1 addition & 2 deletions .github/workflows/export-mtk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ jobs:
entries: ${{ steps.contexts.outputs.entries }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-light
- id: socs
env:
SOCS: ${{ inputs.socs }}
run: |
if [ -z "$SOCS" ]; then
python3 -m pip install --quiet pyyaml
SOCS=$(python3 -c 'import json, yaml; print(json.dumps(yaml.safe_load(open("config/pipeline.yaml"))["export"]["mtk"]["socs"]))')
fi
echo "socs=$SOCS" >>"$GITHUB_OUTPUT"
Expand All @@ -81,7 +81,6 @@ jobs:
# disagree about whether a window fits. Memory is one prompt's calibration steps;
# disk is every prompt's, since writer_batch_size=1 put the rest in the Arrow cache.
run: |
python3 -m pip install --quiet -r requirements/dev.txt
entries=$(python3 -m pipeline mtk-matrix "$MODEL_ID" --revision "$REVISION" --contexts "$CONTEXTS")
echo "$entries"
echo "entries=$entries" >>"$GITHUB_OUTPUT"
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/export-qnn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ jobs:
contexts: ${{ steps.contexts.outputs.contexts }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-light
- id: socs
env:
SOCS: ${{ inputs.socs }}
run: |
if [ -z "$SOCS" ]; then
python3 -m pip install --quiet pyyaml
SOCS=$(python3 -c 'import json, yaml; print(json.dumps(yaml.safe_load(open("config/pipeline.yaml"))["export"]["qnn"]["socs"]))')
fi
echo "socs=$SOCS" >>"$GITHUB_OUTPUT"
Expand All @@ -59,7 +59,6 @@ jobs:
CONTEXTS: ${{ inputs.contexts }}
# Accepts a JSON list, one number, or a comma-separated list; empty means every tier.
run: |
python3 -m pip install --quiet pyyaml
CONTEXTS=$(python3 - "$CONTEXTS" <<'PY'
import json, sys, yaml
raw = sys.argv[1].strip()
Expand Down
35 changes: 18 additions & 17 deletions .github/workflows/export-vulkan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
entries: ${{ steps.contexts.outputs.entries }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-light
- id: contexts
env:
CONTEXTS: ${{ inputs.contexts }}
Expand All @@ -53,7 +54,6 @@ jobs:
# on the same sizing.host_need_bytes, so the two cannot disagree about a window; one
# no tier can carry is left out here rather than started on a runner it would kill.
run: |
python3 -m pip install --quiet -r requirements/dev.txt
entries=$(python3 -m pipeline export-matrix "$MODEL_ID" --revision "$REVISION" --backend vulkan --contexts "$CONTEXTS")
echo "$entries"
echo "entries=$entries" >>"$GITHUB_OUTPUT"
Expand All @@ -66,40 +66,41 @@ jobs:
fail-fast: false
matrix:
entry: ${{ fromJSON(needs.targets.outputs.entries) }}
# Sized per window by the targets job: the export peak grows with the window squared
# (every attention layer holds a window x window causal mask), so Qwen3-4B needs ~33 GiB
# at 2k and ~108 GiB at 32k. A window no tier in vulkan.runner_tiers can carry is left
# out; since 2026-10-07 that tier is the 15.7 GiB Namespace profile, with no swap. The
# runner has no GPU, so the file gets a structural check (findings 28, 30).
runs-on: ${{ matrix.entry.runner }}
# The export runs on Modal, in a Sandbox with the memory this window needs (the targets
# job's memory_mib: sizing.host_need_bytes plus modal.memory_margin): the peak grows with
# the window squared, from ~5 GiB at 2k to ~134 GiB for Qwen3-4B at 32k. This job only
# sends it, waits, and publishes what comes back. Modal has no GPU either, so the file
# gets a structural check (findings 28, 30).
runs-on: namespace-profile-execupack
timeout-minutes: 350
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
HF_HUB_DISABLE_PROGRESS_BARS: "1"
MODEL_ID: ${{ inputs.model_id }}
REVISION: ${{ inputs.revision }}
CONTEXT: ${{ matrix.entry.context }}
MEMORY_MIB: ${{ matrix.entry.memory_mib }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: ./.github/actions/setup-export
with:
swap-gib: ${{ matrix.entry.swap_gib }}
- uses: ./.github/actions/setup-modal

# Exit 4 means this runner cannot build this window (memory grows with the square of
# the window): recorded as a skip, so the other windows' jobs stand on their own.
# The runner has no GPU: the file gets a structural check, the device benchmarks run it.
- name: Export and check
# Exit 4 means this window cannot be built (the export's own gate): recorded as a skip,
# so the other windows' jobs stand on their own.
- name: Export and check on Modal
run: |
echo "ARTIFACT=vulkan-${MODEL_ID//\//--}-${CONTEXT}" >>"$GITHUB_ENV"
set +e
python -m pipeline export-vulkan "$MODEL_ID" --revision "$REVISION" --context "$CONTEXT" \
--out "$WORK_DIR/out" --work "$WORK_DIR/work"
python -m pipeline modal-run --memory-mib "$MEMORY_MIB" --requirements requirements/export-xnnpack.txt \
--get "$WORK_DIR/out" \
--script 'python -m pipeline export-vulkan "$MODEL_ID" --revision "$REVISION" --context "$CONTEXT" --out "$OUT" --work "$WORK"'
rc=$?
set -e
if [ "$rc" -eq 4 ]; then
echo "SKIPPED=1" >>"$GITHUB_ENV"
echo "::warning title=Window skipped::$MODEL_ID at $CONTEXT tokens cannot be exported on this runner"
echo "::warning title=Window skipped::$MODEL_ID at $CONTEXT tokens cannot be exported"
exit 0
fi
exit "$rc"
Expand Down
Loading