# Quickstart: Fine-Tune Your First Model 6 steps from zero to a fine-tuned model using SFT with synthetic data. > **Time**: ~20 min active + 1-3 hours training. ## Prerequisites - Microsoft Foundry project with a deployed model (e.g., `gpt-4.1-mini`) - Python 3.10+ with `openai` installed - Project endpoint URL and API key (Foundry portal → Project Settings) ## Step 1: Connect to Your Project ```bash export OPENAI_BASE_URL="https://.services.ai.azure.com/api/projects//openai/v1/" export AZURE_OPENAI_API_KEY="" ``` ```python from openai import OpenAI import os client = OpenAI(base_url=os.environ["OPENAI_BASE_URL"], api_key=os.environ["AZURE_OPENAI_API_KEY"]) resp = client.chat.completions.create(model="gpt-4.1-mini", messages=[{"role": "user", "content": "Hello"}], max_tokens=10) print(resp.choices[0].message.content) ``` ## Step 2: Generate Training Data ```python import json, re SYSTEM_PROMPT = "You are a concise technical support agent. Answer in 1-2 sentences." generation_prompt = """Generate 50 diverse technical support conversations. Each should have a customer question and an ideal agent response (1-2 sentences). Cover: password resets, billing, product setup, account changes, shipping, troubleshooting. Return a JSON array where each element has "question" and "answer" fields.""" resp = client.chat.completions.create( model="gpt-4.1-mini", messages=[{"role": "user", "content": generation_prompt}], max_tokens=8000, temperature=1.0, ) content = resp.choices[0].message.content match = re.search(r'```(?:json)?\s*\n(.*?)\n```', content, re.DOTALL) json_str = match.group(1) if match else content.strip().strip("`").replace("json\n", "") examples = json.loads(json_str) for split, name, rng in [("train", "train.jsonl", examples[:40]), ("val", "val.jsonl", examples[40:])]: with open(name, "w") as f: for ex in rng: f.write(json.dumps({"messages": [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": ex["question"]}, {"role": "assistant", "content": ex["answer"]}, ]}) + "\n") ``` Validate: `python scripts/validate/validate_sft.py train.jsonl` ## Step 3: Baseline the Base Model ```python with open("val.jsonl") as f: test_examples = [json.loads(line) for line in f][:5] for ex in test_examples: resp = client.chat.completions.create( model="gpt-4.1-mini", messages=ex["messages"][:2], max_tokens=200) print(f"Q: {ex['messages'][1]['content']}") print(f"Expected: {ex['messages'][2]['content']}") print(f"Base model: {resp.choices[0].message.content}\n") ``` ## Step 4: Upload Data and Submit Job ```python import time with open("train.jsonl", "rb") as f: train = client.files.create(file=f, purpose="fine-tune") with open("val.jsonl", "rb") as f: val = client.files.create(file=f, purpose="fine-tune") for _ in range(30): if client.files.retrieve(train.id).status == "processed" and client.files.retrieve(val.id).status == "processed": break time.sleep(10) job = client.fine_tuning.jobs.create( model="gpt-4.1-mini", training_file=train.id, validation_file=val.id, suffix="my-first-ft", method={"type": "supervised"}, hyperparameters={"n_epochs": 2, "learning_rate_multiplier": 1.0}, ) print(f"Job submitted: {job.id}") ``` Or via script: ```bash python scripts/submit_training.py --model gpt-4.1-mini --training-file train.jsonl --validation-file val.jsonl --type sft --suffix my-first-ft --epochs 2 ``` ## Step 5: Monitor ```bash python scripts/monitor_training.py --job-id ``` Or check [Microsoft Foundry portal](https://ai.azure.com) → Fine-tuning → Jobs. ## Step 6: Deploy, Test, and Compare ```bash python scripts/deploy_model.py --model-id --name my-ft-deployment --capacity 50 ``` ```python for ex in test_examples: base = client.chat.completions.create(model="gpt-4.1-mini", messages=ex["messages"][:2], max_tokens=200) ft = client.chat.completions.create(model="my-ft-deployment", messages=ex["messages"][:2], max_tokens=200) print(f"Q: {ex['messages'][1]['content']}") print(f"Base: {base.choices[0].message.content}") print(f"Fine-tuned: {ft.choices[0].message.content}\n") ``` ## What's Next - **Scale data**: 200-500 examples → `workflows/dataset-creation.md` - **Try RFT**: For verifiable answers → `references/training-types.md` - **Debug**: `workflows/diagnose-poor-results.md` - **Full guide**: `workflows/full-pipeline.md`