feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command
Add /ultraresearch-local for structured research combining local codebase analysis with external knowledge via parallel agent swarms. Produces research briefs with triangulation, confidence ratings, and source quality assessment. New command: /ultraresearch-local with modes --quick, --local, --external, --fg. New agents: research-orchestrator (opus), docs-researcher, community-researcher, security-researcher, contrarian-researcher, gemini-bridge (all sonnet). New template: research-brief-template.md. Integration: --research flag in /ultraplan-local accepts pre-built research briefs (up to 3), enriches the interview and exploration phases. Planning orchestrator cross-references brief findings during synthesis. Design principle: Context Engineering — right information to right agent at right time. Research briefs are structured artifacts in the pipeline: ultraresearch → brief → ultraplan --research → plan → ultraexecute. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
baa2d0220b
488 changed files with 213221 additions and 0 deletions
|
|
@ -0,0 +1,453 @@
|
|||
# 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
|
||||
|
||||
```yaml
|
||||
# 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
|
||||
|
||||
```yaml
|
||||
# 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)
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
```json
|
||||
// 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue