Spaces:
Sleeping
Sleeping
| from pathlib import Path | |
| import json | |
| import sys | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[3])) | |
| from research.modal._common import ( # noqa: E402 | |
| COMMON_ENV, | |
| baseline_experiment_name, | |
| baseline_profiles_for_jobs, | |
| build_finetune_cmd, | |
| build_lm_eval_cmd, | |
| check_publish_gate_files, | |
| discover_cached_baselines, | |
| evaluate_gate, | |
| general_goals_for_job, | |
| prepare_jobs, | |
| profiles_needing_baseline_run, | |
| resolve_base_model_id, | |
| split_csv, | |
| ) | |
| def test_build_lm_eval_cmd_accepts_runtime_overrides(): | |
| cmd = build_lm_eval_cmd( | |
| experiment_name="exp", | |
| config="cfg.yaml", | |
| preset="minicpm5-1b", | |
| tasks=["arc_easy", "hellaswag"], | |
| limit=5, | |
| num_fewshot=1, | |
| batch_size="2", | |
| device="cuda", | |
| dtype="float16", | |
| seed=7, | |
| ) | |
| assert cmd[-15:] == [ | |
| "--tasks", | |
| "arc_easy", | |
| "hellaswag", | |
| "--limit", | |
| "5", | |
| "--num-fewshot", | |
| "1", | |
| "--batch-size", | |
| "2", | |
| "--device", | |
| "cuda", | |
| "--dtype", | |
| "float16", | |
| "--seed", | |
| "7", | |
| ] | |
| def test_prepare_jobs_filters_and_applies_finetune_overrides(): | |
| _, jobs = prepare_jobs( | |
| sector="math", | |
| profiles=["math"], | |
| max_steps=3, | |
| max_samples=11, | |
| finetune_overrides={"lr": 1e-4, "lora_r": 8, "dataset_split": "train[:11]"}, | |
| ) | |
| assert [job["name"] for job in jobs] == ["math-lora"] | |
| job = jobs[0] | |
| assert job["max_steps"] == 3 | |
| assert job["max_samples"] == 11 | |
| assert job["dataset_split"] == "train[:11]" | |
| assert job["args"]["lr"] == 1e-4 | |
| assert job["args"]["lora_r"] == 8 | |
| cmd = build_finetune_cmd(job, "/tmp/out") | |
| assert "--max_steps" in cmd | |
| assert cmd[cmd.index("--max_steps") + 1] == "3" | |
| assert "--lr" in cmd | |
| assert cmd[cmd.index("--lr") + 1] == "0.0001" | |
| assert "--lora_r" in cmd | |
| assert cmd[cmd.index("--lora_r") + 1] == "8" | |
| def test_split_csv_trims_empty_values(): | |
| assert split_csv(" math, science ,,code ") == ["math", "science", "code"] | |
| assert split_csv(None) is None | |
| def _results(task_scores: dict[str, float]) -> dict: | |
| return { | |
| "results": { | |
| task: {"acc,none": score, "acc_stderr,none": 0.01} | |
| for task, score in task_scores.items() | |
| } | |
| } | |
| def test_evaluate_gate_guard_only_goals(): | |
| candidate = _results({"arc_easy": 0.5, "hellaswag": 0.4}) | |
| baseline = _results({"arc_easy": 0.52, "hellaswag": 0.41}) | |
| goals = { | |
| "guard_tasks": [ | |
| {"task": "arc_easy", "max_regress": 0.03}, | |
| {"task": "hellaswag", "max_regress": 0.03}, | |
| ] | |
| } | |
| gate = evaluate_gate(candidate=candidate, baseline=baseline, goals=goals) | |
| assert gate["passed"] is True | |
| assert len(gate["checks"]) == 2 | |
| def test_check_publish_gate_requires_both_skill_and_general(tmp_path): | |
| skill_cand = tmp_path / "skill_cand.json" | |
| skill_base = tmp_path / "skill_base.json" | |
| general_cand = tmp_path / "general_cand.json" | |
| general_base = tmp_path / "general_base.json" | |
| skill_cand.write_text( | |
| json.dumps(_results({"gsm8k": 0.4})) | |
| ) | |
| skill_base.write_text( | |
| json.dumps(_results({"gsm8k": 0.33})) | |
| ) | |
| general_cand.write_text( | |
| json.dumps(_results({"arc_easy": 0.5, "hellaswag": 0.4})) | |
| ) | |
| general_base.write_text( | |
| json.dumps(_results({"arc_easy": 0.52, "hellaswag": 0.41})) | |
| ) | |
| gate = check_publish_gate_files( | |
| skill_candidate_path=str(skill_cand), | |
| skill_baseline_path=str(skill_base), | |
| skill_goals={"task": "gsm8k", "min_improve": 0.02}, | |
| general_candidate_path=str(general_cand), | |
| general_baseline_path=str(general_base), | |
| general_goals={ | |
| "guard_tasks": [{"task": "arc_easy", "max_regress": 0.03}] | |
| }, | |
| ) | |
| assert gate["passed"] is True | |
| assert gate["skill"]["passed"] is True | |
| assert gate["general"]["passed"] is True | |
| assert any(c["check"].startswith("general:") for c in gate["checks"]) | |
| def test_baseline_profiles_include_general_for_publishable_jobs(): | |
| _, jobs = prepare_jobs(job="math-lora") | |
| defaults = {"general_eval_profile": "compare_study", "general_goals": {"guard_tasks": []}} | |
| profiles = baseline_profiles_for_jobs(jobs, defaults) | |
| assert "math" in profiles | |
| assert "compare_study" in profiles | |
| def test_general_goals_only_for_publishable_jobs(): | |
| _, math_jobs = prepare_jobs(job="math-lora") | |
| _, local_jobs = prepare_jobs(job="alpaca-lora") | |
| defaults = {"general_goals": {"guard_tasks": [{"task": "piqa", "max_regress": 0.03}]}} | |
| assert general_goals_for_job(math_jobs[0], defaults) is not None | |
| assert general_goals_for_job(local_jobs[0], defaults) is None | |
| def test_resolve_base_model_id_from_preset(): | |
| _, jobs = prepare_jobs(job="math-lora") | |
| defaults, job = {}, jobs[0] | |
| assert resolve_base_model_id(job, defaults) == "openbmb/MiniCPM5-1B" | |
| def test_profiles_needing_baseline_run_respects_skip_and_cache(): | |
| cached = {"math": True, "compare_study": False} | |
| assert profiles_needing_baseline_run( | |
| ["math", "compare_study"], cached, skip_baseline=False | |
| ) == ["compare_study"] | |
| assert profiles_needing_baseline_run( | |
| ["math", "compare_study"], cached, skip_baseline=True | |
| ) == [] | |
| def test_baseline_experiment_name_uses_preset(): | |
| assert baseline_experiment_name("minicpm5-1b", "math") == "minicpm5-1b__baseline__math" | |
| def test_common_env_redirects_xet_logs_off_hf_cache_volume(): | |
| assert COMMON_ENV["HF_XET_LOG_DEST"] == "/tmp/xet-logs/" | |