Files
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

214 lines
9.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# packages/inference/verify/gpu/_common.sh
#
# Shared bash helpers for the per-card verification scripts
# (verify_3090.sh / verify_4090.sh / verify_5090.sh / verify_h200.sh).
#
# Each per-card script:
# 1. Sources this file.
# 2. Sets PROFILE_ID, EXPECTED_SHORT_NAME, EXPECTED_CUDA_ARCH.
# 3. Calls `run_gpu_verify "$@"`.
#
# The shared logic:
# - Validates nvidia-smi reports the expected GPU.
# - Reads the per-card YAML (via `node -e` — no model load).
# - Calls `make cuda-verify` in the parent dir (kernel-fixture parity).
# - Optionally runs `llama-bench` against a smoke model (only when
# ELIZA_GPU_BENCH=1 — defaults off, so the script is safe to run
# on a Mac for `--help` / dry-run checks).
# - Emits JSON evidence to evidence/gpu/<gpu>/<timestamp>.json.
#
# **DOES NOT LOAD ANY MODEL > 1.7B by default**. The bench step requires
# an explicit opt-in (`ELIZA_GPU_BENCH=1`) plus an `ELIZA_MTP_SMOKE_MODEL`
# path. The script aborts early when neither is set in `--bench` mode.
#
# Usage:
# ./verify_4090.sh --help
# ./verify_4090.sh --dry-run # validates env, no work
# ELIZA_GPU_BENCH=1 ELIZA_MTP_SMOKE_MODEL=/path/to/9b.gguf \
# ./verify_4090.sh
set -euo pipefail
# Resolved by the caller after sourcing.
: "${PROFILE_ID:?PROFILE_ID must be set before sourcing _common.sh}"
: "${EXPECTED_SHORT_NAME:?EXPECTED_SHORT_NAME must be set}"
: "${EXPECTED_CUDA_ARCH:?EXPECTED_CUDA_ARCH must be set}"
GPU_VERIFY_USAGE() {
cat <<USAGE
Usage:
${0##*/} [--help] [--dry-run]
Validates the host GPU matches the expected card (${EXPECTED_SHORT_NAME})
and that the buun-llama-cpp fork has the per-profile kernels available.
Reads per-bundle deployment recommendations from:
packages/shared/src/local-inference-gpu/profiles/${PROFILE_ID}.yaml
Environment:
ELIZA_GPU_BENCH=1 enable the llama-bench TPS smoke
(requires ELIZA_MTP_SMOKE_MODEL)
ELIZA_MTP_SMOKE_MODEL=<path> GGUF to bench (must be the smoke_bundle
declared in the YAML, or a smaller tier)
ELIZA_MTP_LLAMA_DIR=<path> llama.cpp build root
(default: ~/.cache/eliza-mtp/eliza-llama-cpp)
ELIZA_GPU_REPORT_DIR=<path> evidence output dir
(default: evidence/gpu/${PROFILE_ID})
Exit codes:
0 pass
2 GPU mismatch (refused to run; will not silently downgrade)
3 toolchain missing (no nvidia-smi / no nvcc)
4 YAML profile parse failure
5 bench failed or TPS outside tolerance
USAGE
}
case "${1:-}" in
-h|--help)
GPU_VERIFY_USAGE; exit 0 ;;
esac
DRY_RUN=0
if [[ "${1:-}" == "--dry-run" ]]; then
DRY_RUN=1
fi
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$HERE" rev-parse --show-toplevel 2>/dev/null || echo "$HERE/../../../../..")"
VERIFY_DIR="$(cd "$HERE/.." && pwd)"
YAML_PATH="$REPO_ROOT/packages/shared/src/local-inference-gpu/profiles/${PROFILE_ID}.yaml"
REPORT_DIR="${ELIZA_GPU_REPORT_DIR:-$VERIFY_DIR/evidence/gpu/$PROFILE_ID}"
TIMESTAMP="$(date -u '+%Y%m%dT%H%M%SZ')"
REPORT_PATH="$REPORT_DIR/${TIMESTAMP}.json"
abort() {
local code="$1"; shift
echo "[verify-${PROFILE_ID}] $*" >&2
exit "$code"
}
# ---- pre-flight ----------------------------------------------------------
[[ -f "$YAML_PATH" ]] || abort 4 "missing profile YAML: $YAML_PATH"
if (( DRY_RUN == 1 )); then
echo "[verify-${PROFILE_ID}] --dry-run mode: validating YAML + reading expected kernels…"
fi
# Parse the YAML once. We resolve `yaml` from the shared package's
# node_modules so the script works regardless of caller cwd. If that
# fails the YAML may still be malformed — fatal in either case.
SHARED_PKG_DIR="$REPO_ROOT/packages/shared"
NODE_SCRIPT='import { readFileSync } from "node:fs";
import YAML from "yaml";
const yaml = YAML.parse(readFileSync(process.env.YAML_PATH, "utf8"));
const cmake = yaml.verify_recipe.cmake_flags.join("|");
const kernels = yaml.verify_recipe.expected_kernels.join(",");
process.stdout.write([
yaml.gpu_id,
yaml.verify_recipe.cuda_arch,
cmake,
kernels,
yaml.verify_recipe.smoke_bundle,
yaml.verify_recipe.tolerance_pct,
].join(" "));'
PARSED_LINE="$( (cd "$SHARED_PKG_DIR" && YAML_PATH="$YAML_PATH" node --input-type=module -e "$NODE_SCRIPT") 2>/dev/null || true )"
read -r PARSED_GPU_ID PARSED_ARCH PARSED_CMAKE_FLAGS PARSED_KERNELS PARSED_SMOKE_BUNDLE PARSED_TOLERANCE <<< "$PARSED_LINE"
[[ -n "${PARSED_GPU_ID:-}" ]] || abort 4 "failed to parse $YAML_PATH (yaml dep missing? run 'bun install' in packages/shared)"
[[ "$PARSED_GPU_ID" == "$PROFILE_ID" ]] || abort 4 "YAML gpu_id mismatch: $PARSED_GPU_ID vs $PROFILE_ID"
[[ "$PARSED_ARCH" == "$EXPECTED_CUDA_ARCH" ]] || abort 4 "YAML cuda_arch mismatch: $PARSED_ARCH vs $EXPECTED_CUDA_ARCH"
echo "[verify-${PROFILE_ID}] yaml ok: arch=$PARSED_ARCH smoke=$PARSED_SMOKE_BUNDLE tol=${PARSED_TOLERANCE}%"
echo "[verify-${PROFILE_ID}] expected kernels: $PARSED_KERNELS"
if (( DRY_RUN == 1 )); then
echo "[verify-${PROFILE_ID}] dry-run complete; not running nvidia-smi / make cuda-verify"
exit 0
fi
# ---- nvidia-smi GPU match -----------------------------------------------
command -v nvidia-smi >/dev/null 2>&1 || abort 3 "nvidia-smi missing — verification cannot proceed (try on a Linux host with an NVIDIA driver)"
GPU_QUERY="$(nvidia-smi --query-gpu=name,memory.total,compute_cap --format=csv,noheader 2>/dev/null || true)"
[[ -n "$GPU_QUERY" ]] || abort 3 "nvidia-smi returned no GPUs"
GPU_NAME="$(printf '%s\n' "$GPU_QUERY" | head -1 | awk -F', ' '{print $1}')"
GPU_MEMORY="$(printf '%s\n' "$GPU_QUERY" | head -1 | awk -F', ' '{print $2}')"
GPU_COMPUTE="$(printf '%s\n' "$GPU_QUERY" | head -1 | awk -F', ' '{print $3}')"
case "$EXPECTED_SHORT_NAME" in
"3090") [[ "$GPU_NAME" == *"RTX 3090"* ]] || abort 2 "expected RTX 3090; nvidia-smi reports: $GPU_NAME" ;;
"4090") [[ "$GPU_NAME" == *"RTX 4090"* ]] || abort 2 "expected RTX 4090; nvidia-smi reports: $GPU_NAME" ;;
"5090") [[ "$GPU_NAME" == *"RTX 5090"* ]] || abort 2 "expected RTX 5090; nvidia-smi reports: $GPU_NAME" ;;
"H200") [[ "$GPU_NAME" == *"H200"* ]] || abort 2 "expected H200; nvidia-smi reports: $GPU_NAME" ;;
*) abort 2 "unknown EXPECTED_SHORT_NAME=$EXPECTED_SHORT_NAME" ;;
esac
echo "[verify-${PROFILE_ID}] gpu match ok: $GPU_NAME ($GPU_MEMORY, compute_cap=$GPU_COMPUTE)"
# ---- kernel-fixture parity (cheap, no model load) ----------------------
command -v nvcc >/dev/null 2>&1 || abort 3 "nvcc missing — install CUDA toolkit ${EXPECTED_CUDA_ARCH}-class"
echo "[verify-${PROFILE_ID}] running 'make cuda-verify'…"
(cd "$VERIFY_DIR" && make cuda-verify)
# ---- optional bench (gated; expensive) ---------------------------------
BENCH_STATUS="skipped"
BENCH_DECODE_TPS=""
BENCH_PREFILL_TPS=""
if [[ "${ELIZA_GPU_BENCH:-0}" == "1" ]]; then
SMOKE_MODEL="${ELIZA_MTP_SMOKE_MODEL:-}"
[[ -n "$SMOKE_MODEL" && -f "$SMOKE_MODEL" ]] || abort 5 "ELIZA_GPU_BENCH=1 set but ELIZA_MTP_SMOKE_MODEL is missing/not a file"
LLAMA_DIR="${ELIZA_MTP_LLAMA_DIR:-$HOME/.cache/eliza-mtp/eliza-llama-cpp}"
LLAMA_BENCH="$LLAMA_DIR/build-cuda/bin/llama-bench"
[[ -x "$LLAMA_BENCH" ]] || abort 5 "llama-bench missing at $LLAMA_BENCH (build with: bun run packages/app-core/scripts/build-llama-cpp-mtp.mjs --target linux-x64-cuda)"
echo "[verify-${PROFILE_ID}] llama-bench: $SMOKE_MODEL"
BENCH_OUT="$("$LLAMA_BENCH" -m "$SMOKE_MODEL" -ngl 999 -fa 1 -p 512 -n 128 2>&1 || true)"
echo "$BENCH_OUT"
# llama-bench output ends with markdown tables; extract pp512 / tg128 columns.
BENCH_PREFILL_TPS="$(printf '%s\n' "$BENCH_OUT" | awk '/pp512/ {gsub(/[\t ]+/, " "); print $NF}' | head -1)"
BENCH_DECODE_TPS="$(printf '%s\n' "$BENCH_OUT" | awk '/tg128/ {gsub(/[\t ]+/, " "); print $NF}' | head -1)"
if [[ -n "$BENCH_DECODE_TPS" && -n "$BENCH_PREFILL_TPS" ]]; then
BENCH_STATUS="completed"
else
BENCH_STATUS="parse-failed"
fi
else
echo "[verify-${PROFILE_ID}] bench skipped (set ELIZA_GPU_BENCH=1 + ELIZA_MTP_SMOKE_MODEL to run)"
fi
# ---- evidence JSON ------------------------------------------------------
mkdir -p "$REPORT_DIR"
GPU_NAME_J="$GPU_NAME" \
GPU_MEMORY_J="$GPU_MEMORY" \
GPU_COMPUTE_J="$GPU_COMPUTE" \
PROFILE_ID_J="$PROFILE_ID" \
PARSED_TOLERANCE_J="$PARSED_TOLERANCE" \
PARSED_SMOKE_BUNDLE_J="$PARSED_SMOKE_BUNDLE" \
BENCH_STATUS_J="$BENCH_STATUS" \
BENCH_DECODE_TPS_J="$BENCH_DECODE_TPS" \
BENCH_PREFILL_TPS_J="$BENCH_PREFILL_TPS" \
REPORT_PATH_J="$REPORT_PATH" \
node --input-type=module <<'NODE'
import { writeFileSync } from "node:fs";
const r = {
schemaVersion: 1,
runner: `verify_${process.env.PROFILE_ID_J}.sh`,
startedAt: new Date().toISOString(),
profileId: process.env.PROFILE_ID_J,
smokeBundle: process.env.PARSED_SMOKE_BUNDLE_J,
tolerancePct: Number(process.env.PARSED_TOLERANCE_J),
gpu: {
name: process.env.GPU_NAME_J,
memory: process.env.GPU_MEMORY_J,
computeCap: process.env.GPU_COMPUTE_J,
},
bench: {
status: process.env.BENCH_STATUS_J,
decodeTps: process.env.BENCH_DECODE_TPS_J || null,
prefillTps: process.env.BENCH_PREFILL_TPS_J || null,
},
};
writeFileSync(process.env.REPORT_PATH_J, `${JSON.stringify(r, null, 2)}\n`);
console.log(`[verify-${process.env.PROFILE_ID_J}] evidence: ${process.env.REPORT_PATH_J}`);
NODE
echo "[verify-${PROFILE_ID}] PASS"