name: tmic run run-name: tmic run ${{ inputs.model }} # Create a MIC for one checkpoint, end to end: # run tmic run --mode agent --local-only with a read-only token: plan, fixture, # build, Auto check and a CPU recording; gates are auto-approved. Then # auto_mic.py ready: validated, or only missing hardware this runner lacks. # publish (publish: true, the default) in the mic-publish environment, which only main # can use: measure every declared case on cloud CPU and CUDA, approve NEW # candidates, publish huggingface-mic/-mic and add it to the prototypes # fleet. Runs no model code itself. New contracts only: a model already in a # fleet or on the Hub is refused (reviewed update flow). # After an export it dispatches coverage-space.yml, which refreshes the MIC coverage Space. # mic-impact.yml dispatches it for suggested contracts (matched by run name) and # refreshes its page when a run finishes. # # gh workflow run tmic-run.yml --repo huggingface/transformers-mic -f model=org/name [-f publish=false] # gh workflow run tmic-run.yml --repo huggingface/transformers-mic -f model=org/name -f source_run_id= # publish an earlier draft # [-f contract_name=] when the contract's name is taken in a fleet by another checkpoint # [-f overwrite_unexported=true] replace a huggingface-mic repo published earlier but in no fleet # gh run download --repo huggingface/transformers-mic -n tmic-workspace # or -n tmic-shrink / tmic-publication # # What the run job needs and why (each cost one failed attempt to find): # GH_TOKEN create queries GitHub history through gh # --bill-to HF_HUB_READ_TOKEN cannot bill the huggingface org for the planner, # so the token owner's credits are used ('') # doc-builder + [runtime] the build stage runs the usage.md contract on: workflow_dispatch: inputs: model: required: true type: string source_run_id: description: "Reuse a built workspace from an earlier tmic run (optional)" required: false type: string default: "" publish: description: "Measure CPU/CUDA and publish a new MIC into the prototypes fleet" type: boolean default: true revision: required: false type: string default: "" transformers_ref: required: false type: string default: main contract_name: description: "Fleet name to publish under, when the default collides (e.g. Qwen3_5_VL)" required: false type: string default: "" overwrite_unexported: description: "Overwrite a published huggingface-mic repo that no fleet references" type: boolean default: false permissions: contents: read jobs: run: runs-on: ubuntu-latest timeout-minutes: 120 env: SOURCE_RUN_ID: ${{ inputs.source_run_id }} HF_TOKEN: ${{ secrets.HF_HUB_READ_TOKEN }} GH_TOKEN: ${{ github.token }} HF_HUB_DISABLE_PROGRESS_BARS: "1" PYTHONUNBUFFERED: "1" MODEL: ${{ inputs.model }} REVISION: ${{ inputs.revision }} TRANSFORMERS_REF: ${{ inputs.transformers_ref }} steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.11" - name: Free disk run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL - name: Install run: | git clone --filter=blob:none https://github.com/huggingface/transformers.git "$RUNNER_TEMP/transformers" git -C "$RUNNER_TEMP/transformers" checkout -q "$TRANSFORMERS_REF" python -m pip install --quiet --upgrade pip python -m pip install --quiet --index-url https://download.pytorch.org/whl/cpu torch torchvision python -m pip install --quiet -e ".[runtime]" -e "$RUNNER_TEMP/transformers" jsonschema \ "git+https://github.com/huggingface/doc-builder@c69e96c087165ba49b1788e0c3464654dd60253c" - name: Reuse a built workspace if: inputs.source_run_id != '' run: | python - <<'PYCODE' import json, os, subprocess run_id = os.environ["SOURCE_RUN_ID"] assert run_id.isdecimal(), "source_run_id must be numeric" info = json.loads(subprocess.check_output(["gh", "api", f"repos/{os.environ['GITHUB_REPOSITORY']}/actions/runs/{run_id}"])) assert info["path"] == ".github/workflows/tmic-run.yml" and info["head_branch"] == "main" assert info["event"] == "workflow_dispatch" and info["status"] == "completed" subprocess.run(["gh", "run", "download", run_id, "--repo", os.environ["GITHUB_REPOSITORY"], "-n", "tmic-workspace", "-D", "."], check=True) PYCODE - name: tmic run if: inputs.source_run_id == '' run: | set +e args=("$MODEL" --mode agent --local-only --bill-to "" --baseline-execution local --out work/run --transformers-checkout "$RUNNER_TEMP/transformers") [ -n "$REVISION" ] && args+=(--revision "$REVISION") tmic run "${args[@]}" > result.json; code=$? for _ in $(seq 12); do python - <<'PY' || break import json, sys q = json.load(open("result.json")).get("pending_question") if not q or q["kind"] == "retry": sys.exit(1) print("approving", q["kind"], file=sys.stderr) json.dump({"question_id": q["question_id"], "answer": "approve", "reason": "tmic-run workflow, local-only"}, open("answer.json", "w")) PY tmic run "${args[@]}" --answer answer.json > result.json; code=$? done for f in work/run/.mic/automation/logs/*.log; do echo "::group::$f"; tail -150 "$f"; echo "::endgroup::"; done python -c "import json;r=json.load(open('result.json'));print(json.dumps({k:r.get(k) for k in ('status','stage','pending_question')},indent=1)[:4000])" status=$(python -c "import json;print(json.load(open('result.json')).get('status'))") echo "### tmic run $MODEL: $status (exit $code)" >> "$GITHUB_STEP_SUMMARY" - name: Ready for cloud measurement? # pipefail: without it tee's success would hide a failed gate, and publish would run. run: | set -o pipefail python .github/scripts/auto_mic.py ready --model "$MODEL" | tee -a "$GITHUB_STEP_SUMMARY" - name: Fixture report if: always() run: | python - <<'PY' import glob, json for build in glob.glob("work/run/.mic/artifacts/*/*/build.json"): folder = build.rsplit("/", 1)[0] b, c = json.load(open(build)), json.load(open(folder + "/config.json")) text = c.get("text_config", c) print("fixture", folder, "parameters", b["parameters"], "weights", b.get("weights"), "missing", b["missing_parameters"]) print("layers", text.get("num_hidden_layers"), {k: v for k, v in text.items() if isinstance(v, list) and len(v) == text.get("num_hidden_layers")}) print("scalars", {k: text.get(k) for k in ("first_k_dense_replace", "index_topk", "n_routed_experts", "num_experts_per_tok") if k in text}) print("gate", json.dumps(b.get("gate"))[:1500]) print("health", json.dumps(b.get("numeric_health"))) PY - name: Shrink page if: always() run: | # tmic shrink builds the checkpoint and the fixture on the meta device (configs only). for build in work/run/.mic/artifacts/*/*/build.json; do [ -f "$build" ] || continue folder=$(dirname "$build") tmic shrink "$folder" --source "$MODEL${REVISION:+@$REVISION}" --html "shrink-$(basename "$(dirname "$folder")").html" || true done ls shrink-*.html 2>/dev/null || echo "no fixture was built" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() with: name: tmic-shrink path: shrink-*.html if-no-files-found: ignore retention-days: 7 - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() with: name: tmic-workspace path: | result.json ready-result.json work/run include-hidden-files: true retention-days: 7 publish: needs: run if: inputs.publish # The write token is an environment secret; the environment only admits main. environment: mic-publish runs-on: ubuntu-latest timeout-minutes: 420 permissions: contents: read actions: write steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with: python-version: "3.11" - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: name: tmic-workspace - run: python -m pip install . - name: Measure CPU and CUDA, validate, publish and add to fleet env: HF_TOKEN: ${{ secrets.MIC_BASELINE_WRITE_TOKEN }} GH_TOKEN: ${{ github.token }} MODEL: ${{ inputs.model }} TRANSFORMERS_REF: ${{ inputs.transformers_ref }} CONTRACT_NAME: ${{ inputs.contract_name }} OVERWRITE: ${{ inputs.overwrite_unexported }} HF_HUB_DISABLE_PROGRESS_BARS: "1" PYTHONUNBUFFERED: "1" run: | test -n "$HF_TOKEN" || { echo "Configure MIC_BASELINE_WRITE_TOKEN in the mic-publish environment"; exit 1; } args=(--model "$MODEL" --transformers-ref "$TRANSFORMERS_REF") if [ -n "$CONTRACT_NAME" ]; then [[ "$CONTRACT_NAME" =~ ^[A-Za-z][A-Za-z0-9_.-]{0,63}$ ]] || { echo "invalid contract_name"; exit 1; } args+=(--contract-name "$CONTRACT_NAME") fi [ "$OVERWRITE" = true ] && args+=(--overwrite-unexported) python .github/scripts/auto_mic.py publish "${args[@]}" - name: Refresh the coverage Space # Queued behind any refresh in progress (coverage-space.yml's concurrency group). env: GH_TOKEN: ${{ github.token }} run: gh workflow run coverage-space.yml --repo "$GITHUB_REPOSITORY" --ref main - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 if: always() with: name: tmic-publication path: publish-result.json if-no-files-found: ignore retention-days: 30 - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 if: always() with: name: tmic-cloud-workspace path: work include-hidden-files: true retention-days: 7