Buckets:

glennmatlin's picture
download
raw
8.56 kB
#!/usr/bin/env bash
set -euo pipefail
# EK-FAC attribution driver for the pinned Bergson (v0.9.0).
#
# Replaces the earlier scaffold that called a non-existent `bergson ekfac`
# subcommand. The pinned Bergson exposes the EK-FAC pieces as separate
# stages, so this driver chains them with the real CLI:
#
# A. bergson build -> raw gradient indices for value and query data
# B. bergson hessian -> KFAC covariances + eigenvalue correction (EK-FAC factors)
# C. apply_hessian -> inverse-Hessian-vector product (IVHP) preconditioned grads
# D. (hand-off) -> existing TrackStar dot-score over IVHP query grads
#
# Stage D reuses the unchanged TrackStar scoring path, so this driver owns
# only the EK-FAC-specific work (A-C). The follow-on command is printed at
# the end.
#
# Usage:
# bash scripts/ekfac.sh \
# --model allenai/Olmo-3-1025-7B \
# --value-data /path/to/value.jsonl \
# --query-data /path/to/query.jsonl \
# --output-dir ~/scratch/ekfac/olmo7b \
# --gpus 8
MODEL="allenai/Olmo-3-1025-7B"
VALUE_DATA=""
QUERY_DATA=""
OUTPUT_DIR=""
PROMPT_COLUMN="text"
COMPLETION_COLUMN=""
PROJECTION_DIM=16
PRECISION="fp32"
HESSIAN_DTYPE="bf16"
TOKEN_BATCH=4096
LAMBDA_DAMP=0.1
GPUS=1
EV_CORRECTION=true
IVHP_SIDE="query"
PYTHONEXEC=""
DRY_RUN=false
while [ $# -gt 0 ]; do
case "$1" in
--model) MODEL="$2"; shift 2 ;;
--value-data) VALUE_DATA="$2"; shift 2 ;;
--query-data) QUERY_DATA="$2"; shift 2 ;;
--output-dir) OUTPUT_DIR="$2"; shift 2 ;;
--prompt-column) PROMPT_COLUMN="$2"; shift 2 ;;
--completion-column) COMPLETION_COLUMN="$2"; shift 2 ;;
--projection-dim) PROJECTION_DIM="$2"; shift 2 ;;
--precision) PRECISION="$2"; shift 2 ;;
--hessian-dtype) HESSIAN_DTYPE="$2"; shift 2 ;;
--token-batch) TOKEN_BATCH="$2"; shift 2 ;;
--lambda-damp) LAMBDA_DAMP="$2"; shift 2 ;;
--gpus) GPUS="$2"; shift 2 ;;
--ev-correction) EV_CORRECTION="$2"; shift 2 ;;
--ivhp-side) IVHP_SIDE="$2"; shift 2 ;;
--python) PYTHONEXEC="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
*) echo "Unknown option: $1" >&2; exit 1 ;;
esac
done
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
PYTHONEXEC="${PYTHONEXEC:-$REPO_DIR/.venv/bin/python}"
for required in MODEL VALUE_DATA QUERY_DATA OUTPUT_DIR; do
if [ -z "${!required}" ]; then
echo "ERROR: --${required,,} is required" >&2
exit 1
fi
done
case "$IVHP_SIDE" in
query | value) ;;
*) echo "ERROR: --ivhp-side must be query or value" >&2; exit 1 ;;
esac
# Each gradient index is nested one level under a wrapper directory. The
# TrackStar scorer's --build-dir/--query-build-dir expect a parent whose
# children are the leaf indices (discover_shard_indices iterates children),
# so the leaves cannot sit directly under the run directory.
VALUE_DIR="$OUTPUT_DIR/value_index"
VALUE_GRADS="$VALUE_DIR/shard_0000"
QUERY_DIR="$OUTPUT_DIR/query_index"
QUERY_GRADS="$QUERY_DIR/q_0000"
HESSIAN_RUN="$OUTPUT_DIR/hessian"
HESSIAN_FACTORS="$HESSIAN_RUN/kfac"
IVHP_DIR="$OUTPUT_DIR/${IVHP_SIDE}_ivhp_index"
IVHP_OUT="$IVHP_DIR/ivhp_0000"
# Projected EK-FAC (corpus-scale). apply_hessian needs a FULL-dimensional input
# index (projection_dim 0) because it multiplies by the full-dim factors, then
# projects its OUTPUT into the other side's projection_dim subspace via
# --projection_config_path. So the IVHP side is built full-dim and the other side
# stays projected; stage D dot-scores both in the same projection_dim space.
if [ "$IVHP_SIDE" = query ]; then
VALUE_PROJ="$PROJECTION_DIM"
QUERY_PROJ=0
PROJ_CONFIG_DIR="$VALUE_GRADS"
else
VALUE_PROJ=0
QUERY_PROJ="$PROJECTION_DIM"
PROJ_CONFIG_DIR="$QUERY_GRADS"
fi
FSDP_ARGS=()
if [ "$GPUS" -gt 1 ]; then
FSDP_ARGS=(--fsdp)
fi
EV_ARGS=()
if [ "$EV_CORRECTION" = true ]; then
EV_ARGS=(--ev_correction)
fi
QUERY_PROMPT_ARGS=(--prompt_column "$PROMPT_COLUMN")
if [ -n "$COMPLETION_COLUMN" ]; then
QUERY_PROMPT_ARGS+=(--completion_column "$COMPLETION_COLUMN")
fi
echo "=============================================="
echo " EK-FAC attribution"
echo "=============================================="
echo "Model: $MODEL"
echo "Value data: $VALUE_DATA"
echo "Query data: $QUERY_DATA"
echo "Output: $OUTPUT_DIR"
echo "ProjDim: $PROJECTION_DIM (projected EK-FAC: IVHP input full-dim, output projected)"
echo "Precision: $PRECISION (hessian $HESSIAN_DTYPE)"
echo "GPUs: $GPUS"
echo "EV corr: $EV_CORRECTION IVHP side: $IVHP_SIDE lambda damp: $LAMBDA_DAMP"
echo "Python: $PYTHONEXEC"
echo "=============================================="
run() {
echo "+ $*"
if [ "$DRY_RUN" = false ]; then
"$@"
fi
}
mkdir -p "$OUTPUT_DIR" "$VALUE_DIR" "$QUERY_DIR" "$IVHP_DIR"
# Stage A: raw gradient indices for value and query data.
run "$PYTHONEXEC" -m bergson build "$VALUE_GRADS" \
--model "$MODEL" \
--dataset json --data_args "data_files=$VALUE_DATA" \
--prompt_column "$PROMPT_COLUMN" \
--projection_dim "$VALUE_PROJ" \
--precision "$PRECISION" \
--token_batch_size "$TOKEN_BATCH" \
--skip_preconditioners \
--unit_normalize --truncation --overwrite \
${FSDP_ARGS[@]+"${FSDP_ARGS[@]}"}
run "$PYTHONEXEC" -m bergson build "$QUERY_GRADS" \
--model "$MODEL" \
--dataset json --data_args "data_files=$QUERY_DATA" \
"${QUERY_PROMPT_ARGS[@]}" \
--projection_dim "$QUERY_PROJ" \
--precision "$PRECISION" \
--token_batch_size "$TOKEN_BATCH" \
--skip_preconditioners \
--unit_normalize --truncation --overwrite \
${FSDP_ARGS[@]+"${FSDP_ARGS[@]}"}
# Stage B: EK-FAC factors from the value (training) distribution.
run "$PYTHONEXEC" -m bergson hessian "$HESSIAN_RUN" \
--model "$MODEL" \
--dataset json --data_args "data_files=$VALUE_DATA" \
--prompt_column "$PROMPT_COLUMN" \
--method kfac \
--hessian_dtype "$HESSIAN_DTYPE" \
--projection_dim "$PROJECTION_DIM" \
--precision "$PRECISION" \
--token_batch_size "$TOKEN_BATCH" \
--truncation \
--overwrite \
${EV_ARGS[@]+"${EV_ARGS[@]}"} \
${FSDP_ARGS[@]+"${FSDP_ARGS[@]}"}
# Stage C: apply IVHP to the chosen gradient side.
if [ "$IVHP_SIDE" = query ]; then
IVHP_GRADS="$QUERY_GRADS"
else
IVHP_GRADS="$VALUE_GRADS"
fi
APPLY_CMD=("$PYTHONEXEC")
if [ "$GPUS" -gt 1 ]; then
APPLY_CMD=("$PYTHONEXEC" -m torch.distributed.run --nproc_per_node="$GPUS")
fi
run "${APPLY_CMD[@]}" -m bergson.hessians.apply_hessian \
--hessian_method_path "$HESSIAN_FACTORS" \
--gradient_path "$IVHP_GRADS" \
--run_path "$IVHP_OUT" \
--projection_config_path "$PROJ_CONFIG_DIR" \
--lambda_damp_factor "$LAMBDA_DAMP"
# The projected apply_hessian output omits the processor files the dot-score
# loader (GradientProcessor.load) needs. Copy them from PROJ_CONFIG_DIR (same
# projection) so the IVHP index is loadable for stage D, until bergson's
# apply_hessian writes a self-contained index.
# NOTE: this reuses PROJ_CONFIG_DIR's unit-normalizer, which rescales per-query
# score magnitudes (rankings preserved). The correct long-term fix is an
# identity processor on the IVHP index.
echo "+ copy processor files from $PROJ_CONFIG_DIR into $IVHP_OUT"
if [ "$DRY_RUN" = false ]; then
cp "$PROJ_CONFIG_DIR/processor_config.json" \
"$PROJ_CONFIG_DIR/normalizers.pth" \
"$PROJ_CONFIG_DIR/preconditioners.pth" \
"$PROJ_CONFIG_DIR/preconditioners_eigen.pth" \
"$PROJ_CONFIG_DIR/preprocess_config.json" \
"$PROJ_CONFIG_DIR/total_processed.pt" \
"$IVHP_OUT/"
fi
if [ "$IVHP_SIDE" = query ]; then
SCORE_BUILD_DIR="$VALUE_DIR"
SCORE_QUERY_DIR="$IVHP_DIR"
else
SCORE_BUILD_DIR="$IVHP_DIR"
SCORE_QUERY_DIR="$QUERY_DIR"
fi
echo "=============================================="
echo " EK-FAC stages A-C complete"
echo "=============================================="
echo "Value index: $VALUE_GRADS"
echo "Query index: $QUERY_GRADS"
echo "EK-FAC factors: $HESSIAN_FACTORS"
echo "IVHP ($IVHP_SIDE): $IVHP_OUT"
echo ""
echo "Stage D (score) reuses the existing TrackStar dot-score path. The"
echo "--build-dir and --query-build-dir below are wrapper directories whose"
echo "children are the leaf indices, which is what the scorer expects:"
echo " data-attribution-trackstar-dot-score \\"
echo " --build-dir $SCORE_BUILD_DIR \\"
echo " --query-build-dir $SCORE_QUERY_DIR \\"
echo " --variant base --run-id ekfac_\$(date -u +%Y%m%dT%H%M%SZ)"

Xet Storage Details

Size:
8.56 kB
·
Xet hash:
87e7c1ecb398e3b95d9ed043d7bc7351cd6bc4eeae462742989f2e780f8ab6f6

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.