ktg-plugin-marketplace/plugins/ms-ai-architect/skills/ms-ai-infrastructure/references/hybrid-edge/disconnected-ai-scenarios.md
Kjell Tore Guttormsen 6a7632146e feat(ms-ai-architect): add plugin to open marketplace (v1.5.0 baseline)
Initial addition of ms-ai-architect plugin to the open-source marketplace.
Private content excluded: orchestrator/ (Linear tooling), docs/utredning/
(client investigation), generated test reports and PDF export script.
skill-gen tooling moved from orchestrator/ to scripts/skill-gen/.

Security scan: WARNING (risk 20/100) — no secrets, no injection found.
False positive fixed: added gitleaks:allow to Python variable reference
in output-validation-grounding-verification.md line 109.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 17:17:17 +02:00

19 KiB

Disconnected AI Scenarios

Last updated: 2026-02 Status: GA Category: Hybrid Cloud & Edge AI


Introduksjon

Frakoblede (disconnected) AI-scenarioer er situasjoner der AI-arbeidsbelastninger ma kjore uten internettilkobling — enten permanent, periodisk eller i beredskapssituasjoner. For norsk offentlig sektor er dette svart relevant: Forsvaret opererer i omrader uten nettdekning, helsesektoren trenger AI-stotte i ambulanser og utposter, og kritisk infrastruktur (energi, transport) ma fungere uavhengig av skytjenester.

Microsoft tilbyr flere losninger for frakoblet AI: Azure AI Foundry Tools disconnected containers for tradisjonelle AI-tjenester (tale, tekst, bilde), Azure Stack Edge for hardware-basert edge-inferens, Azure Local med disconnected operations for storre Kubernetes-miljoer, og ONNX Runtime for helt lokale modellkjoringer uten skyavhengigheter.

Denne referansen dekker de viktigste moensterne for offline modell-deployment, datarekonsiliering, lokal caching/synkronisering og fallback-strategier — alle med fokus pa palit drift nar nettverkstilkoblingen er ustabil eller fravarende.


Spekter av tilkobling

AI-scenarioer fordeler seg langs et tilkoblingsspektrum:

┌─────────────────────────────────────────────────────┐
│  Alltid     Sporadisk    Periodisk    Helt           │
│  tilkoblet  tilkoblet    tilkoblet    frakoblet      │
│  ●──────────●────────────●────────────●              │
│  |          |            |            |              │
│  Standard   Connected    Batch sync   Air-gapped     │
│  Azure      containers   +            lokale          │
│  services   (billing)    offline ops  modeller       │
└─────────────────────────────────────────────────────┘
Modus Nettverkskrav Azure-tjenester Billing
Alltid tilkoblet Stabilt internett Alle Pay-as-you-go
Connected containers Periodisk (billing) Begrensede Bruksbasert
Periodisk synk Timer/dager mellom tilkoblinger Batch-synk Commitment tier
Helt frakoblet Ingen Kun lokale Forhndsbetalt lisens

Offline Model Deployment

Azure AI Foundry Tools Disconnected Containers

Microsofts primaere losning for AI-tjenester uten nettverkstilkobling:

Tjeneste Container Disconnected Status
Speech to Text speech-to-text Ja GA
Custom Speech to Text custom-speech-to-text Ja GA
Neural Text to Speech neural-text-to-speech Ja GA
Translator text-translation Ja GA
Language Detection text-language-detection Ja GA
Key Phrase Extraction text-keyphrase Ja GA
Named Entity Recognition text-ner Ja GA
PII Detection text-pii Ja GA
Sentiment Analysis text-sentiment Ja GA
CLU clu Ja GA
Summarization text-summarization Ja Preview
Read OCR vision-read Ja GA
Document Intelligence document-intelligence Ja GA
Content Safety (Text) contentsafety-text Ja Preview
Content Safety (Image) contentsafety-image Ja Preview
Prompt Shields contentsafety-promptshields Ja Preview

Prosess for disconnected deployment

┌─────────────────────────────────────────┐
│  1. Soknad og godkjenning               │
│     ├── Enterprise Agreement kreves     │
│     ├── Gyldig business case            │
│     └── Godkjenning innen 10 dager      │
│                                         │
│  2. Lisensnedlasting                    │
│     ├── Kjop commitment tier            │
│     ├── Last ned lisensfil              │
│     └── Lisensfil har utlopsdato        │
│                                         │
│  3. Container-nedlasting                │
│     ├── Pull fra MCR (online)           │
│     ├── Eksporter til tar               │
│     └── Overfar til offline-miljo       │
│                                         │
│  4. Offline deployment                  │
│     ├── Importer container              │
│     ├── Mount lisensfil                 │
│     └── Kjor uten nettverkstilkobling   │
└─────────────────────────────────────────┘

Lisensnedlasting og container-oppsett

# Steg 1: Last ned lisens (online maskin)
docker run --rm -it \
  -v /host/license:/license \
  mcr.microsoft.com/azure-cognitive-services/speechservices/speech-to-text \
  eula=accept \
  billing=https://my-resource.cognitiveservices.azure.com \
  apikey=<API_KEY> \
  DownloadLicense=True \
  Mounts:License=/license

# Steg 2: Eksporter container image
docker save \
  mcr.microsoft.com/azure-cognitive-services/speechservices/speech-to-text \
  -o speech-to-text.tar

# Steg 3: Overfar til offline-miljo (USB, etc.)
# Kopier speech-to-text.tar og lisensfil

# Steg 4: Importer pa offline-maskin
docker load -i speech-to-text.tar

# Steg 5: Kjor uten nettverkstilkobling
docker run --rm -it -p 5000:5000 \
  -v /host/license:/license \
  mcr.microsoft.com/azure-cognitive-services/speechservices/speech-to-text \
  eula=accept \
  Mounts:License=/license \
  Mounts:Output=/output

ONNX Runtime — helt lokale modeller

For scenarioer uten Docker- eller lisensbehov:

# Helt lokal inferens med ONNX Runtime
# Ingen skyavhengighet, ingen lisens, ingen Docker
import onnxruntime as ort
import numpy as np

# Last modell fra lokal disk
session = ort.InferenceSession(
    "/models/document-classifier.onnx",
    providers=['CPUExecutionProvider']
)

# Kjor inferens
input_name = session.get_inputs()[0].name
result = session.run(None, {
    input_name: np.array(preprocessed_data)
})

Azure Stack Edge i disconnected modus

Nkkelforskjeller offline vs online

Funksjon Online Disconnected
Azure Portal management Ja Nei — kun lokal UI
Kubernetes workloads Full Arc-stotte Lokal kubectl
Container registry Azure Container Registry Edge Container Registry
Overvaking Azure Monitor Lokalt Kubernetes dashboard
Azure Arc Full integrasjon Ikke tilgjengelig
VM-styring Arc-enabled VMs Lokalt PowerShell/UI
GPU workloads Full stotte Full stotte (forklargjort)

Forberedelse for disconnected drift

# Forbered Azure Stack Edge for offline-bruk
# (Gjores mens enheten fortsatt er online)

# 1. Aktiver enhet via Azure Portal
# 2. Enable Kubernetes
Set-AzureDataBoxEdgeRole -Name "Kubernetes" -Activated

# 3. Deploy alle nodvendige container workloads
kubectl apply -f ai-inference-deployment.yaml

# 4. Push container images til Edge Container Registry
docker tag my-model:v1 ecr.edgehostname:31001/my-model:v1
docker push ecr.edgehostname:31001/my-model:v1

# 5. Verifiser at alt kjorer
kubectl get pods -A

# 6. Koble fra nettverket

Data Reconciliation Strategies

Utfordringer med frakoblet data

Nar AI-systemer kjorer offline, oppstar det utfordringer med:

  • Data som genereres lokalt ma synkroniseres nar tilkobling gjenopprettes
  • Modellresultater fra offline-perioden ma valideres
  • Konflikter mellom lokale og sentrale data
  • Versjonshaandtering av modeller og konfigurasjoner

Rekonsilieringsmoenstre

Moenster Beskrivelse Bruksomrade
Store-and-Forward Buffer lokalt, send nar tilkoblet IoT-data, loggfiler
Event Sourcing Registrer alle hendelser, replay sentralt Audit, compliance
Last-Write-Wins Siste endring vinner ved konflikt Enkle konfigurasjoner
Merge/CRDTs Konfliktfri sammenslaing Distribuerte datasett
Manual Review Menneske loeser konflikter Kritiske beslutninger

Store-and-Forward med IoT Hub

# Lokal buffering og batch-synkronisering
import json
import os
from datetime import datetime
from pathlib import Path

class OfflineBuffer:
    def __init__(self, buffer_dir="/data/offline-buffer"):
        self.buffer_dir = Path(buffer_dir)
        self.buffer_dir.mkdir(parents=True, exist_ok=True)

    def store_result(self, inference_result, metadata):
        """Lagre inferensresultat lokalt."""
        entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "result": inference_result,
            "metadata": metadata,
            "synced": False
        }
        filepath = self.buffer_dir / f"{entry['timestamp']}.json"
        filepath.write_text(json.dumps(entry))
        return filepath

    def get_unsynced(self):
        """Hent alle usynkroniserte resultater."""
        results = []
        for f in sorted(self.buffer_dir.glob("*.json")):
            entry = json.loads(f.read_text())
            if not entry.get("synced"):
                results.append((f, entry))
        return results

    async def sync_to_cloud(self, iot_client):
        """Synkroniser bufferede resultater til sky."""
        unsynced = self.get_unsynced()
        for filepath, entry in unsynced:
            try:
                await iot_client.send_message(
                    json.dumps(entry)
                )
                entry["synced"] = True
                entry["synced_at"] = datetime.utcnow().isoformat()
                filepath.write_text(json.dumps(entry))
            except Exception as e:
                # Fortsett med neste — proev igjen senere
                print(f"Sync feilet for {filepath}: {e}")
                break

Modellversjon-rekonsiliering

# model-sync-config.yaml
sync:
  strategy: "check-on-connect"
  model_registry:
    cloud: "https://ml-workspace.azureml.net/models"
    local: "/models/registry.json"
  conflict_resolution: "cloud-wins"
  validation:
    enabled: true
    test_dataset: "/data/validation/standard-test.json"
    min_accuracy: 0.95
  rollback:
    enabled: true
    keep_previous: 3

Local Cache and Sync

Flerlags cache-arkitektur

┌──────────────────────────────────────────┐
│  Lag 1: In-Memory Cache (Redis)          │
│  TTL: 1 time │ Storrelse: 2 GB           │
│  Hoyest prioritet, raskest tilgang       │
├──────────────────────────────────────────┤
│  Lag 2: Lokal Disk Cache (SSD)           │
│  TTL: 7 dager │ Storrelse: 100 GB        │
│  Modellvekter, embeddings, resultater    │
├──────────────────────────────────────────┤
│  Lag 3: Persistent Storage (S2D/NAS)     │
│  Ingen TTL │ Storrelse: 1 TB+            │
│  Full modellhistorikk, treningsdata      │
├──────────────────────────────────────────┤
│  Lag 4: Cloud Sync (Azure Blob)          │
│  Synk ved tilkobling                     │
│  Master-kopi av modeller og data         │
└──────────────────────────────────────────┘

Synkroniseringslogikk

# Intelligent sync-manager
class SyncManager:
    def __init__(self, config):
        self.local_store = LocalModelStore(config.local_path)
        self.cloud_store = AzureBlobStore(config.connection_string)
        self.sync_log = SyncLog(config.log_path)

    async def check_connectivity(self):
        """Sjekk om skytilkobling er tilgjengelig."""
        try:
            await self.cloud_store.ping()
            return True
        except Exception:
            return False

    async def sync_models(self):
        """Synkroniser modeller mellom lokal og sky."""
        if not await self.check_connectivity():
            return SyncResult(status="offline", synced=0)

        # Hent manifest fra sky
        cloud_manifest = await self.cloud_store.get_manifest()
        local_manifest = self.local_store.get_manifest()

        updates = []
        for model_id, cloud_info in cloud_manifest.items():
            local_info = local_manifest.get(model_id)

            if not local_info:
                # Ny modell — last ned
                updates.append(("download", model_id, cloud_info))
            elif cloud_info['version'] > local_info['version']:
                # Oppdatert modell — last ned ny versjon
                updates.append(("update", model_id, cloud_info))

        # Utfor oppdateringer med prioritering
        for action, model_id, info in sorted(
            updates, key=lambda x: x[2].get('priority', 99)
        ):
            try:
                await self._download_model(model_id, info)
                self.sync_log.record(action, model_id, "success")
            except Exception as e:
                self.sync_log.record(action, model_id, f"failed: {e}")

        # Last opp lokale resultater
        await self._upload_offline_results()

        return SyncResult(
            status="synced",
            synced=len(updates)
        )

Fallback Inference Patterns

Degraderingsstrategier

Strategi Nar Implementasjon
Full model → Lite model GPU svikter Fall tilbake til CPU-modell
Cloud model → Edge model Nettverk nede Bruk lokal kvantisert modell
ML-modell → Regler Modell korrupt Regelbasert fallback
Real-time → Batch Overbelastning Buffer foresporsler
AI → Manuell Alt feiler Eskalering til menneske

Implementasjon av fallback-kaskade

class ResilientInferenceEngine:
    def __init__(self):
        self.engines = [
            CloudInference(endpoint="https://foundry.azure.com"),
            LocalGPUInference(model_path="/models/full-model.onnx"),
            LocalCPUInference(model_path="/models/quantized-int8.onnx"),
            RuleBasedFallback(rules_path="/config/rules.json")
        ]

    async def infer(self, input_data, timeout=5.0):
        """Prover inferensmotorer i prioritetsrekkefoolge."""
        last_error = None

        for engine in self.engines:
            try:
                result = await asyncio.wait_for(
                    engine.predict(input_data),
                    timeout=timeout
                )
                return InferenceResult(
                    prediction=result,
                    engine=engine.name,
                    confidence=engine.confidence_level,
                    degraded=(engine != self.engines[0])
                )
            except asyncio.TimeoutError:
                last_error = f"{engine.name}: timeout"
                timeout = min(timeout * 2, 30)  # Okt timeout for neste
            except Exception as e:
                last_error = f"{engine.name}: {e}"
                continue

        # Alle motorer feilet — returner fallback
        return InferenceResult(
            prediction=None,
            engine="none",
            confidence=0,
            degraded=True,
            error=last_error
        )

Health monitoring for offline-systemer

# health-check-config.yaml
health_checks:
  model_health:
    interval: 60s
    checks:
      - name: model_loaded
        type: inference_test
        input: "test_input.json"
        expected_output_shape: [1, 10]
      - name: gpu_available
        type: nvidia_smi
        min_free_memory_mb: 1024
      - name: disk_space
        type: disk
        min_free_gb: 10

  degradation_rules:
    - condition: "gpu_available == false"
      action: "switch_to_cpu_model"
    - condition: "disk_space < 5GB"
      action: "cleanup_old_models"
    - condition: "model_loaded == false"
      action: "reload_from_cache"
      max_retries: 3

Scenarioer for norsk offentlig sektor

Forsvar og beredskap

Scenario Tilkoblingsstatus Losning
Feltoperasjoner Helt frakoblet ONNX Runtime + kvantiserte modeller
Kjoretoy/fartoy Periodisk Store-and-forward + modellsynk
Kommandoplass Begrenset Azure Stack Edge disconnected
Sambandssystemer Ustabil Fallback-kaskade med degradering

Helse

Scenario Tilkoblingsstatus Losning
Ambulanse Ustabil Lokal bildeanalyse (ONNX)
Distriktslege Periodisk Disconnected containers (tale, tekst)
Sykehus DR Beredskap Azure Local med offline-kapasitet
Feltsykehus Frakoblet Forhndslastede modeller

Transport og infrastruktur

Scenario Tilkoblingsstatus Losning
Tunneler Frakoblet Edge-inferens med kamerasystem
Fartsoyvervaking Ustabil Lokal objektdeteksjon
Trafikkanalyse Periodisk Batch-analyse med synk
Fergedrift Variabel Hybrid med sky-fallback

Lisens- og kostnadshensyn

Disconnected containers prismodell

Prismodell Beskrivelse Krav
Commitment tier Arlig forpliktelse Enterprise Agreement
Per-tjeneste Betal per container-tjeneste Godkjent soknad
Kalenderars-binding 12 mnd minimum Automatisk fornyelse

Viktige begrensninger

  • Lisensfil har utlopsdato — krever periodisk fornyelse
  • Enterprise Agreement eller tilsvarende er obligatorisk
  • Godkjenningsprosess tar opptil 10 virkedager
  • Ingen SLA for disconnected containers (kunde eier infrastruktur)
  • Ikke tilgjengelig i sovereign clouds (kun public cloud for opprettelse)

For Cosmo

  • Azure tilbyr et komplett spekter for frakoblet AI — fra Foundry Tools disconnected containers (tale, tekst, bilde) til helt lokale ONNX Runtime-modeller uten skyavhengighet.
  • Disconnected containers krever Enterprise Agreement og godkjenning — lisensfiler har utlopsdato og ma fornyes, men gir tilgang til de samme API-ene som sky-tjenestene.
  • Fallback-kaskader er essensielt for paalitelig edge-AI — design alltid med degraderingsstrategi: sky → lokal GPU → lokal CPU → regler → manuell.
  • Store-and-forward med rekonsilieringslogikk loser utfordringen med data som genereres offline — buffer lokalt, synkroniser ved tilkobling, hndter konflikter.
  • For norsk offentlig sektor er frakoblet AI kritisk for beredskap, forsvar og helse — Azure Stack Edge og ONNX Runtime gir funksjonskapasitet uten internett-avhengighet.