# Model Distillation for Performance **Last updated:** 2026-04 | Verified: MCP 2026-04 **Status:** GA **Category:** Performance & Scalability **Type:** reference **Source:** https://learn.microsoft.com/azure/foundry/openai/concepts/fine-tuning-considerations --- ## Innhold - [Introduksjon](#introduksjon) - [Kjernekomponenter](#kjernekomponenter) - [Distillation Training Process](#distillation-training-process) - [Model Size vs. Quality Tradeoffs](#model-size-vs-quality-tradeoffs) - [Token Reduction Benefits](#token-reduction-benefits) - [Use Case Suitability](#use-case-suitability) - [Norsk offentlig sektor](#norsk-offentlig-sektor) - [Beslutningsrammeverk](#beslutningsrammeverk) - [Modellvalg og routing-strategi (oppdatert 2026-04)](#modellvalg-og-routing-strategi-oppdatert-2026-04) - [Referanser](#referanser) - [For Cosmo](#for-cosmo) ## Introduksjon Model distillation er prosessen der en stor, kraftig modell (teacher) brukes til å trene en mindre, raskere modell (student) som oppnår akseptabel kvalitet for en spesifikk oppgave. I Azure OpenAI-konteksten betyr dette typisk å samle produksjonsdata fra en premium-modell som GPT-4o eller o3, og bruke disse som treningsdata for å fine-tune en mindre modell som GPT-4o-mini eller GPT-4.1-nano. Microsoft Foundry tilbyr en integrert distillation-pipeline via Stored Completions-funksjonen. Produksjonsforespørsler og -svar lagres automatisk, filtreres etter kvalitet, og konverteres direkte til fine-tuning datasett. Dette eliminerer manuell datakuratering og gir en strømlinjeformet vei fra stor modell til optimalisert, kostnadseffektiv deployment. For norsk offentlig sektor er distillation spesielt verdifullt fordi det muliggjør lavere driftskostnader, raskere responstider og potensielt bedre kontroll over modellens oppførsel. En distillert modell trenger færre tokens per forespørsel (kortere prompts), noe som direkte reduserer både latens og kostnad. ## Kjernekomponenter | Komponent | Formål | Teknologi | |-----------|--------|-----------| | Stored Completions | Automatisk lagring av produksjonsdata | Microsoft Foundry | | Fine-tuning API | LoRA-basert tilpasning av base-modeller | Azure OpenAI | | Evaluation Framework | Kvalitetsmåling av distillert modell | Microsoft Foundry Evaluations | | Teacher Model | Stor modell som genererer treningsdata | GPT-4o, o3, GPT-5 | | Student Model | Mindre modell som trenes via distillation | GPT-4o-mini, GPT-4.1-nano | ## Distillation Training Process ### Steg 1: Aktiver Stored Completions ```python from openai import AzureOpenAI client = AzureOpenAI( azure_endpoint="https://my-aoai.openai.azure.com", api_key="...", api_version="2024-12-01-preview" ) # Aktiver stored completions for teacher-modellen response = client.chat.completions.create( model="gpt-4o", # Teacher model messages=[ {"role": "system", "content": "Du er en norsk saksbehandler-assistent..."}, {"role": "user", "content": "Oppsummer denne klagen: ..."} ], store=True, # Lagre completion for distillation metadata={ "task": "complaint-summary", "quality_score": "verified" } ) ``` ### Steg 2: Samle og kuratere treningsdata ```python # Samle tilstrekkelig med stored completions # Minimum: 10 completions (anbefalt: 500-1000+) def curate_distillation_dataset( completions: list[dict], min_quality_score: float = 0.8, target_size: int = 1000 ) -> list[dict]: """Curate high-quality completions for distillation.""" curated = [] for completion in completions: # Filtrer basert på kvalitet if completion.get("quality_score", 0) < min_quality_score: continue # Konverter til fine-tuning format training_example = { "messages": [ {"role": "system", "content": completion["system_prompt"]}, {"role": "user", "content": completion["user_input"]}, {"role": "assistant", "content": completion["assistant_output"]} ] } curated.append(training_example) if len(curated) >= target_size: break return curated # Minimum 10 stored completions, anbefalt 500+ # Microsoft anbefaler hundrevis til tusenvis for best resultat ``` ### Steg 3: Fine-tune student-modellen ```python import json # Opprett treningsfil def create_training_file(dataset: list[dict], filename: str): with open(filename, "w") as f: for example in dataset: f.write(json.dumps(example) + "\n") # Last opp og start fine-tuning def start_distillation_finetuning( client: AzureOpenAI, training_file: str, student_model: str = "gpt-4o-mini" ): """Start fine-tuning of student model with teacher data.""" # Last opp treningsdata file = client.files.create( file=open(training_file, "rb"), purpose="fine-tune" ) # Start fine-tuning jobb job = client.fine_tuning.jobs.create( training_file=file.id, model=student_model, hyperparameters={ "n_epochs": 3, "learning_rate_multiplier": 1.0, "batch_size": "auto" }, suffix="distilled-complaint-summary" ) return job ``` ### Steg 4: Evaluer distillert modell ```python async def evaluate_distillation( teacher_client: AzureOpenAI, student_client: AzureOpenAI, test_prompts: list[dict], teacher_model: str = "gpt-4o", student_model: str = "ft:gpt-4o-mini:distilled" ) -> dict: """Compare teacher vs student model quality.""" results = {"teacher": [], "student": [], "quality_matches": 0} for prompt in test_prompts: # Teacher response (ground truth) teacher_resp = teacher_client.chat.completions.create( model=teacher_model, messages=prompt["messages"] ) # Student response student_resp = student_client.chat.completions.create( model=student_model, messages=prompt["messages"] ) teacher_text = teacher_resp.choices[0].message.content student_text = student_resp.choices[0].message.content results["teacher"].append({ "output": teacher_text, "tokens": teacher_resp.usage.total_tokens, "latency_ms": teacher_resp.response_ms # Hvis tilgjengelig }) results["student"].append({ "output": student_text, "tokens": student_resp.usage.total_tokens, "latency_ms": student_resp.response_ms }) # Beregn metrics avg_teacher_tokens = sum( r["tokens"] for r in results["teacher"]) / len(results["teacher"]) avg_student_tokens = sum( r["tokens"] for r in results["student"]) / len(results["student"]) return { "test_size": len(test_prompts), "avg_teacher_tokens": round(avg_teacher_tokens), "avg_student_tokens": round(avg_student_tokens), "token_reduction_pct": round( (1 - avg_student_tokens / avg_teacher_tokens) * 100, 1), } ``` ## Model Size vs. Quality Tradeoffs ### Sammenligning av Azure OpenAI-modeller | Modell | Relativ størrelse | Input TPM/PTU | Latens-mål | Kostnad (Standard) | Typisk bruk etter distillation | |--------|------------------|---------------|------------|---------------------|-------------------------------| | GPT-5 | Største | 4,750 | 50 TPS | Høyest | Teacher model | | GPT-4.1 | Stor | 3,000 | 80 TPS | Høy | Teacher / produksjon | | GPT-4o | Stor | 2,500 | 25 TPS | Høy | Teacher model | | GPT-4.1-mini | Medium | 14,900 | 90 TPS | Medium | Student — god balanse | | GPT-4o-mini | Medium | 37,000 | 33 TPS | Lav | Student — kostnadsoptimal | | GPT-4.1-nano | Liten | 59,400 | 100 TPS | Lavest | Student — latens-kritisk | ### Kvalitets-/kostnadsmatrise ```python # Sammenlign distillation-kandidater distillation_candidates = { "gpt-4o → gpt-4o-mini": { "teacher_cost_per_1m_input": 2.50, "student_cost_per_1m_input": 0.15, "cost_reduction": "94%", "expected_quality_retention": "85-95%", "best_for": "General tasks, summarization" }, "gpt-4.1 → gpt-4.1-mini": { "teacher_cost_per_1m_input": 2.00, "student_cost_per_1m_input": 0.40, "cost_reduction": "80%", "expected_quality_retention": "88-96%", "best_for": "Instruction following, structured output" }, "gpt-4.1 → gpt-4.1-nano": { "teacher_cost_per_1m_input": 2.00, "student_cost_per_1m_input": 0.10, "cost_reduction": "95%", "expected_quality_retention": "75-90%", "best_for": "Classification, simple extraction" } } ``` ## Token Reduction Benefits ### Hvorfor distillerte modeller bruker færre tokens ``` Standard prompt (med few-shot examples): ┌─────────────────────────────────────────┐ │ System prompt: 200 tokens │ │ Few-shot example 1: 150 tokens │ │ Few-shot example 2: 150 tokens │ │ Few-shot example 3: 150 tokens │ │ User input: 500 tokens │ │ ───────────────────────────────── │ │ TOTALT INPUT: 1,150 tokens │ └─────────────────────────────────────────┘ Distillert modell (innebygd kunnskap): ┌─────────────────────────────────────────┐ │ System prompt: 50 tokens │ │ User input: 500 tokens │ │ ───────────────────────────────── │ │ TOTALT INPUT: 550 tokens (52% reduksjon)│ └─────────────────────────────────────────┘ ``` ### Kostnadsberegning ```python def calculate_distillation_savings( monthly_requests: int, avg_input_tokens_before: int, avg_input_tokens_after: int, avg_output_tokens: int, teacher_input_price_per_1m: float, teacher_output_price_per_1m: float, student_input_price_per_1m: float, student_output_price_per_1m: float, finetuning_cost: float = 500 # Engangskostnad for fine-tuning ) -> dict: """Calculate monthly savings from model distillation.""" # Teacher-kostnad teacher_input_cost = ( monthly_requests * avg_input_tokens_before / 1_000_000 * teacher_input_price_per_1m) teacher_output_cost = ( monthly_requests * avg_output_tokens / 1_000_000 * teacher_output_price_per_1m) teacher_total = teacher_input_cost + teacher_output_cost # Student-kostnad student_input_cost = ( monthly_requests * avg_input_tokens_after / 1_000_000 * student_input_price_per_1m) student_output_cost = ( monthly_requests * avg_output_tokens / 1_000_000 * student_output_price_per_1m) student_total = student_input_cost + student_output_cost monthly_savings = teacher_total - student_total roi_months = finetuning_cost / monthly_savings if monthly_savings > 0 else float('inf') return { "teacher_monthly_nok": round(teacher_total * 11, 2), # USD → NOK "student_monthly_nok": round(student_total * 11, 2), "monthly_savings_nok": round(monthly_savings * 11, 2), "savings_pct": round((1 - student_total / teacher_total) * 100, 1), "roi_months": round(roi_months, 1) } # Eksempel: Direktoratet for digital tjenesteutvikling dokumentanalyse savings = calculate_distillation_savings( monthly_requests=100_000, avg_input_tokens_before=1200, # Med few-shot avg_input_tokens_after=550, # Distillert avg_output_tokens=300, teacher_input_price_per_1m=2.50, teacher_output_price_per_1m=10.00, student_input_price_per_1m=0.15, student_output_price_per_1m=0.60, finetuning_cost=500 ) print(f"Månedlig besparelse: {savings['monthly_savings_nok']} NOK") print(f"ROI: {savings['roi_months']} måneder") ``` ## Use Case Suitability ### Når distillation er egnet | Use case | Egnethet | Begrunnelse | |----------|----------|-------------| | Dokumentklassifisering | Svært egnet | Enkel oppgave, høy konsistens | | Oppsummering | Egnet | Forutsigbart format, godt distillert | | Sentiment-analyse | Svært egnet | Binær/tertsiær output | | Kodeforklaring | Moderat egnet | Krever presisjon, men mønsterbart | | Kreativ skriving | Lite egnet | Variasjon er ønskelig | | Kompleks resonnering | Lite egnet | Mister nuanser ved distillation | | Flerspråklig oversettelse | Moderat egnet | Avhenger av språkpar og domene | ### Når distillation IKKE bør brukes ``` ❌ Oppgaven krever konstant oppdatert kunnskap (bruk RAG i stedet) ❌ Output-variabilitet er viktig (kreative oppgaver) ❌ Volumet er for lavt (< 1000 forespørsler/mnd) — besparelsen dekker ikke fine-tuning-kostnad ❌ Oppgaven endrer seg ofte — modellen må re-trenes ❌ Sikkerhetskritiske beslutninger der teacher-modellens resonnering er viktig ``` ## Norsk offentlig sektor - **Personvern og GDPR**: Stored Completions lagrer brukerdata — sørg for at databehandleravtale dekker fine-tuning-formål. Treningsdata kan ikke eksporteres fra Microsoft Foundry. - **Utredningsinstruksen**: Distillation bør dokumenteres som et tiltak for kostnadsoptimalisering i AI-utredninger. Beregn besparelser over 3-5 år for å rettferdiggjøre initial investering. - **Forvaltningsloven**: Hvis den distillerte modellen brukes til vedtaksstøtte, dokumenter at kvaliteten er validert og at den oppfyller krav til forsvarlig saksbehandling. - **Anskaffelser**: Fine-tuning hosting koster per time (uavhengig av bruk). Sammenlign totalkostnad inkludert hosting mot standard pay-per-token. ## Beslutningsrammeverk | Scenario | Anbefaling | Begrunnelse | |----------|------------|-------------| | Høyt volum, enkel oppgave | Distiller til nano/mini | Størst kostnadsbesparelse | | Middels volum, moderat kompleksitet | Distiller til mini | God balanse kvalitet/kostnad | | Lavt volum (<1K/mnd) | Behold teacher | Fine-tuning-kostnad > besparelse | | Hyppig endring i oppgave | Unngå distillation | Re-training overhead | | Latens-kritisk (<500ms) | Distiller til nano + PTU | Lavest mulig responstid | ## Modellvalg og routing-strategi (oppdatert 2026-04) Microsoft dokumenterer nå **10 seleksjonskriterier** ved valg av AI-modell for distillasjon: | Kriterium | Relevans for distillasjon | |-----------|--------------------------| | Task fit | Velg teacher og student basert på oppgavens art | | **Routing strategy** | Definer routing FØR distillasjon — påvirker teacher-modellvalg | | Cost | Studentmodellens kostnad er primær motivasjon | | Context window | Student må håndtere samme kontekst som teacher | | Security | Studentmodell arver ikke teachers sikkerhetstiltak — re-evaluer | | Region | Student deployes i samme region som teacher for dataresidency | | Deployment | PTU vs Standard — student er oftest Standard til start | | Domain | Domene-spesifikk teacher gir bedre student | | Performance | Latens- og throughput-krav til student (se modellmatrise) | | **Tunability** | Studentmodellen MÅ støtte fine-tuning (f.eks. GPT-4o-mini, GPT-4.1-nano) | ### Modell-routing som distillasjonsstrategi ```python # Model routing strategy i distillasjonskontekst # Teacher: GPT-4.1 (høyeste kvalitet) # Router: Klassifiser oppgavekompleksitet → velg modell dynamisk # Student: GPT-4.1-mini eller GPT-4.1-nano (basert på klassifisering) from openai import AzureOpenAI import json client = AzureOpenAI( azure_endpoint="https://my-foundry.openai.azure.com", api_key="...", api_version="2024-10-21" ) def classify_task_complexity(user_input: str) -> str: """Klassifiser oppgavekompleksitet for routing.""" response = client.chat.completions.create( model="gpt-4.1-nano", # Rask og billig til routing messages=[{ "role": "system", "content": "Klassifiser denne brukerforespørselen: 'simple' (fakta, svar, klassifisering) eller 'complex' (resonnering, kreativt, multi-steg). Svar med ett ord." }, {"role": "user", "content": user_input}] ) return response.choices[0].message.content.strip().lower() def route_to_model(user_input: str) -> str: """Route til riktig modell basert på kompleksitet.""" complexity = classify_task_complexity(user_input) if complexity == "simple": model = "ft:gpt-4.1-nano:distilled-v1" # Distillert nano for enkle oppgaver else: model = "gpt-4.1" # Teacher for komplekse oppgaver response = client.chat.completions.create( model=model, messages=[{"role": "user", "content": user_input}] ) return response.choices[0].message.content # Routing strategy gir: lavere kostnad for enkle oppgaver + høy kvalitet for komplekse ``` ### Oppdatert modellmatrise for distillasjon | Modell | Tunability | TPM (PTU, input) | Anbefalt student-rolle | |--------|-----------|-----------------|----------------------| | GPT-4.1-nano | Ja | 59,400 | Enkle oppgaver, latens-kritisk | | GPT-4o-mini | Ja | 37,000 | Generelle oppgaver, kostnadsoptimal | | GPT-4.1-mini | Ja | 14,900 | Moderate oppgaver, god balanse | | GPT-4.1 | Nei (direkte) | 3,000 | Teacher (ikke student) | | GPT-4o | Nei (direkte) | 2,500 | Teacher (ikke student) | ## Referanser - [Azure OpenAI stored completions & distillation](https://learn.microsoft.com/azure/foundry-classic/openai/how-to/stored-completions) — Distillation workflow - [Fine-tuning considerations](https://learn.microsoft.com/azure/foundry/openai/concepts/fine-tuning-considerations) — Når fine-tuning er riktig - [Customize a model with fine-tuning](https://learn.microsoft.com/azure/foundry/openai/how-to/fine-tuning) — Fine-tuning guide - [Choose the right AI model](https://learn.microsoft.com/azure/architecture/ai-ml/guide/choose-ai-model) — Modellvalg-guide ## For Cosmo - **Bruk denne referansen** når kunden har høyt volum av repetitive AI-oppgaver og ønsker å redusere kostnader uten å miste kvalitet. - Stored Completions → Distill-flyten i Microsoft Foundry er den enkleste veien — ingen manuell datakuratering nødvendig. - Anbefal alltid evaluering med reelle testdata før produksjonsdeployment av distillert modell — kvalitetstap varierer sterkt per oppgave. - GPT-4.1-nano gir 59,400 input TPM per PTU vs. 3,000 for GPT-4.1 — en 20x throughput-økning for enkle oppgaver. - Fine-tuned modeller har hosting-kostnad per time — beregn break-even punkt basert på forventet volum.