⚡ ML Engineering Portfolio Project

Phi-2 QLoRA Model Comparison & Benchmark Suite

Empirical comparison between the frozen microsoft/phi-2 base model (2.78B) and its 4-bit QLoRA adapter (5.24M parameters / 0.19%) evaluated on a 50-task leak-free algorithmic benchmark.

Functional Pass Rate
68.0% +16.0%
34/50 unit-tested tasks passed vs 26/50 (52%) for raw base model.
EOS Termination Rate
96.0% +78.0%
48/50 clean stops vs 9/50 (18%) raw (eliminated runaway loops).
Runaway Token Cutoffs
4.0% -80.0%
Only 2/50 hit token ceiling vs 42/50 (84%) for raw base model.
Parameter Footprint
0.19% 5.24M / 2.78B
Adapter safetensors footprint is ~20 MB; base weights remain frozen.
Select Benchmark Prompt Category: Real generations from actual model evaluations under greedy decoding (temp=0.0)
Loading prompt...
🏛️ Raw Phi-2 Base Model microsoft/phi-2
⚠️ Runaway Continuation
# Loading base generation...
🚀 Fine-Tuned QLoRA Adapter Config E (Step 100)
✅ Clean EOS Stop
# Loading adapted generation...
💡 Key Empirical Observation: Notice how the raw base model exhibits runaway generation—hallucinating subsequent exercises, prompt tokens (### Exercise 5, ### Instruction:), and hitting the maximum token limit. The fine-tuned QLoRA adapter cleanly terminates generation with <|endoftext|> immediately upon completing the requested function.
Model / Configuration Training Scope Target Modules Resp Loss Core Pass% (50 Tasks) EOS Term% Max-Token% Mean Length
Raw Phi-2 Base Pretrained (2.78B) None 0.5792 52.0% (26/50) 18.0% 84.0% 284.6 tok
Phase 2 Corrected (Ref) 2,000 samples q_proj, v_proj 0.4471 62.0% (31/50) 94.0% 6.0% 112.8 tok
Config A (Attn-Only, 2k) 2,000 samples q_proj, v_proj 0.4522 62.0% (31/50) 98.0% 2.0% 112.8 tok
Config B (Full-Attn, 2k) 2,000 samples q, k, v, dense 0.4477 54.0% (27/50) 90.0% 10.0% 121.9 tok
Config C (All-Linear, 2k) 2,000 samples q, k, v, dense, fc1, fc2 0.4442 60.0% (30/50) 98.0% 2.0% 115.6 tok
Config D (Masking-Ablation, 2k) 2,000 samples q_proj, v_proj (no mask) 0.4489 62.0% (31/50) 98.0% 2.0% 114.1 tok
Config E (5k, Step 100) [BEST] 5,000 samples q_proj, v_proj 0.4803 68.0% (34/50) 96.0% 4.0% 115.4 tok
Algorithmic Category Task Count Raw Phi-2 Base Config E Step 100 Improvement Delta
String Manipulation 6 2/6 (33%) 3/6 (50%) +17%
Data Structures 8 3/8 (38%) 5/8 (63%) +25%
Sorting & Searching 6 3/6 (50%) 5/6 (83%) +33%
Recursion & Dynamic Programming 8 5/8 (63%) 7/8 (88%) +25%
OOP & Class Definitions 6 3/6 (50%) 4/6 (67%) +17%
File I/O & Exception Handling 4 1/4 (25%) 2/4 (50%) +25%
Algorithm Complexity & Edge Cases 6 5/6 (83%) 3/6 (50%) -33%
Bug Fixing 6 4/6 (67%) 5/6 (83%) +16%
Overall 50-Task Total 50 26/50 (52.0%) 34/50 (68.0%) +16.0%

🔬 Scientific Fine-Tuning Pipeline

The project systematically addressed common low-resource fine-tuning failure modes:

  • Context Loss Recovery: Identified that an initial preprocessing pipeline dropped the input column in 69% of records. Restored full input preservation.
  • EOS Supervision: Proved in Phase 2B that omitted EOS tokens caused a 75% rate of runaway text generation. Enforced terminal <|endoftext|> token loss.
  • Response-Only Masking: Implemented Phase2CompletionCollator to restrict gradient updates solely to the generated code response, cutting training wall-clock time by 5.27× over full-sequence masking.
  • LoRA Target Scope: Evaluated Attention-only (q_proj, v_proj) vs Full-Attention vs All-Linear, confirming Attention-only is parameter-optimal at 5.24M parameters.
  • Hardware Discipline: Executed training and evaluation within the memory confines of a 6 GB consumer GPU (NVIDIA RTX 4050) with a peak VRAM allocation of ~3.1 GB.

💻 Run Inference Locally

Load the adapter directly from Hugging Face Hub on your local GPU or CPU:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel

# Configure 4-bit NF4 quantization (or remove for CPU)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
)

# Load base model & attach adapter
base_model = AutoModelForCausalLM.from_pretrained(
    "microsoft/phi-2",
    quantization_config=bnb_config,
    device_map="auto",
    trust_remote_code=True,
)
model = PeftModel.from_pretrained(base_model, "alfeenafsal/phi2-qlora-finetune")
model.eval()

tokenizer = AutoTokenizer.from_pretrained("alfeenafsal/phi2-qlora-finetune", trust_remote_code=True)
prompt = "### Instruction:\nWrite a Python function that checks if two strings are anagrams.\n\n### Response:\n"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)

with torch.no_grad():
    out = model.generate(**inputs, max_new_tokens=150, do_sample=False)
print(tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
⚠️ Research Demonstration & Safety Disclaimer:
This project is an experimental code-generation fine-tune developed for research and educational purposes. It is not a production-grade coding assistant. Outputs may contain logical flaws or edge-case bugs. Generated code must always be executed inside a sandboxed environment and reviewed before use.