Files
AstrAI/docs/guides/evaluation.md
T
ViperEkura c8b1e40f71 docs: restructure to docs/, add guides and developer docs
- Rename assets/ to docs/, split into guides/ and developer/
- Add get-started.md: installation + 5-step quickstart
- Add guides/evaluation.md: 7 eval scripts with CLI args
- Add guides/distributed.md: DDP/FSDP, gradient accumulation, NCCL
- Add developer/internals.md: loss formulas, RoPE, KV cache math
- Add developer/cuda_kernels.md: build system, benchmarks, file layout
- Fix storage_format doc in preprocessing.md
- Update cross-references in README.md, README-zh-CN.md, Dockerfile
2026-07-30 00:49:04 +08:00

11 KiB

Evaluation

AstrAI provides 7 evaluation scripts in scripts/eval/ covering code generation, knowledge QA, perplexity, summarization, data quality, instruction following, and weight analysis.

Overview

Script Metric Model Invocation External Dataset
evaluate_humaneval.py Code-gen pass@1/10/100 InferenceEngine.generate HF openai/openai_humaneval (auto-download)
evaluate_mmlu.py MCQ accuracy (log-likelihood) Direct model() forward HF cais/mmlu (auto-download)
evaluate_ppl.py Perplexity / token loss Direct model() forward User JSONL
evaluate_rouge.py ROUGE-1/2/L None (pure metric) User JSONL
evaluate_ifd.py Instruction-Following Difficulty Direct model() forward User JSONL
evaluate_ifeval.py Instruction-following constraints InferenceEngine.generate HF google/IFEval (auto-download)
analyze_weights.py SVD effective rank / weight stats None (loads safetensors) Checkpoint dir

Two invocation patterns exist:

  • Generation benchmarks (HumanEval, IFEval): use InferenceEngine to generate responses, then score them.
  • Scoring benchmarks (MMLU, PPL, IFD): call model() directly under torch.inference_mode() for log-likelihood computation.

Common defaults: --param_path defaults to ./params; dtype defaults to bfloat16 on CUDA, float32 on CPU.


HumanEval (Code Generation)

Generates completions for 164 programming problems, executes them against hidden tests, and reports pass@k.

python scripts/eval/evaluate_humaneval.py \
    --param_path ./params \
    --num_samples 20 \
    --batch_size 32 \
    --max_tokens 512 \
    --output results/humaneval.json
Parameter Default Description
--param_path ./params Model directory
--data_path ./humaneval/HumanEval.jsonl HumanEval JSONL (auto-downloaded if missing)
--output None Save results JSON (also writes _completions.json)
--test_only None Test an existing completions JSON (skip generation)
--generate_only False Only generate, skip execution/testing
--num_samples 200 Completions per problem (pass@k needs >= k)
--max_tokens 512 Max generation length
--temperature 0.8 Sampling temperature
--top_p 0.95 Nucleus sampling threshold
--top_k 50 Top-k sampling
--batch_size 32 Generation batch size
--test_workers 8 ProcessPoolExecutor workers for test execution
--test_timeout 3.0 Per-subprocess timeout (seconds)
--problems None Restrict to specific problem indices

Output: stdout prints pass@1, pass@10, pass@100. With --output, writes per-problem results + _summary aggregate and a _completions.json file.

Data: Auto-downloads openai/openai_humaneval from HuggingFace on first run. Each problem has task_id, entry_point, prompt, test.


MMLU (Knowledge QA)

57-subject multiple-choice accuracy via log-likelihood comparison. Supports n-shot few-shot prompting and option permutation.

python scripts/eval/evaluate_mmlu.py \
    --param_path ./params \
    --n_shot 5 \
    --subjects math_algebra history_us \
    --output results/mmlu.json
Parameter Default Description
--param_path ./params Model directory
--data_dir ./mmlu_data MMLU data directory (per-subject CSVs)
--download False Force re-download
--n_shot 5 Few-shot examples (0 = zero-shot)
--subjects all 57 Specific subjects to evaluate
--output None Output JSON path
--split test test or val
--device auto Device (cuda / cpu)
--dtype auto bfloat16 on CUDA, float32 on CPU
--seed 0 Seed for option permutation (0 = enabled, -1 = disabled)

How it works: For each question, builds a prompt with n-shot examples, then scores each choice (A/B/C/D) by computing the summed log-likelihood of the choice token given the context. The choice with the highest log-prob is the prediction.

Output: stdout prints per-subject accuracy and overall. With --output, writes per-subject {accuracy, correct, total} + _overall aggregate.

Data: Auto-downloads cais/mmlu from HuggingFace. Stored as per-subject CSVs in <data_dir>/<split>/ and <data_dir>/dev/ (for few-shot).


Perplexity (PPL)

Token-level negative-log-likelihood and perplexity on arbitrary text data. Supports streaming mode (memory-efficient) and non-streaming mode (exact per-token stats).

python scripts/eval/evaluate_ppl.py \
    --param_path ./params \
    --input_path data.jsonl \
    --output_dir ppl_results/ \
    --batch_size 4 \
    --max_length 2048
Parameter Default Description
--param_path required Model directory
--input_path required Input file, glob, or directory
--output_dir required Output directory for summary.json + token JSONL
--text_key text Key for the text field in input data
--batch_size 4 Batch size
--max_length 2048 Max sequence length (tokens)
--token_level False Store per-token log_probs + token-type analysis
--max_samples None Random subsample per file
--device auto Device
--dtype auto Torch dtype

Input: JSONL or JSON files. Each item must have a field named by --text_key (default text). If --input_path is a directory, recursively collects *.jsonl and *.json.

Output: summary.json with per-file stats (tokens, mean/median loss, perplexity, p50/p90/p95/p99). With --token_level, also writes per-token JSONL with token IDs and log-probs.


ROUGE

ROUGE-1/2/L (precision, recall, F1) for summarization. Self-contained implementation with no external dependencies.

python scripts/eval/evaluate_rouge.py \
    --data_path predictions.jsonl \
    --output results/rouge.json
Parameter Default Description
--data_path required JSONL with reference/candidate per line
--output None Output JSON path

Input: JSONL, one object per line:

{"reference": "Ground truth text", "candidate": "Model output text"}

Output: stdout prints rouge-1, rouge-2, rouge-l each as P/R/F1. With --output, writes JSON with aggregate and per_item scores.

Can also be imported as a library:

from scripts.eval.evaluate_rouge import compute_rouge
scores = compute_rouge(reference, candidate)

IFD (Instruction-Following Difficulty)

Data quality metric: IFD = L_conditional / L_unconditional. Measures how much harder it is to predict a response given its instruction vs. without it. Useful for filtering instruction-tuning data.

python scripts/eval/evaluate_ifd.py \
    --param_path ./params \
    --input_path sft_data.jsonl \
    --output_dir ifd_results/ \
    --format messages \
    --batch_size 8
Parameter Default Description
--param_path required Model directory
--input_path required Input file, glob, or directory
--output_dir required Output directory
--max_len 2048 Max token length
--format plain plain (instruction/response fields) or messages (chat format)
--instr_key instruction Instruction field key (plain format)
--resp_key response Response field key (plain format)
--batch_size 8 Items per model-forward flush
--device auto Device
--dtype auto Torch dtype
--sentinel_text \n Prefix for unconditional pass ("" → bos/pad fallback)
--per_token False Include per-token IFD breakdown
--max_samples None Random subsample per file

How it works: Two forward passes per batch — (1) conditional: packed BFD sequence with context + response, (2) unconditional: response prefixed with a sentinel. IFD = mean_conditional_loss / mean_unconditional_loss. IFD > 1 means the instruction makes the response harder to predict (higher quality data).

Output: Per-file <label>_ifd.jsonl with IFD scores per item. summary.json aggregates per-file stats.


IFEval (Instruction Following)

Google's IFEval benchmark: generates responses and verifies 27 types of constraints (keywords, format, length, case, punctuation, etc.).

python scripts/eval/evaluate_ifeval.py \
    --param_path ./params \
    --num_samples 1 \
    --max_tokens 512 \
    --output results/ifeval.json
Parameter Default Description
--param_path ./params Model directory
--data_path ./ifeval/input_data.jsonl IFEval JSONL (auto-downloaded if missing)
--output None Output JSON path
--max_tokens 512 Max generation tokens
--temperature 0.1 Sampling temperature (low for instruction-following)
--top_p 0.95 Top-p sampling
--top_k 50 Top-k sampling
--num_samples 1 Samples per problem (best-of-n scoring)
--batch_size 1 Inference batch size
--limit None Limit to first N problems (quick testing)
--dump_responses None Path to dump raw responses as JSONL

Output: stdout prints overall accuracy + per-constraint-type accuracy table. With --output, writes per-problem results + _summary.

Data: Auto-downloads google/IFEval from HuggingFace. Each problem has key, prompt, instruction_id_list, kwargs.


Weight Analysis

SVD-based effective rank and weight statistics for checkpoint diagnostics. Does not load the model graph or run any forward pass.

python scripts/eval/analyze_weights.py \
    --ckpt_dir ./checkpoint/epoch_1_step_6000 \
    --output results/weights.json
Parameter Default Description
--ckpt_dir required Checkpoint dir with model.safetensors + config.json
--compare None Additional checkpoint dirs to compare
--no_svd False Skip SVD; show only weight stats (faster)
--output None Save results as JSON
--device cuda Device for SVD

Output: SVD effective rank by component (ER@90/95/99%, entropic rank, condition number), per-layer effective rank grid, and weight value statistics (mean/std/min/max). Provides a utilization verdict (HIGH >0.85 / MODERATE >0.5 / LOW).


Tips

  • Quick test: Use --limit (IFEval) or --problems (HumanEval) to run on a small subset first.
  • Auto-download: HumanEval, MMLU, and IFEval auto-download their datasets on first run. The other scripts expect user-provided data.
  • Output formats: --output writes a single JSON for most scripts. PPL and IFD write an --output_dir containing summary.json plus per-file artifacts.
  • CPU mode: All scripts auto-detect CUDA. To force CPU, use --device cpu --dtype float32.

Document Update Time: 2026-07-30