On-Premises SLM and Phi Model Deployment
Last updated: 2026-02
Status: GA
Category: Hybrid Cloud & Edge AI
Introduksjon
Small Language Models (SLM) er kompakte AI-modeller med faerre enn 10 milliarder parametere som kan kjores effektivt pa lokal hardware uten skyavhengighet. Microsofts Phi-modellserie — fra Phi-2 (2.7B) til Phi-4 (14B) — representerer state-of-the-art for SLM, med ytelse som konkurrerer med modeller mange ganger storre.
For norsk offentlig sektor er lokal SLM-deployment sarlig attraktivt: full datakontroll uten at data forlater organisasjonens nettverk, forutsigbare kostnader uten per-token-prising, og mulighet for drift i miljoer med begrenset eller ingen internettilkobling. Phi-modellene er spesielt godt egnet fordi de er optimalisert for oppgaver som klassifisering, oppsummering, enhetstuttrekking og enkel sporsmalsbesvaring.
Microsoft tilbyr flere deploymentsveier for lokale SLM: Azure App Service sidecar, AKS Edge Essentials med KAITO, ONNX Runtime pa Windows/Linux, og Windows ML pa Copilot+ PC-er. Valget avhenger av skaleringsbehovet, tilgjengelig hardware og integrasjonskrav.
Kjernekomponenter
| Komponent |
Formal |
Teknologi |
| Phi-3 Mini |
3.8B parameter SLM for generelle oppgaver |
MIT-lisens |
| Phi-3 Small |
7B parameter SLM for hoeyere kvalitet |
MIT-lisens |
| Phi-3 Medium |
14B parameter SLM for komplekse oppgaver |
MIT-lisens |
| Phi-3.5 Mini |
Forbedret 3.8B med multilingual stoette |
MIT-lisens |
| Phi-4 Mini |
Nyeste 3.8B med forbedret resonnering |
MIT-lisens |
| ONNX Runtime |
Cross-platform inferensmotor |
Open source |
| KAITO |
Kubernetes AI Toolchain Operator |
Azure Arc |
| Olive |
Modelloptimalisering for deployment |
Microsoft |
| Windows ML |
Lokal inferens pa Windows |
Windows SDK |
Phi-3/Phi-4 Deployment
Modelloversikt
| Modell |
Parametere |
Kontekst |
RAM-krav |
GPU-krav |
Styrker |
| Phi-3 Mini 4K |
3.8B |
4K tokens |
8 GB |
Valgfritt |
Enkel Q&A, klassifisering |
| Phi-3 Mini 128K |
3.8B |
128K tokens |
8 GB |
Anbefalt |
Lange dokumenter |
| Phi-3 Small |
7B |
128K tokens |
16 GB |
Anbefalt |
Flerspraklig, koding |
| Phi-3 Medium |
14B |
128K tokens |
32 GB |
Pakrevd |
Kompleks resonnering |
| Phi-3.5 Mini |
3.8B |
128K tokens |
8 GB |
Valgfritt |
Multilingual, forbedret |
| Phi-4 Mini |
3.8B |
128K tokens |
8 GB |
Valgfritt |
Beste resonnering i klassen |
Deployment med Azure App Service Sidecar
# App Service sidecar-konfigurasjon for Phi-3.5 Mini
apiVersion: apps/v1
kind: Deployment
metadata:
name: phi-slm-app
spec:
template:
spec:
containers:
# Hoved-applikasjon
- name: web-app
image: myregistry.azurecr.io/myapp:latest
ports:
- containerPort: 8080
env:
- name: SLM_ENDPOINT
value: "http://localhost:11434"
# SLM sidecar
- name: phi-sidecar
image: mcr.microsoft.com/oss/ollama/ollama:latest
ports:
- containerPort: 11434
resources:
requests:
memory: "8Gi"
cpu: "4"
limits:
memory: "16Gi"
cpu: "8"
command: ["ollama", "serve"]
lifecycle:
postStart:
exec:
command: ["ollama", "pull", "phi3.5"]
Deployment med KAITO pa AKS Edge
# KAITO Workspace for Phi-3 Mini pa edge
apiVersion: kaito.sh/v1alpha1
kind: Workspace
metadata:
name: phi3-edge
annotations:
kaito.sh/enablelb: "false" # Ikke ekstern lastbalansering pa edge
spec:
resource:
instanceType: "Standard_NC4as_T4_v3" # GPU-node
labelSelector:
matchLabels:
apps: phi3-edge
inference:
preset:
name: "phi-3-mini-128k-instruct"
adapters:
- source:
name: "custom-norwegian-adapter"
image: "myregistry/phi3-no-adapter:v1"
ONNX Runtime deployment (CPU)
# Phi-3 Mini deployment med ONNX Runtime (ingen GPU nodvendig)
import onnxruntime_genai as og
class PhiLocalDeployment:
def __init__(self, model_path: str):
"""
Initialiser Phi-3/4 lokal deployment.
model_path: Sti til ONNX-optimalisert Phi-modell
"""
self.model = og.Model(model_path)
self.tokenizer = og.Tokenizer(self.model)
self.search_options = {
"max_length": 2048,
"temperature": 0.7,
"top_p": 0.9,
"do_sample": True
}
def generate(self, prompt: str, system_message: str = None,
max_tokens: int = 1024) -> str:
"""Generer svar fra lokal Phi-modell"""
if system_message:
full_prompt = (
f"<|system|>\n{system_message}<|end|>\n"
f"<|user|>\n{prompt}<|end|>\n"
f"<|assistant|>\n"
)
else:
full_prompt = (
f"<|user|>\n{prompt}<|end|>\n"
f"<|assistant|>\n"
)
input_tokens = self.tokenizer.encode(full_prompt)
params = og.GeneratorParams(self.model)
params.set_search_options(**{
**self.search_options,
"max_length": max_tokens
})
params.input_ids = input_tokens
generator = og.Generator(self.model, params)
output_tokens = []
while not generator.is_done():
generator.compute_logits()
generator.generate_next_token()
new_token = generator.get_next_tokens()[0]
output_tokens.append(new_token)
return self.tokenizer.decode(output_tokens)
def generate_streaming(self, prompt: str, system_message: str = None):
"""Streaming-generering for lavere opplevd latens"""
full_prompt = self._format_prompt(prompt, system_message)
input_tokens = self.tokenizer.encode(full_prompt)
params = og.GeneratorParams(self.model)
params.set_search_options(**self.search_options)
params.input_ids = input_tokens
generator = og.Generator(self.model, params)
tokenizer_stream = self.tokenizer.create_stream()
while not generator.is_done():
generator.compute_logits()
generator.generate_next_token()
token = generator.get_next_tokens()[0]
yield tokenizer_stream.decode(token)
Resource-Constrained Sizing
Hardware-dimensjonering
| Scenario |
Modell |
CPU |
RAM |
GPU |
Disk |
Inferens-hastighet |
| Minimal (PC) |
Phi-3 Mini INT4 |
4 kjerner |
8 GB |
Ingen |
5 GB |
~10 tokens/s |
| Standard (server) |
Phi-3 Mini FP16 |
8 kjerner |
16 GB |
T4 16GB |
10 GB |
~40 tokens/s |
| Ytelse (GPU) |
Phi-3 Small FP16 |
8 kjerner |
32 GB |
A10G 24GB |
20 GB |
~50 tokens/s |
| Enterprise |
Phi-3 Medium FP16 |
16 kjerner |
64 GB |
A100 40GB |
40 GB |
~60 tokens/s |
| Edge (NPU) |
Phi-3 Mini INT4 |
Snapdragon X |
16 GB |
NPU |
5 GB |
~20 tokens/s |
Minnesoptimalisering
# Konfigurasjon for ressursbegrensede miljoer
import onnxruntime as ort
def create_optimized_session(model_path: str, max_memory_gb: float = 4.0):
"""Opprett ONNX-session optimalisert for begrenset minne"""
session_options = ort.SessionOptions()
# Reduser minnebruk
session_options.enable_mem_pattern = True
session_options.enable_mem_reuse = True
# Begrens trader basert pa tilgjengelige kjerner
import os
available_cores = os.cpu_count() or 4
session_options.intra_op_num_threads = max(1, available_cores // 2)
session_options.inter_op_num_threads = max(1, available_cores // 4)
# Velg execution provider basert pa tilgjengelig hardware
providers = []
if ort.get_device() == "GPU":
providers.append(('CUDAExecutionProvider', {
'device_id': 0,
'arena_extend_strategy': 'kSameAsRequested',
'gpu_mem_limit': int(max_memory_gb * 1024 * 1024 * 1024),
'cudnn_conv_algo_search': 'HEURISTIC'
}))
providers.append('CPUExecutionProvider')
return ort.InferenceSession(
model_path,
sess_options=session_options,
providers=providers
)
Prompt Optimization for SLM
SLM-spesifikke prompt-teknikker
SLM-er har begrenset kontekstvindu og resonneringskapasitet sammenlignet med LLM-er. Prompt-optimalisering er kritisk:
| Teknikk |
Beskrivelse |
Effekt |
| Konsist system-melding |
Kort, presis rolledefinisjon (< 100 tokens) |
Bedre oppgavefokus |
| Strukturert output |
Be om JSON/tabell-format |
Mer palitelig parsing |
| Few-shot eksempler |
1-3 konkrete eksempler |
Hoyere noyaktighet |
| Decomposition |
Del opp komplekse oppgaver |
Bedre resultater |
| Constraint-basert |
Eksplisitte begrensninger |
Unnga hallusinasjoner |
Prompt-maler for norsk offentlig sektor
# Optimaliserte prompt-maler for SLM i offentlig sektor
SLM_PROMPTS = {
"klassifisering": """<|system|>
Du klassifiserer dokumenter. Svar KUN med en av kategoriene.
Kategorier: {categories}
<|end|>
<|user|>
Klassifiser folgende tekst:
"{text}"
Kategori:<|end|>
<|assistant|>""",
"oppsummering": """<|system|>
Du oppsummerer tekst pa norsk. Maks {max_words} ord.
<|end|>
<|user|>
Oppsummer folgende:
"{text}"
<|end|>
<|assistant|>
Oppsummering:""",
"uttrekking": """<|system|>
Du trekker ut strukturert informasjon. Svar i JSON-format.
<|end|>
<|user|>
Trekk ut folgende felter fra teksten: {fields}
Tekst: "{text}"
JSON:<|end|>
<|assistant|>
{{""",
"qa_med_kontekst": """<|system|>
Du svarer pa sporsmal basert pa konteksten. Svar KUN basert pa informasjonen gitt.
Hvis svaret ikke finnes i konteksten, si "Ikke tilstrekkelig informasjon."
<|end|>
<|user|>
Kontekst:
{context}
Sporsmal: {question}
<|end|>
<|assistant|>"""
}
Fine-Tuning at Edge
Lokal fine-tuning av Phi-modeller
# LoRA fine-tuning av Phi-3 for norsk offentlig sektor
from transformers import (
AutoModelForCausalLM, AutoTokenizer,
TrainingArguments, Trainer
)
from peft import LoraConfig, get_peft_model
import torch
def finetune_phi_lora(
base_model: str = "microsoft/phi-3-mini-4k-instruct",
dataset_path: str = "training_data.jsonl",
output_dir: str = "./phi3-finetuned"
):
"""Fine-tune Phi-3 med LoRA for norsk offentlig sektor"""
# Last modell med 4-bit kvantisering for a spare minne
model = AutoModelForCausalLM.from_pretrained(
base_model,
torch_dtype=torch.bfloat16,
load_in_4bit=True,
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(base_model)
# LoRA-konfigurasjon (minimal for edge)
lora_config = LoraConfig(
r=16, # Lav rank for edge-deployment
lora_alpha=32,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
# Treningsargumenter optimalisert for begrenset hardware
training_args = TrainingArguments(
output_dir=output_dir,
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
save_strategy="epoch",
optim="paged_adamw_8bit", # Minneeffektiv optimizer
max_grad_norm=0.3,
warmup_ratio=0.03
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=load_dataset(dataset_path),
tokenizer=tokenizer
)
trainer.train()
# Lagre kun LoRA-adapteret (liten filstorrelse)
model.save_pretrained(output_dir)
# Adapter-storrelse: typisk 20-50 MB vs 7+ GB for full modell
ONNX-eksport for deployment
# Konverter fine-tuned Phi-3 til ONNX for deployment
python -m olive run \
--config olive-config.json \
--model-id ./phi3-finetuned \
--output-dir ./phi3-onnx-optimized \
--precision int4 \
--target-device cpu
// olive-config.json
{
"input_model": {
"type": "HfModel",
"model_path": "./phi3-finetuned"
},
"passes": [
{"type": "OnnxConversion"},
{"type": "OnnxQuantization", "quant_mode": "dynamic", "weight_type": "QInt4"},
{"type": "OrtTransformersOptimization", "model_type": "gpt2"}
],
"engine": {
"target": "onnxruntime",
"execution_providers": ["CPUExecutionProvider"]
}
}
Norsk offentlig sektor
Hvorfor lokal SLM for offentlig sektor?
- Datakontroll: Ingen data forlater organisasjonens nettverk — viktig for personopplysninger og gradert informasjon
- Kostnadskontroll: Fast infrastrukturkostnad uten per-token-prising — enklere budsjettforvaltning
- Tilgjengelighet: Fungerer uten internettilkobling — relevant for felt, krisesituasjoner, og isolerte miljoer
- Etterlevelse: Enklere a demonstrere compliance med Schrems II, GDPR, og NSM-krav
Anbefalte bruksomrader for SLM
| Bruksomrade |
Modell |
Beskrivelse |
| Dokumentklassifisering |
Phi-3 Mini INT4 |
Klassifiser innkommende post/henvendelser |
| Oppsummering |
Phi-3.5 Mini |
Oppsummer lange utredninger og hoeringsnotater |
| Informasjonsuttrekking |
Phi-3 Mini |
Trekk ut nokkeldata fra skjemaer |
| Intern Q&A |
Phi-4 Mini + RAG |
Svar pa sporsmal fra regelverk |
| Tekstgenerering |
Phi-3 Small |
Utkast til brev og standardsvar |
Beslutningsrammeverk
| Scenario |
Anbefaling |
Begrunnelse |
| Enkel klassifisering/uttrekking |
Phi-3 Mini INT4 pa CPU |
Minimal hardware, rask inferens |
| Norsk sprakbehandling |
Phi-3.5 Mini eller Phi-4 Mini |
Bedre multilingual stoette |
| Kompleks resonnering |
Phi-3 Medium pa GPU |
Nodvendig kapasitet |
| Edge-deployment (IoT) |
Phi-3 Mini INT4 ONNX |
Minst fotavtrykk |
| Windows-klient |
Windows ML + Phi-4 Mini |
Automatisk hardware-optimalisering |
| Copilot+ PC |
Windows ML med NPU |
Best ytelse/watt |
| Server-deployment |
KAITO pa AKS Edge |
Skalerbart, Kubernetes-managed |
For Cosmo
- Phi-3 Mini INT4 er det naturlige startpunktet for de fleste offentlige sektors SLM-bruk — 3.8B parametere gir overraskende god kvalitet for klassifisering, uttrekking og enkel Q&A, og krever kun 8 GB RAM uten GPU
- Fine-tuning med LoRA er nodvendig for doenmespesifikke oppgaver — en LoRA-adapter pa 20-50 MB er mye enklere a distribuere til edge enn en full modell, og gir dramatisk forbedring for norsk fagsprak
- Prompt-optimalisering er viktigere for SLM enn for LLM — korte, strukturerte prompts med eksplisitte output-formater og 1-3 few-shot-eksempler oker kvaliteten betydelig
- ONNX Runtime + Olive er den foretrukne deployment-pipeline — konverter til ONNX, kvantiser til INT4, og deploy pa CPU for maksimal portabilitet og ytelse
- For norsk offentlig sektor: Lokal SLM-deployment eliminerer de fleste Schrems II-utfordringer — data forlater aldri nettverket, noe som forenkler personvernkonsekvensvurdering og compliance-dokumentasjon