scripts used in generating my submission
Browse filesthese scripts I built (with help from LLMs: gemini 2.5 pro and gpt5) and they encapsulate the work done in creating my submission. The only thing I am not sharing are the planning documents I wrote for my submission, as 1. I currently appear to have first place and 2. that may not last, and part of my planning documents include improvements I can make, if I am so inspired.
- evaluate.sh +49 -0
- format_dataset.py +38 -0
- merge.sh +90 -0
- train.sh +74 -0
evaluate.sh
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# Final project evaluation launcher for gsm8k using lighteval + vLLM on hf jobs.
|
| 3 |
+
set -euo pipefail
|
| 4 |
+
|
| 5 |
+
: "${HF_TOKEN:?HF_TOKEN must be exported with write permissions.}"
|
| 6 |
+
: "${HF_USERNAME:?HF_USERNAME must be exported before running this script.}"
|
| 7 |
+
|
| 8 |
+
MODEL_NAME="${MODEL_NAME:-smollm3-sft-math-tuned}"
|
| 9 |
+
HUB_MODEL_ID="${HUB_MODEL_ID:-${HF_USERNAME}/${MODEL_NAME}}"
|
| 10 |
+
RESULTS_TEMPLATE_DEFAULT='{org}/details_{org}__{model}_private'
|
| 11 |
+
RESULTS_PATH_TEMPLATE="${RESULTS_PATH_TEMPLATE:-$RESULTS_TEMPLATE_DEFAULT}"
|
| 12 |
+
HUB_MODEL_REVISION="${HUB_MODEL_REVISION:-main}"
|
| 13 |
+
|
| 14 |
+
FLAVOR="${FLAVOR:-a10g-large}"
|
| 15 |
+
TIMEOUT="${TIMEOUT:-60m}"
|
| 16 |
+
TASK_SPEC="${TASK_SPEC:-lighteval|gsm8k|0}"
|
| 17 |
+
|
| 18 |
+
if [[ "${DEBUG:-0}" != "0" ]]; then
|
| 19 |
+
echo "[DEBUG] Running evaluation on a reduced setup."
|
| 20 |
+
FLAVOR="${DEBUG_FLAVOR:-t4-small}"
|
| 21 |
+
TIMEOUT="${DEBUG_TIMEOUT:-20m}"
|
| 22 |
+
fi
|
| 23 |
+
|
| 24 |
+
echo "Submitting evaluation job:"
|
| 25 |
+
echo " Model : ${HUB_MODEL_ID}"
|
| 26 |
+
echo " Results template : ${RESULTS_PATH_TEMPLATE}"
|
| 27 |
+
echo " Hardware : ${FLAVOR}"
|
| 28 |
+
echo " Task spec : ${TASK_SPEC}"
|
| 29 |
+
|
| 30 |
+
MODEL_ARGS="model_name=${HUB_MODEL_ID}"
|
| 31 |
+
if [[ -n "${HUB_MODEL_REVISION}" && "${HUB_MODEL_REVISION}" != "none" ]]; then
|
| 32 |
+
MODEL_ARGS="${MODEL_ARGS},revision=${HUB_MODEL_REVISION}"
|
| 33 |
+
fi
|
| 34 |
+
|
| 35 |
+
hf jobs uv run \
|
| 36 |
+
--flavor "${FLAVOR}" \
|
| 37 |
+
--timeout "${TIMEOUT}" \
|
| 38 |
+
--with "git+https://github.com/huggingface/lighteval@main#egg=lighteval[vllm,gsm8k]" \
|
| 39 |
+
--with emoji \
|
| 40 |
+
--secrets HF_TOKEN \
|
| 41 |
+
lighteval vllm \
|
| 42 |
+
"${MODEL_ARGS}" \
|
| 43 |
+
"${TASK_SPEC}" \
|
| 44 |
+
--push-to-hub \
|
| 45 |
+
--results-org "${HF_USERNAME}" \
|
| 46 |
+
--results-path-template "${RESULTS_PATH_TEMPLATE}"
|
| 47 |
+
|
| 48 |
+
echo "Evaluation job queued. Check your datasets under ${HF_USERNAME}/ for the 'details_*' entry once complete."
|
| 49 |
+
echo "Recommendation: apply self-consistency by sampling multiple completions locally and majority-voting the final answer."
|
format_dataset.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from datasets import load_dataset
|
| 3 |
+
|
| 4 |
+
# --- Configuration ---
|
| 5 |
+
# Your Hugging Face username is needed to create the new dataset repo.
|
| 6 |
+
# Make sure you are logged in via `huggingface-cli login`.
|
| 7 |
+
HF_USERNAME = os.getenv("HF_USERNAME")
|
| 8 |
+
if not HF_USERNAME:
|
| 9 |
+
raise ValueError("Please set the HF_USERNAME environment variable.")
|
| 10 |
+
|
| 11 |
+
SOURCE_DATASET = "meta-math/MetaMathQA"
|
| 12 |
+
NEW_DATASET_NAME = f"{HF_USERNAME}/MetaMathQA-formatted"
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# --- Formatting Function ---
|
| 16 |
+
# This function creates the single 'text' column the training script needs.
|
| 17 |
+
def format_prompt(example):
|
| 18 |
+
# The prompt format should ideally match the base model's training style.
|
| 19 |
+
# A simple question/answer format is a good starting point.
|
| 20 |
+
return {"text": f"Question: {example['query']}\n\nAnswer: {example['response']}"}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# --- Main Script ---
|
| 24 |
+
if __name__ == "__main__":
|
| 25 |
+
print(f"Loading original dataset '{SOURCE_DATASET}'...")
|
| 26 |
+
dataset = load_dataset(SOURCE_DATASET, split="train")
|
| 27 |
+
|
| 28 |
+
print("Formatting dataset...")
|
| 29 |
+
formatted_dataset = dataset.map(format_prompt)
|
| 30 |
+
|
| 31 |
+
# Optional: remove old columns to keep the dataset clean
|
| 32 |
+
formatted_dataset = formatted_dataset.remove_columns(["query", "response", "type"])
|
| 33 |
+
|
| 34 |
+
print(f"Pushing formatted dataset to '{NEW_DATASET_NAME}'...")
|
| 35 |
+
formatted_dataset.push_to_hub(NEW_DATASET_NAME)
|
| 36 |
+
|
| 37 |
+
print("\n✅ Success! Your formatted dataset is ready on the Hub.")
|
| 38 |
+
print("You can now update your train.sh script.")
|
merge.sh
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# HF Job to merge a LoRA adapter with its base model and push to the Hub.
|
| 3 |
+
set -euo pipefail
|
| 4 |
+
|
| 5 |
+
# --- Configuration (update if necessary) -------------------------------------
|
| 6 |
+
: "${HF_TOKEN:?HF_TOKEN must be exported with write permissions.}"
|
| 7 |
+
: "${HF_USERNAME:?HF_USERNAME must be exported before running this script.}"
|
| 8 |
+
|
| 9 |
+
# The base model you trained from
|
| 10 |
+
BASE_MODEL="${BASE_MODEL:-HuggingFaceTB/SmolLM3-3B-Base}"
|
| 11 |
+
# The repo containing your LoRA adapter files
|
| 12 |
+
ADAPTER_ID="${ADAPTER_ID:-${HF_USERNAME}/smollm3-sft-math-tuned}"
|
| 13 |
+
# The repo where the final MERGED model will be saved.
|
| 14 |
+
# This should be the same as your adapter repo to replace it.
|
| 15 |
+
HUB_MODEL_ID="${HUB_MODEL_ID:-${ADAPTER_ID}}"
|
| 16 |
+
|
| 17 |
+
# --- Job settings ------------------------------------------------------------
|
| 18 |
+
# Merging a 3B model can be memory intensive. a10g-large is a safe choice.
|
| 19 |
+
FLAVOR="${FLAVOR:-a10g-large}"
|
| 20 |
+
TIMEOUT="${TIMEOUT:-30m}"
|
| 21 |
+
|
| 22 |
+
echo "Submitting LoRA merge job:"
|
| 23 |
+
echo " Base model : ${BASE_MODEL}"
|
| 24 |
+
echo " Adapter repo : ${ADAPTER_ID}"
|
| 25 |
+
echo " Final Hub repo : ${HUB_MODEL_ID}"
|
| 26 |
+
echo " Hardware : ${FLAVOR}"
|
| 27 |
+
|
| 28 |
+
# --- hf jobs command ---
|
| 29 |
+
hf jobs uv run \
|
| 30 |
+
--flavor "${FLAVOR}" \
|
| 31 |
+
--timeout "${TIMEOUT}" \
|
| 32 |
+
--secrets HF_TOKEN \
|
| 33 |
+
--with "torch" \
|
| 34 |
+
--with "peft" \
|
| 35 |
+
--with "transformers>=4.38.0" \
|
| 36 |
+
--with "accelerate" \
|
| 37 |
+
--with "huggingface_hub" \
|
| 38 |
+
--env "BASE_MODEL=${BASE_MODEL}" \
|
| 39 |
+
--env "ADAPTER_ID=${ADAPTER_ID}" \
|
| 40 |
+
--env "HUB_MODEL_ID=${HUB_MODEL_ID}" \
|
| 41 |
+
python -c "$(cat <<'EOF'
|
| 42 |
+
import os
|
| 43 |
+
import torch
|
| 44 |
+
from peft import PeftModel
|
| 45 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 46 |
+
from huggingface_hub import HfApi, create_repo
|
| 47 |
+
|
| 48 |
+
# --- Get variables from environment ---
|
| 49 |
+
base_model_id = os.getenv("BASE_MODEL")
|
| 50 |
+
adapter_id = os.getenv("ADAPTER_ID")
|
| 51 |
+
hub_model_id = os.getenv("HUB_MODEL_ID")
|
| 52 |
+
output_dir = "merged-model" # Local temp directory in the job runner
|
| 53 |
+
|
| 54 |
+
# --- Load Models and Merge ---
|
| 55 |
+
print(f"Loading base model: {base_model_id}")
|
| 56 |
+
base_model = AutoModelForCausalLM.from_pretrained(
|
| 57 |
+
base_model_id,
|
| 58 |
+
torch_dtype=torch.bfloat16,
|
| 59 |
+
device_map="auto",
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
print(f"Loading adapter: {adapter_id}")
|
| 63 |
+
model = PeftModel.from_pretrained(base_model, adapter_id)
|
| 64 |
+
|
| 65 |
+
print("Merging adapter weights...")
|
| 66 |
+
model = model.merge_and_unload()
|
| 67 |
+
|
| 68 |
+
tokenizer = AutoTokenizer.from_pretrained(base_model_id)
|
| 69 |
+
|
| 70 |
+
# --- Save and Upload ---
|
| 71 |
+
print(f"Saving merged model locally to '{output_dir}'")
|
| 72 |
+
model.save_pretrained(output_dir)
|
| 73 |
+
tokenizer.save_pretrained(output_dir)
|
| 74 |
+
|
| 75 |
+
print(f"Uploading merged model to the Hub at {hub_model_id}")
|
| 76 |
+
# Ensure the repo exists and then upload the contents of our folder
|
| 77 |
+
create_repo(hub_model_id, repo_type="model", exist_ok=True)
|
| 78 |
+
api = HfApi()
|
| 79 |
+
api.upload_folder(
|
| 80 |
+
folder_path=output_dir,
|
| 81 |
+
repo_id=hub_model_id,
|
| 82 |
+
repo_type="model",
|
| 83 |
+
commit_message="Upload merged LoRA model",
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
print("Job complete.")
|
| 87 |
+
EOF
|
| 88 |
+
)"
|
| 89 |
+
|
| 90 |
+
echo "Merge job queued. Check your model repo '${HUB_MODEL_ID}' for the merged files upon completion."
|
train.sh
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# Final project training launcher for SmolLM3 fine-tuning with hf jobs.
|
| 3 |
+
# Adapts the competition-ready workflow documented in final_plan.md.
|
| 4 |
+
set -euo pipefail
|
| 5 |
+
|
| 6 |
+
# --- Required configuration --------------------------------------------------
|
| 7 |
+
: "${HF_TOKEN:?HF_TOKEN must be exported with write permissions.}"
|
| 8 |
+
: "${HF_USERNAME:?HF_USERNAME must be exported before running this script.}"
|
| 9 |
+
|
| 10 |
+
MODEL_NAME="${MODEL_NAME:-smollm3-sft-math-tuned}"
|
| 11 |
+
BASE_MODEL="${BASE_MODEL:-HuggingFaceTB/SmolLM3-3B-Base}"
|
| 12 |
+
DATASET_NAME="${DATASET_NAME:-${HF_USERNAME}/MetaMathQA-formatted}"
|
| 13 |
+
HUB_MODEL_ID="${HUB_MODEL_ID:-${HF_USERNAME}/${MODEL_NAME}}"
|
| 14 |
+
|
| 15 |
+
# --- Training hyperparameters (override via env when needed) -----------------
|
| 16 |
+
LEARNING_RATE="${LEARNING_RATE:-5e-5}"
|
| 17 |
+
PER_DEVICE_BATCH="${PER_DEVICE_BATCH:-2}"
|
| 18 |
+
GRAD_ACCUM="${GRAD_ACCUM:-8}"
|
| 19 |
+
MAX_STEPS="${MAX_STEPS:-1000}"
|
| 20 |
+
EVAL_STEPS="${EVAL_STEPS:-200}"
|
| 21 |
+
SAVE_STEPS="${SAVE_STEPS:-200}"
|
| 22 |
+
SEED="${SEED:-42}"
|
| 23 |
+
OUTPUT_DIR="${OUTPUT_DIR:-smollm3-sft-jobs-math}"
|
| 24 |
+
|
| 25 |
+
# --- LoRA configuration ------------------------------------------------------
|
| 26 |
+
LORA_R="${LORA_R:-8}"
|
| 27 |
+
LORA_ALPHA="${LORA_ALPHA:-32}"
|
| 28 |
+
LORA_DROPOUT="${LORA_DROPOUT:-0.05}"
|
| 29 |
+
IFS=' ' read -r -a LORA_TARGET_MODULES_ARR <<< "${LORA_TARGET_MODULES:-q_proj k_proj v_proj o_proj gate_proj up_proj down_proj}"
|
| 30 |
+
|
| 31 |
+
# --- Job settings ------------------------------------------------------------
|
| 32 |
+
FLAVOR="${FLAVOR:-a10g-large}"
|
| 33 |
+
TIMEOUT="${TIMEOUT:-2h}"
|
| 34 |
+
|
| 35 |
+
if [[ "${DEBUG:-0}" != "0" ]]; then
|
| 36 |
+
echo "[DEBUG] Running shortened smoke test."
|
| 37 |
+
MAX_STEPS="${DEBUG_MAX_STEPS:-20}"
|
| 38 |
+
FLAVOR="${DEBUG_FLAVOR:-t4-small}"
|
| 39 |
+
TIMEOUT="${DEBUG_TIMEOUT:-20m}"
|
| 40 |
+
fi
|
| 41 |
+
|
| 42 |
+
echo "Submitting training job:"
|
| 43 |
+
echo " Hub model id : ${HUB_MODEL_ID}"
|
| 44 |
+
echo " Base model : ${BASE_MODEL}"
|
| 45 |
+
echo " Dataset : ${DATASET_NAME}"
|
| 46 |
+
echo " Flavor : ${FLAVOR}"
|
| 47 |
+
echo " Max steps : ${MAX_STEPS}"
|
| 48 |
+
|
| 49 |
+
hf jobs uv run \
|
| 50 |
+
--flavor "${FLAVOR}" \
|
| 51 |
+
--timeout "${TIMEOUT}" \
|
| 52 |
+
--secrets HF_TOKEN \
|
| 53 |
+
"https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py" \
|
| 54 |
+
--model_name_or_path "${BASE_MODEL}" \
|
| 55 |
+
--dataset_name "${DATASET_NAME}" \
|
| 56 |
+
--learning_rate "${LEARNING_RATE}" \
|
| 57 |
+
--per_device_train_batch_size "${PER_DEVICE_BATCH}" \
|
| 58 |
+
--gradient_accumulation_steps "${GRAD_ACCUM}" \
|
| 59 |
+
--max_steps "${MAX_STEPS}" \
|
| 60 |
+
--eval_steps "${EVAL_STEPS}" \
|
| 61 |
+
--save_steps "${SAVE_STEPS}" \
|
| 62 |
+
--seed "${SEED}" \
|
| 63 |
+
--output_dir "${OUTPUT_DIR}" \
|
| 64 |
+
--hub_model_id "${HUB_MODEL_ID}" \
|
| 65 |
+
--report_to none \
|
| 66 |
+
--use_peft \
|
| 67 |
+
--lora_r "${LORA_R}" \
|
| 68 |
+
--lora_alpha "${LORA_ALPHA}" \
|
| 69 |
+
--lora_dropout "${LORA_DROPOUT}" \
|
| 70 |
+
--lora_target_modules "${LORA_TARGET_MODULES_ARR[@]}" \
|
| 71 |
+
--bf16 True \
|
| 72 |
+
--push_to_hub
|
| 73 |
+
|
| 74 |
+
echo "Training job queued. Monitor progress on the Hugging Face Hub Jobs dashboard."
|