This file documents every step of the pipeline for interview preparation. NOT uploaded to GitHub.
GCP Project: fieldpilot-485003
Billing: Linked to free credits ($300 budget)
GPU Quota: Requested GPUS_ALL_REGIONS increase from 0 → 1 (approved instantly)
VM: Vertex AI Workbench instance codetune-nb
- Zone:
us-west4-b(T4s were exhausted in us-central1, us-east1, us-west1 — had to try 12+ zones) - Machine:
n1-highmem-8(8 vCPUs, 52GB RAM) - GPU: Tesla T4 (16GB VRAM)
- Disk: 200GB PD-Balanced
- Image: PyTorch 2.7 + CUDA 12.8 on Ubuntu 22.04
- Cost: ~$0.35/hr for T4 +
$0.40/hr for n1-highmem-8 = **$0.75/hr total**
Why T4 over A100?
- A100 = $3.67/hr (10x more expensive)
- T4 has 16GB VRAM — tight but works with QLoRA + gradient checkpointing
- QLoRA reduces trainable params to <1% so 16GB is enough
- Budget-conscious: $300 credits need to last for train + eval + serve + benchmark
Chose: Qwen/Qwen2.5-Coder-7B-Instruct
Why not Llama 3.1 8B? Llama 3.1 is gated on HuggingFace (requires Meta approval, can take hours/days). Qwen2.5-Coder is:
- Fully open (no approval gate)
- 7B params (same class as Llama 8B)
- Actually stronger on coding benchmarks (HumanEval, MBPP)
- Uses ChatML template (standard, well-supported)
Interview talking point: "I chose the model that let me ship fastest without sacrificing quality. Qwen2.5-Coder outperforms Llama 3.1 8B on coding tasks anyway — the gating was a business constraint, not a technical one."
Dataset: CodeAlpaca-20k (sahil2801/CodeAlpaca-20k)
- 20,022 instruction/response pairs covering code generation
- Filtered to Python-only: 7,414 kept (37% of original)
- Filtered out: 10,423 non-Python, 2,184 too short (<3 lines), 1 too long (>100 lines)
- Train/eval split: 6,672 train / 742 eval (90/10)
Chat template: Qwen2.5 ChatML format:
<|im_start|>system
You are a Python coding assistant...<|im_end|>
<|im_start|>user
{instruction}<|im_end|>
<|im_start|>assistant
{output}<|im_end|>
Interview talking point: "Data curation is where most fine-tuning projects fail. I filtered aggressively — only Python, only 3-100 lines, deduplicated — because training on garbage produces garbage. The chat template must exactly match the model's expected format or the model learns the wrong token patterns."
Base model: Qwen/Qwen2.5-Coder-7B-Instruct
Quantization: 4-bit NF4 with double quantization
LoRA rank: 16 (alpha: 32, dropout: 0.05)
Target modules: q_proj, k_proj, v_proj, o_proj
Trainable params: ~87M out of 4.35B (~2%)
Effective batch size: 16 (4 per device × 4 gradient accumulation)
Learning rate: 2e-4 with cosine schedule
Epochs: 3
Max sequence length: 2048
Optimizer: paged_adamw_32bit (memory efficient)
Gradient checkpointing: enabled (saves ~40% VRAM)Why these choices?
- QLoRA (4-bit): Fits 7B model in 16GB VRAM. Full fine-tuning would need 56GB+.
- Rank 16: Good balance. Rank 8 underfits, rank 64 overfits on small datasets.
- All attention projections: Not just q/v (common mistake). Targeting all 4 gives better quality for ~2x the trainable params.
- Cosine schedule: Better than linear decay for short training runs.
- Gradient checkpointing: Trades ~20% speed for ~40% VRAM savings. Critical on T4.
Interview talking point: "QLoRA lets you fine-tune a 7B model on consumer hardware. The key insight is that 4-bit quantization preserves model quality during training because the gradients flow through the LoRA adapters in full precision — the frozen weights are just for the forward pass."
Status: Training in progress on GCP VM Expected duration: ~4-6 hours on T4 for 3 epochs × 6,672 examples Expected cost: ~$3-5
Fireworks AI productizes exactly this workflow:
- Dataset curation → Fireworks' fine-tuning product accepts custom datasets
- Fine-tuning (SFT) → Fireworks offers SFT as a managed service
- Evaluation → The role is literally "Evals & Post-Training Product"
- Serving at multiple quantization levels → Fireworks' core inference product
- Benchmarking throughput/latency/cost → How Fireworks sells (fastest inference)
GroundTruth provides the structural eval signal — one of 4 eval suites:
- HumanEval (functional correctness)
- MBPP (broader code generation)
- Structural verification via GT (hallucination detection, import correctness)
- Custom quality evals (type hints, docstrings, error handling)
GT is integrated as a Python library, not the star of the show. It's one eval signal among four. But it's the UNIQUE signal — nobody else measures structural correctness of generated code.
Interview talking point: "Functional correctness (does the code pass tests?) is necessary but not sufficient. Code can pass tests while importing from nonexistent modules, using hallucinated function names, or calling APIs with wrong signatures. GroundTruth catches these structural issues that tests miss."
| Metric | Value |
|---|---|
| Base model | Qwen2.5-Coder-7B-Instruct |
| Training data | 6,672 examples (filtered from 20K) |
| Trainable params | ~87M / 4.35B (2%) |
| Training cost | ~$3-5 on T4 |
| Total pipeline cost | ~$10-15 (well under $300 budget) |
| Eval suites | 4 (HumanEval, MBPP, Structural/GT, Custom) |
| Serving configs | 9 (3 frameworks × 3 quant levels) |
| Benchmark prompts | 50 (10 short, 20 medium, 20 long) |
- Standard SFT on CodeAlpaca, instruction format
- HumanEval: ~68-70% — -18% vs base
- Root cause: SFT shifts model distribution away from base instruct format
- Switched to body-only completion format (no
defheader in output) - HumanEval: 74.4% (122/164) — still -12% vs base
- Bugs hit:
raw.strip()removed leading 4-space indent →returnat module level → SyntaxError - Root cause of degradation: SFT on instruction data causes catastrophic forgetting (per RLEF paper)
- Method: Group Relative Policy Optimization (TRL GRPOTrainer)
- Reward: Binary code execution (python3 subprocess, timeout=10s)
- Config: rank=16, alpha=32, LR=5e-6, 2 gen, 128 max tokens, 75 steps, 34 min
- Result: 86.6% (142/164) — matched base exactly
- GRPO recovered all SFT damage in one 34-min run
- Method: Second GRPO pass starting from V4 (already at 86.6%)
- Config: rank=16, alpha=32, LR=5e-6, 2 gen, 256 max tokens, 187 steps, 2h 2min
- Result: 87.8% (144/164) — BEAT BASELINE by +1.2%
- Model fit fully in GPU (2 shards vs V4's 4) → eval ran 8x faster (971s vs 7783s)
| Model | HumanEval pass@1 | Passed | Delta |
|---|---|---|---|
| Base Qwen2.5-Coder-7B-Instruct | 86.6% | 142/164 | — |
| V1 SFT | ~68% | ~112/164 | -18% |
| V2 SFT | ~70% | ~115/164 | -16% |
| V3 SFT (completion) | 74.4% | 122/164 | -12.2% |
| V4 GRPO (150 ex) | 86.6% | 142/164 | = base |
| V5 GRPO (374 ex) | 87.8% | 144/164 | +1.2% |
- HumanEval: 86.6% (142/164)
- Structural: 75% pass rate, 0 hallucinated symbols, 2 missing imports, 3 missing symbols
- Custom (code quality): 69.8% overall — docstrings 83%, error handling 78%, Pythonic 80%
Why SFT hurts instruct models: Fine-tuning an already-instruction-tuned model on a new dataset shifts the token distribution. The model "forgets" its base RLHF alignment. This is the catastrophic forgetting problem documented in the RLEF paper (Gehman et al.).
Why GRPO works:
GRPO keeps the model close to the reference policy via KL penalty while only reinforcing behaviors that lead to passing tests. It can't forget what it already knows — it can only add new behaviors. The KL coefficient (beta=0.05) controls this tradeoff.
Why compounding GRPO (V4→V5) helped: V4 at 86.6% was already solving most easy/medium MBPP problems. V5's second pass with 2.5x more data provided signal on the marginal problems where V4 was inconsistent. Even with low reward variance (most problems solved or not solved consistently), the larger dataset gave more signal on edge cases.
Research backing:
- RLEF paper: RL methods preserve base capabilities; SFT degrades them
- Posterior-GRPO: +13.9% relative on Qwen2.5-Coder-7B-Instruct using GRPO with execution reward
- Our result: +1.2% absolute over base (86.6% → 87.8%) in <3 hours total GRPO training
- VM: n1-highmem-8 + T4 GPU = ~$0.75/hr
- Total runtime:
48 hours ≈ **$36 total** - Well within $300 free credit budget
results/eval/base.json— base model full evalresults/eval/codetune_v3.json— V3 SFT resultsresults/eval/codetune_v4.json— V4 GRPO full results (all 3 suites)results/eval/codetune_v5.json— V5 GRPO HumanEval resultsresults/v4_eval.log— V4 eval run logresults/v5_train.log— V5 GRPO training log (with step metrics)results/v5_eval.log— V5 eval run logtrain/grpo_v4.py— V4 GRPO scripttrain/grpo_v5.py— V5 GRPO script