Files
elizaos--eliza/packages/training/scripts/eval_loop.sh
T
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

188 lines
5.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# eval_loop.sh — every interval, score every checkpoint that has been
# pulled by `checkpoint_sync_loop.sh` but not yet scored, and append one
# line per scored step to `_progress.jsonl` (the file the UI plots).
#
# A checkpoint dir is "evaluated" iff it contains a sibling `_eval.json`
# file written by eval_checkpoint.py. We never re-evaluate; if you want
# to force a rescore, delete that file.
#
# Args:
# --run-name <name> (required) — must match RUN_NAME used by
# train_vast.sh / checkpoint_sync_loop.sh.
# --registry-key <k> (required) — passed straight through to
# eval_checkpoint.py so the result JSON
# records which model line this came from.
# --interval-seconds <n> default 600 (10 min). Time between sweeps.
# --val-jsonl <path> default training/data/smoke/val.jsonl.
# --max-examples <n> default 50, per-bucket cap for native_tool_call_bench.
#
# On SIGTERM/SIGINT we exit cleanly between sweeps.
set -euo pipefail
RUN_NAME=""
REGISTRY_KEY=""
INTERVAL_SECONDS=600
VAL_JSONL=""
MAX_EXAMPLES=50
usage() {
cat <<'EOF'
Usage: eval_loop.sh --run-name <name> --registry-key <k>
[--interval-seconds N] [--val-jsonl PATH] [--max-examples N]
Scans training/checkpoints/<run-name>/ for any checkpoint-* dirs (and
final/) that don't yet have a sibling _eval.json, runs eval_checkpoint.py
on each, and appends the result to training/checkpoints/<run-name>/_progress.jsonl.
Required:
--run-name <name>
--registry-key <k> gemma4-e2b / gemma4-e4b / gemma4-12b / gemma4-31b
Optional:
--interval-seconds <n> default 600 (10 min)
--val-jsonl <path> default training/data/smoke/val.jsonl
--max-examples <n> default 50 per bucket
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--run-name) RUN_NAME="${2:-}"; shift 2 ;;
--registry-key) REGISTRY_KEY="${2:-}"; shift 2 ;;
--interval-seconds) INTERVAL_SECONDS="${2:-}"; shift 2 ;;
--val-jsonl) VAL_JSONL="${2:-}"; shift 2 ;;
--max-examples) MAX_EXAMPLES="${2:-}"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*)
echo "error: unknown arg $1" >&2
usage >&2
exit 2
;;
esac
done
if [[ -z "$RUN_NAME" || -z "$REGISTRY_KEY" ]]; then
echo "error: --run-name and --registry-key are required" >&2
usage >&2
exit 2
fi
if ! [[ "$INTERVAL_SECONDS" =~ ^[0-9]+$ ]] || [[ "$INTERVAL_SECONDS" -lt 1 ]]; then
echo "error: --interval-seconds must be a positive integer" >&2
exit 2
fi
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LOCAL_CKPT_DIR="$ROOT/checkpoints/$RUN_NAME"
PROGRESS_LOG="$LOCAL_CKPT_DIR/_progress.jsonl"
LOG_FILE="$HOME/.eliza/checkpoint-eval.log"
LOG_MAX_BYTES=$((10 * 1024 * 1024))
if [[ -z "$VAL_JSONL" ]]; then
VAL_JSONL="$ROOT/data/smoke/val.jsonl"
fi
mkdir -p "$LOCAL_CKPT_DIR" "$(dirname "$LOG_FILE")"
log() {
local ts
ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
local line="[$ts] [eval $RUN_NAME] $*"
echo "$line"
if [[ -f "$LOG_FILE" ]]; then
local size
size="$(stat -c%s "$LOG_FILE" 2>/dev/null || stat -f%z "$LOG_FILE" 2>/dev/null || echo 0)"
if [[ "$size" -ge "$LOG_MAX_BYTES" ]]; then
mv -f "$LOG_FILE" "$LOG_FILE.1"
fi
fi
echo "$line" >> "$LOG_FILE"
}
SHOULD_EXIT=0
on_signal() {
log "received signal — will exit after current sweep"
SHOULD_EXIT=1
}
trap on_signal TERM INT
evaluate_one() {
local ckpt_dir="$1"
local marker="$ckpt_dir/_eval.json"
if [[ -f "$marker" ]]; then
return 0
fi
log "evaluate: $ckpt_dir"
if python3 "$ROOT/scripts/eval_checkpoint.py" \
--checkpoint "$ckpt_dir" \
--registry-key "$REGISTRY_KEY" \
--val-jsonl "$VAL_JSONL" \
--max-examples "$MAX_EXAMPLES" \
--out "$marker" >> "$LOG_FILE" 2>&1; then
# Append the single-line result to _progress.jsonl. We re-read the
# marker (rather than letting eval_checkpoint.py write JSONL directly)
# so the on-disk schema stays append-only and we can verify the marker
# is well-formed before committing it to the curve.
if python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$marker" >/dev/null 2>&1; then
python3 -c "import json,sys; print(json.dumps(json.load(open(sys.argv[1]))))" "$marker" \
>> "$PROGRESS_LOG"
log "evaluate: $ckpt_dir done"
else
log "evaluate: $ckpt_dir produced unparsable _eval.json — skipping append"
rm -f "$marker"
fi
else
log "evaluate: $ckpt_dir FAILED — see log for traceback"
fi
}
log "start: run=$RUN_NAME registry=$REGISTRY_KEY interval=${INTERVAL_SECONDS}s val=$VAL_JSONL max_examples=$MAX_EXAMPLES"
while true; do
if [[ "$SHOULD_EXIT" -eq 1 ]]; then
log "exit: signal received"
exit 0
fi
if [[ -d "$LOCAL_CKPT_DIR" ]]; then
# Sort by step number ascending so the progress.jsonl ends up roughly
# ordered by training step (the UI sorts on read regardless, but this
# makes `tail -f _progress.jsonl` watchable).
while IFS= read -r ckpt; do
[[ -z "$ckpt" ]] && continue
[[ "$SHOULD_EXIT" -eq 1 ]] && break
evaluate_one "$ckpt"
done < <(
{
find "$LOCAL_CKPT_DIR" -mindepth 1 -maxdepth 1 -type d -name 'checkpoint-*' \
| awk -F'checkpoint-' '{print $2"\t"$0}' \
| sort -n \
| cut -f2-
# `final/` last — eval_checkpoint.py promotes it to max+1.
if [[ -d "$LOCAL_CKPT_DIR/final" ]]; then
echo "$LOCAL_CKPT_DIR/final"
fi
}
)
else
log "sweep: $LOCAL_CKPT_DIR doesn't exist yet — waiting for first pull"
fi
if [[ "$SHOULD_EXIT" -eq 1 ]]; then
log "exit: signal received"
exit 0
fi
remaining="$INTERVAL_SECONDS"
while [[ "$remaining" -gt 0 ]]; do
sleep 1
remaining=$((remaining - 1))
if [[ "$SHOULD_EXIT" -eq 1 ]]; then
log "exit: signal received during sleep"
exit 0
fi
done
done