|
1 | 1 | #!/usr/bin/env bash |
2 | 2 | # transcribefile_smoke.sh — regression smoke for the transcribefile APE. |
3 | 3 | # |
4 | | -# Two layers: |
| 4 | +# Three layers: |
5 | 5 | # 1. Model-free probes — always run. Catches CLI argv / WAV-loader / |
6 | 6 | # help-text regressions without needing any model artifact. |
7 | 7 | # 2. Parakeet end-to-end — gated on TRANSCRIBEFILE_PARAKEET_GGUF. Skipped |
8 | 8 | # (with a warning, not a failure) when the model isn't available, so |
9 | 9 | # `make check` stays green on machines without the model. |
| 10 | +# 3. Metal backend — needs layer 2's model plus macOS on Apple Silicon |
| 11 | +# with a registered Metal device; skipped elsewhere. Asserts that |
| 12 | +# --backend metal selects an MTL device and that the Metal and CPU |
| 13 | +# transcripts match exactly. |
10 | 14 | # |
11 | 15 | # Usage: |
12 | 16 | # tests/transcribefile_smoke.sh <path-to-transcribefile-binary> |
13 | 17 | # |
14 | 18 | # Env: |
15 | 19 | # TRANSCRIBEFILE_PARAKEET_GGUF Path to a parakeet GGUF; if unset or the |
16 | | -# file is missing, layer 2 is skipped. |
| 20 | +# file is missing, layers 2 and 3 are skipped. |
17 | 21 |
|
18 | 22 | set -euo pipefail |
19 | 23 |
|
@@ -74,3 +78,43 @@ echo "$out" | grep -q 'realtime:' || fail "parakeet output missing 'realtime:' l |
74 | 78 | echo "$out" | grep -qi 'country' || fail "parakeet transcription missing 'country'" |
75 | 79 | realtime=$(echo "$out" | grep -oE 'realtime:[[:space:]]+[0-9]+x' | head -1 || true) |
76 | 80 | pass "parakeet transcribes jfk.wav (${realtime:-realtime: ?})" |
| 81 | + |
| 82 | +echo "[smoke] layer 3 — metal backend" |
| 83 | + |
| 84 | +# Metal is macOS/Apple-Silicon only. Elsewhere (and on macs where the |
| 85 | +# runtime dylib build isn't possible, e.g. no Xcode CLT) the contract is |
| 86 | +# graceful degradation to CPU, so absence of a metal device is a SKIP, |
| 87 | +# not a failure. |
| 88 | +if [ "$(uname -s)" != "Darwin" ] || [ "$(uname -m)" != "arm64" ]; then |
| 89 | + echo " SKIP metal: requires macOS on Apple Silicon" >&2 |
| 90 | + exit 0 |
| 91 | +fi |
| 92 | +if ! "$APE" --list-devices 2>/dev/null | grep -q 'kind=metal'; then |
| 93 | + echo " SKIP metal: no metal device registered" \ |
| 94 | + "(Xcode command-line tools missing?)" >&2 |
| 95 | + exit 0 |
| 96 | +fi |
| 97 | + |
| 98 | +# Explicit --backend metal must actually select an MTL device and produce |
| 99 | +# the same transcript TEXT as the CPU backend. Only the text: fields are |
| 100 | +# compared: word timestamps and token probabilities may legitimately |
| 101 | +# differ across backends — different kernels and accumulation orders give |
| 102 | +# slightly different logits, so near-tie decisions (a timestamp on a |
| 103 | +# frame boundary, a probability rounding) can flip, and quantized models |
| 104 | +# amplify this. The decoded text is expected to be stable. |
| 105 | +mtl=$("$APE" --backend metal -q -m "$MODEL" "$SAMPLE" 2>/dev/null) \ |
| 106 | + || fail "metal run exited non-zero" |
| 107 | +echo "$mtl" | grep -qE 'backend:[[:space:]]+MTL' || fail "metal run did not select an MTL device" |
| 108 | +echo "$mtl" | grep -qi 'country' || fail "metal transcription missing 'country'" |
| 109 | +pass "parakeet transcribes jfk.wav on metal" |
| 110 | + |
| 111 | +cpu=$("$APE" --backend cpu -q -m "$MODEL" "$SAMPLE" 2>/dev/null) \ |
| 112 | + || fail "cpu run exited non-zero" |
| 113 | +mtl_text=$(echo "$mtl" | grep '^text:' || true) |
| 114 | +cpu_text=$(echo "$cpu" | grep '^text:' || true) |
| 115 | +[ -n "$mtl_text" ] || fail "metal output has no text: line" |
| 116 | +if [ "$mtl_text" != "$cpu_text" ]; then |
| 117 | + printf 'metal:\n%s\ncpu:\n%s\n' "$mtl_text" "$cpu_text" >&2 |
| 118 | + fail "metal and cpu transcript text differs" |
| 119 | +fi |
| 120 | +pass "metal and cpu transcripts match" |
0 commit comments