Spaces:
Sleeping
Sleeping
| # Runs INSIDE the HF Job container. Self-contained: clones the repo, installs | |
| # deps, and walks Phases 0..6. On any failure, the trap pushes whatever | |
| # artifacts already landed in /tmp/results/ to the dataset repo under partial/. | |
| # | |
| # Required env vars (set via `hf jobs run --secret`): | |
| # HF_TOKEN | |
| # WANDB_API_KEY | |
| set -euo pipefail | |
| MODEL_REPO="jester1177/mutant-hunter-qwen-coder-1.5b-lora" | |
| DATASET_REPO="jester1177/mutant-hunter-results" | |
| RESULTS_DIR="/tmp/results" | |
| push_partial() { | |
| rc=$? | |
| echo "" | |
| echo "[trap] caught exit code ${rc}; uploading whatever is in ${RESULTS_DIR}/ as partial/" | |
| if [ -d "${RESULTS_DIR}" ]; then | |
| python - <<'PY' || echo "[trap] partial upload itself failed; giving up" | |
| import os | |
| from huggingface_hub import HfApi | |
| api = HfApi() | |
| api.upload_folder( | |
| folder_path="/tmp/results", | |
| repo_id="jester1177/mutant-hunter-results", | |
| repo_type="dataset", | |
| path_in_repo="partial", | |
| ) | |
| print("[trap] partial artifacts pushed to dataset repo under partial/") | |
| PY | |
| else | |
| echo "[trap] no ${RESULTS_DIR}/ directory exists; nothing to push" | |
| fi | |
| exit "${rc}" | |
| } | |
| trap push_partial ERR | |
| echo "=== Phase 0: setup ===" | |
| cd /tmp | |
| if [ ! -d MetaOpenEnv_MutantHunter ]; then | |
| git clone https://github.com/melohub-xbit/MetaOpenEnv_MutantHunter.git | |
| fi | |
| cd MetaOpenEnv_MutantHunter | |
| mkdir -p "${RESULTS_DIR}" "${RESULTS_DIR}/training" "${RESULTS_DIR}/plots" | |
| python -c "import torch; assert torch.cuda.is_available(), 'No CUDA available in base image'; print(f'Using pre-installed torch {torch.__version__}, CUDA {torch.version.cuda}')" | |
| pip install --no-cache-dir -e ".[training]" | |
| pip install --no-cache-dir bitsandbytes wandb | |
| python -c "from huggingface_hub import login; login(token='${HF_TOKEN}')" | |
| python -c "import os; os.environ['HOME']='/tmp'; import wandb; wandb.login(key='${WANDB_API_KEY}')" | |
| python - <<'PY' | |
| from huggingface_hub import HfApi | |
| api = HfApi() | |
| api.create_repo("jester1177/mutant-hunter-qwen-coder-1.5b-lora", repo_type="model", exist_ok=True) | |
| api.create_repo("jester1177/mutant-hunter-results", repo_type="dataset", exist_ok=True) | |
| print("repos ready") | |
| PY | |
| echo "=== Phase 1: heuristic baseline (~5 min) ===" | |
| python training/baseline_eval.py \ | |
| --episodes 10 \ | |
| --policy mutation_aware \ | |
| --seed-start 0 \ | |
| --out "${RESULTS_DIR}/baseline_heuristic.json" | |
| python - <<'PY' | |
| from huggingface_hub import upload_file | |
| upload_file( | |
| path_or_fileobj="/tmp/results/baseline_heuristic.json", | |
| path_in_repo="baseline_heuristic.json", | |
| repo_id="jester1177/mutant-hunter-results", | |
| repo_type="dataset", | |
| ) | |
| print("baseline_heuristic.json pushed") | |
| PY | |
| echo "=== Phase 2: zero-shot LLM baseline (~30 min) ===" | |
| python evaluation/zero_shot_distribution.py \ | |
| --episodes 10 \ | |
| --model Qwen/Qwen2.5-Coder-1.5B-Instruct \ | |
| --max-new-tokens 1024 \ | |
| --seed-start 0 \ | |
| --device auto | |
| cp evaluation/_results/zero_shot_distribution.json "${RESULTS_DIR}/baseline_zeroshot.json" | |
| python - <<'PY' | |
| from huggingface_hub import upload_file | |
| upload_file( | |
| path_or_fileobj="/tmp/results/baseline_zeroshot.json", | |
| path_in_repo="baseline_zeroshot.json", | |
| repo_id="jester1177/mutant-hunter-results", | |
| repo_type="dataset", | |
| ) | |
| print("baseline_zeroshot.json pushed") | |
| PY | |
| echo "=== Phase 3: 200-step GRPO training (~4h) ===" | |
| python training/train_grpo.py \ | |
| --steps 80 \ | |
| --rollouts-per-step 3 \ | |
| --base-model Qwen/Qwen2.5-Coder-1.5B-Instruct \ | |
| --max-new-tokens 1024 \ | |
| --learning-rate 5e-6 \ | |
| --seed 42 \ | |
| --output-dir "${RESULTS_DIR}/training" \ | |
| --wandb-project mutant-hunter-final | |
| if [ ! -d "${RESULTS_DIR}/training/final" ]; then | |
| echo "ERROR: ${RESULTS_DIR}/training/final/ not found after training" >&2 | |
| exit 1 | |
| fi | |
| python - <<'PY' | |
| from huggingface_hub import HfApi | |
| HfApi().upload_folder( | |
| folder_path="/tmp/results/training/final", | |
| repo_id="jester1177/mutant-hunter-qwen-coder-1.5b-lora", | |
| repo_type="model", | |
| ) | |
| print("LoRA adapter pushed to model repo") | |
| PY | |
| if [ -f "${RESULTS_DIR}/training/training_log.jsonl" ]; then | |
| python - <<'PY' | |
| from huggingface_hub import upload_file | |
| upload_file( | |
| path_or_fileobj="/tmp/results/training/training_log.jsonl", | |
| path_in_repo="training_log.jsonl", | |
| repo_id="jester1177/mutant-hunter-qwen-coder-1.5b-lora", | |
| repo_type="model", | |
| ) | |
| print("training_log.jsonl pushed") | |
| PY | |
| else | |
| echo "[warn] training_log.jsonl not found; skipping upload" | |
| fi | |
| echo "=== Phase 4: trained eval (~30 min) ===" | |
| # Stash Phase 2 output so the next run does not clobber it. | |
| cp "${RESULTS_DIR}/baseline_zeroshot.json" "${RESULTS_DIR}/baseline_zeroshot.keep.json" | |
| python evaluation/zero_shot_distribution.py \ | |
| --episodes 10 \ | |
| --model Qwen/Qwen2.5-Coder-1.5B-Instruct \ | |
| --lora-path "${RESULTS_DIR}/training/final" \ | |
| --max-new-tokens 1024 \ | |
| --seed-start 0 \ | |
| --device auto | |
| cp evaluation/_results/zero_shot_distribution.json "${RESULTS_DIR}/trained_eval.json" | |
| python - <<'PY' | |
| from huggingface_hub import upload_file | |
| upload_file( | |
| path_or_fileobj="/tmp/results/trained_eval.json", | |
| path_in_repo="trained_eval.json", | |
| repo_id="jester1177/mutant-hunter-results", | |
| repo_type="dataset", | |
| ) | |
| print("trained_eval.json pushed") | |
| PY | |
| echo "=== Phase 5: plots ===" | |
| python evaluation/make_plots.py \ | |
| --baseline-heuristic-json "${RESULTS_DIR}/baseline_heuristic.json" \ | |
| --baseline-zeroshot-json "${RESULTS_DIR}/baseline_zeroshot.json" \ | |
| --trained-eval-json "${RESULTS_DIR}/trained_eval.json" \ | |
| --training-log-json "${RESULTS_DIR}/training/training_log.jsonl" \ | |
| --out-dir "${RESULTS_DIR}/plots/" | |
| python - <<'PY' | |
| from huggingface_hub import HfApi | |
| HfApi().upload_folder( | |
| folder_path="/tmp/results/plots", | |
| repo_id="jester1177/mutant-hunter-qwen-coder-1.5b-lora", | |
| repo_type="model", | |
| path_in_repo="plots", | |
| ) | |
| print("plots/ pushed to model repo") | |
| PY | |
| echo "=== Phase 6: summary ===" | |
| echo "Model: https://huggingface.co/${MODEL_REPO}" | |
| echo "Dataset: https://huggingface.co/datasets/${DATASET_REPO}" | |
| python - <<'PY' || echo "[warn] could not read W&B run URL" | |
| import os | |
| os.environ.setdefault("HOME", "/tmp") | |
| try: | |
| import wandb | |
| api = wandb.Api() | |
| runs = api.runs("mutant-hunter-final", order="-created_at", per_page=1) | |
| for r in runs: | |
| print(f"W&B run: {r.url}") | |
| break | |
| except Exception as e: | |
| print(f"[warn] wandb URL lookup failed: {e}") | |
| PY | |
| echo "" | |
| echo "=== Done ===" | |