Observabilitet for AI: OpenTelemetry i inferensforløb

Det korte svar er: kun hvis du kan se, hvad der foregår bag kulissen. I takt med at sprog- og billedmodeller flytter fra laboratoriet til kritiske forretnings­processer, vokser behovet for observabilitet eksplosivt

Hvor vi tidligere talte om CPU-load og memory-footprints, handler det nu om helt nye signaler: token-forbrug, prompt-kvalitet, hallucinationsrate og inferens-latency. Uden dyb indsigt i disse metrikker risikerer organisationer at stå tilbage med uforudsigelige omkostninger, utilfredse brugere - og i værste fald beslutninger baseret på fejlagtige svar.

Heldigvis behøver AI-inferens ikke være en sort boks. Med OpenTelemetry - det åbne standard­rammeværk, der allerede har revolutioneret klassisk applikations­overvågning - er vi nu i stand til at mappe hele inferenskæden fra brugerens første klik til det sidste token streamer ud af modelserveren. Og netop dét er nøglen til at sætte SLO’er, reducere risiko og optimere cost/performance.

I denne artikel dykker vi ned i:

  • hvorfor observabilitet er kritisk for AI-systemer i produktion,
  • hvordan OpenTelemetry giver os nye, semantiske konventioner til AI/LLM-kald,
  • en trin-for-trin opskrift på end-to-end instrumentering af inferenskæden,
  • og ikke mindst hvordan du omsætter data til dashboards, alarmer og løbende forbedringer.

Uanset om du bygger et simpelt chatbot-endpoint eller et fuldskala RAG-setup, vil du efter denne læsning stå stærkere til at måle, forstå og forbedre dine AI-løsninger. Lad os åbne boksen og se, hvad der faktisk sker, når algoritmen svarer - velkommen til fremtidens observabilitet.

Observabilitet for AI: OpenTelemetry i inferensforløb

Hvorfor observabilitet i AI‑inferens er kritisk

AI-løsninger er for længst flyttet fra laboratoriet og ind i forretningskritiske workflows - fra kundeservice-chatbots til automatiseret dokumentanalyse. Når modellen først kører i produktion, forsvinder den ofte ind i et operativt mørke: vi ser kun input og output, men ikke hvorfor responstider pludselig stiger, om svarkvaliteten glider, eller om omkostningerne løber løbsk. Operatørerne mangler dermed det telemetriske kompas, der gør det muligt at styre kvaliteten proaktivt.

Træning vs. Inferens - To helt forskellige overvågningsopgaver

Træningsfase Inferensfase
Data-volumen TB-PB data, batch-orienteret Enkeltkald i real- eller nær-real-tid
Nøgletal Loss, accuracy, GPU-udnyttelse Latency, success-rate, cost pr. kald, token-forbrug
Risikobillede Overfitting, convergens Hallucinationer, timeouts, datadrift
Tidsvindue Dage til uger Millisekunder til sekunder

Kort sagt: hvor træning kan klares med periodisk batch-analyse, kræver inferens løbende telemetri for at holde SLA’er og budgetter.

Fire målbare dimensioner i inferens

  1. Latency
    Brugerens tålmodighed er kort; p95- og p99-latency er ofte direkte koblet til churn og konverteringsrate. Uventede spikes kan skyldes køer, cache-misses eller GPU-saturation.
  2. Svarkvalitet
    Automatiserede guardrails, offline-human review og rating-feeds skal kobles til tracing-data, så man kan korrelere hallucinationer med konkrete model-versioner eller prompt-ændringer.
  3. Omkostning pr. kald
    Hver token koster; uden transparens kan et uskyldigt prompt-skifte fordoble forbruget. Granulær måling af token-ind/ud, cache-hit-rate og accelerator-tid er nødvendig for at styre budgetter.
  4. Driftsstabilitet
    Fejlrater, timeout-andele og nedbrud i downstream-services (vektordatabaser, køer) skal ses samlet for at undgå kaskadefejl.

Sådan reducerer observabilitet risiko

  • Hallucinationer & toxic output: Ved at logge prompt-ID og model-version i samme trace som kvalitetsfeedback kan man hurtigt rulle tilbage efter en deploy, der øger fejlraten.
  • Timeouts: Distribuerede spans afslører flaskehalse (fx langsom embedding-generering) før brugerne mærker det.
  • Datafejl & konceptdrift: Kontinuerlig sammenligning af upstream-features og produktionstekster mod historiske distributions-statistikker giver early warning på uventede mønstre.

Fra synlighed til service level objectives

Når de ovenstående signaler er instrumenteret, kan organisationen etablere SLO’er - fx “p95-latency < 800 ms” eller “≤1 % hallucinationer per 1 000 kald”. De gør det muligt at:

  • Få klare error budgets og sætte incident-alarmer, før brugerne klager.
  • Balancere cost vs. quality: højere temperatur eller større kontekstvindue måles direkte mod økonomien.
  • A/B-teste nye prompt-skabeloner med objektive succes-/kost-metrikker.

Uden denne telemetri er AI-drift et lotteri; med den får teamet et instrumentbræt, der kan styre både oplevet kvalitet og bundlinje.


OpenTelemetry til AI: centrale begreber og semantiske konventioner

OpenTelemetry (OTEL) er blevet det de-facto fælles sprog for observabilitet på tværs af cloud-native applikationer, og det gælder i stigende grad også for AI-drevne inferenskæder. Nedenfor finder du en praktisk introduktion til, hvordan OTEL’s grundelementer - traces, metrics og logs - kan udnyttes i AI-kontekst, hvilke semantiske konventioner der giver mening for LLM-kald, samt hvilke arkitekturvalg der sikrer, at du både får dyb indsigt og overholder compliance-krav.

1. Grundelementerne: Traces, spans, metrics og logs

  1. Traces repræsenterer den samlede rejse for én brugerforespørgsel igennem hele inferenskæden - fra API-gateway til prompt, embeddings, modelserver og tilbage til klienten.
  2. Spans er de enkelte trin i rejsen. Hvert microservice-kald, RAG-slag i vektor-DB eller token-stream fra modellen får sit eget span med tidsstempel, attributter og evt. events.
  3. Metrics summerer helbred og performance over tid (f.eks. llm.request.duration eller gpu.utilization). De driver dashboards, SLO’er og alarmer.
  4. Logs giver rå kontekst til fejlfinding - fx den fulde prompt, stack traces eller output fra guardrails - og kan kobles til enten spans (in-context logs) eller stå alene.

2. Kontekstpropagering i en ai-pipeline

Nøglen til en samlet trace er kontekstpropagering. OTEL udpeger trace_id og span_id, som sendes videre via HTTP-/gRPC-headers eller messaging-metadata.

  • Ved streaming token respons (Server-Sent Events eller WebSockets) bør du fortsætte det oprindelige span_id, men sende events for hvert token-batch for at undgå et overstort antal spans.
  • I asynkrone køer (f.eks. Kafka) tilføjes tracing-headers på producer-siden og løftes videre som nye spans på consumer-siden.
  • Hvis du benytter funktioner som tjeneste (FaaS) til efterbehandling, skal runtime-miljøet konfigureres til automatisk at parse og videresende OTEL-headers.

3. Semantiske konventioner til llm-kald

Attribut Datatype Eksempelværdi Beskrivelse
ai.model.name string gpt-4o Modelnavn eller SKU
ai.model.version string 2024-05-24 Git-sha eller vendor-revision
ai.prompt.tokens_in int 512 Antal inputtokens
ai.response.tokens_out int 127 Antal genererede tokens
ai.cache.hit bool true Cache-resultat på prompt-hash
ai.guardrail.triggered bool false Om safety/quality-filter slog til
ai.cost.usd double 0.0023 Direkte omkostning for kaldet
net.peer.ip string 10.4.2.17 Modelserverens IP (for latency-analyse)

OTEL-fællesskabet arbejder på en AI Semantic Convention; ovenstående er et pragmatisk udgangspunkt for at standardisere attributnavne, så tværgående analyse bliver lettere.

4. Otel collector som navet

OTEL Collector fungerer som et observabilitets-hub:

  • Receivers: HTTP/gRPC, OTLP, FluentBit logs, Prometheus metrics.
  • Processors: batch, attributes (tilføj/omdøb), transform (PII-maskering), tail_sampling (se næste afsnit).
  • Exporters: Grafana Tempo, Jaeger, OTLP til managed APM, BigQuery, S3 til langtidsholdbar logopbevaring.

Ved at centralisere pipelines kan du sikre, at samme filtrering, kryptering og routing gælder på tværs af miljøer og leverandører.

5. Samplingstrategier - Undgå støj, bevar guldet

LLM-traces kan hurtigt eksplodere i datamængde; et eneste chat-UI kan affyre tusindvis af token-events i minuttet. Derfor bør du kombinere flere samplingmetoder:

  • Probabilistisk head-sampling: Vælg f.eks. 5 % af alle indkommende requests tidligt for at reducere belastningen.
  • Tail-based sampling: Collector’en venter, til trace’en er færdig, og beslutter at gemme alle spans for traces, der opfylder betingelser som
    • span.duration > 2 s (latency-outliers)
    • ai.guardrail.triggered == true
    • status_code != 0 (fejl)
  • Token-count sampling: Gem kun fuld prompts/responser, hvis tokens_in < 2000 for at undgå datavolumen-eksplosion ved lange konversationer.

6. Dataminimering, redaction og compliance

AI-observabilitet er sjældent kun et teknisk anliggende - GDPR, Enterprise Security og kontraktlige krav skal også overholdes. Følgende mønstre er gode at implementere tidligt:

  1. PII-detektion og maskering i Collector’en via regex eller ML-klassificering, før data forlader VPC’en.
  2. Prompt-hashing: Gem kun SHA-256 hashes af brugerinput for at støtte cache-hit-analyse og deduplikering uden at lagre selve teksten.
  3. Role-based access control (RBAC) i APM-værktøjet, så kun et begrænset analysteam må se de få traces med fuld payload.
  4. Retention-politikker: Gem traces i 14 dage, metrics i 90 dage, logs i 30 dage (eksempel). Længere retention kræver pseudonymisering.
  5. Encryption-at-rest og in-transit via TLS 1.2+ for alle OTLP pipelines.

7. Næste skridt

Når de semantiske konventioner er på plads, og Collector’en kører, bliver næste skridt at instrumentere selve inferenskæden - fra API-gateway til GPU-kerneltid. Det dækker vi i næste afsnit, hvor vi stiller skarpt på, hvordan de nævnte spans, events og attributter implementeres i praksis.


End‑to‑end instrumentering af inferenskæden

En AI-inferensrejse kan ligne nedenstående forenklede sekvens:

  1. KlientAPI-gateway
  2. Gateway beriger med prompt-skabelonRAG-pipeline
  3. RAG kalder Embedding-serviceVektordatabase
  4. Fuldt prompt sendes til Modelserver / LLM
  5. Output går gennem Post-processing & sikkerhedsfiltre
  6. Svar returneres til Klient

Uden konsistent instrumentering mister vi sammenhængen mellem hop 1-6. OpenTelemetry (OTel) løser dette ved traces (ét end-to-end ID) og spans (deloperationer). Nedenfor får du en praktisk opskrift.

2. Design af trace-modellen

Komponent Span-navn Nøglerelaterede attributter
API-gateway gateway.request http.method, http.route, user.id, x-request-id
Prompt-builder prompt.render template.name, template.version, input.tokens, redacted=true
Embedding-service embedding.encode model.name, model.version, vector.dim, cache.hit
Vektordatabase vector.search db.system="redis", top_k, matches, latency.ms
Modelserver llm.infer model.name, model.size, provider, tokens.in, tokens.out, gpu.id
Safety-filter guardrail.check policy.version, blocked, reasoning.id

Denne tabel bliver til en hierarkisk trace, hvor hvert span ligger under gateway.request. Hvis RAG-pipeline eller modelkald er asynkrone, anvend span links for stadig at forbinde sig til roden.

3. Instrumentering trin for trin

  • Aktivér OTel-middleware (f.eks. otel-gin, otel-fastify eller NGINX-modul).
  • Indsæt traceparent + baggage i alle udgående HTTP-kald.
  • Tilføj en middleware der beregner estimate_tokens for forespørgslen - nyttigt til præ-emptiv cost-monitorering.
  • Eksponer edge-metrics (RPS, 4xx, 5xx) til dashboards med samme service.name.

3.2 prompt-skabeloner

  • Opret et child-span prompt.render lige før prompten sendes videre.
  • Gem kun hash eller template.id som attribut - selve promptteksten kan sendes i Event med redaction policy for GDPR/compliance.
  • Mål render-latency og tokens_before (evt. via tiktoken eller lignende).

  • Embedding-kald: cache.hit=true/false, latency.ms, embedding.model.
  • Vector-DB: registrér top_k, matches_returned, vector_score.avg, samt om query blev filtered.
  • Hvis der bruges batch-encoding eller streaming, anvend AddEvent for hver batch/chunk.

3.4 køer & streaming

Mens HTTP kan bære traceparent, kræver messaging (Kafka, RabbitMQ, NATS) context propagation i headers eller message body.

  1. Ved produce - opret span queue.send og injicér context i headers.
  2. Ved consume - ekstrahér context, start span queue.process (linked til queue.send for fan-in/out scenarier).
  3. Brug SpanStatus for at markere timeouts, retries og DLQ (dead letter queue).

3.5 modelserver & accelerator-metrics

  • Wrap selve POST /completions med span llm.infer.
  • Ved streaming tokens: skyd AddEvent("token") pr. N tokens (f.eks. hver 10.) for at undgå telemetrispam.
  • Indsaml GPU-specifikke resource metrics (SM-util, vRAM, temperatur) via OTel Collector + NVIDIA exporter, og link resource.attributes { "gpu.id" } til spans via baggage.
  • Udregn cost_usd = (tokens_in+tokens_out) × model.unit_price og læg som metric.

3.6 post-processing & guardrails

Sikkerhedsfiltre (toxicity, PII, jailbreak-detektion) bør være egne spans guardrail.check. Attributter:

  • blocked: boolean
  • reason: "profane", "pii", "copyright" ...
  • policy.version: semver for governance/audit

4. Fejlhåndtering og statuskoder

Brug OTel’s SpanStatus:

  • UNSET: OK
  • ERROR + exception.type, exception.message, stacktrace
  • Omsæt model-fejl (quota-exceeded, overloaded) til canonical codes for samlede SLA-grafer.

5. Cache-effekt og cold start

Tilføj attributten cache.hit på relevante spans (prompt-cache, embedding-cache, RAG-docs). En derived metric som:

cache_hit_rate = sum(cache.hit == true) / total_requests

kan visualiseres pr. time for at identificere cold-start mønstre.

Når en brugerforespørgsel forker til flere parallelle modelkald eller baggrunds-embeddings, behold overblikket:

  • Bevar primær trace_id, men opret nye spans med links til roden.
  • Eksempel: RAG forud-beriger indeks; denne batch-job-trace linker til alle klienter der senere genbruger de embeddings.

7. Fra rå data til indsigt

Når OTel-Collector strømmer spans til et backend (Grafana Tempo, Jaeger, Elastic APM, Honeycomb), sammenkobles de med:

  • Metrics: exporter llm_latency_histogram, token_consumption, gpu_utilization
  • Logs: tilføj trace_id i log-korrelationen for nem root-cause-analyse.
  • Dashboards: korrelér p95-latency med cache-hitrate og GPU-util.

8. Collector-tips

  • Tail-based sampling - behold alle traces hvor llm.infer.tokens_out > 4000 ELLER guardrail.blocked=true.
  • Batch processor - saml spans pr. 10k eller 5 sek., så streaming token-events ikke oversvømmer netværket.
  • Attribute filter - maskér user_content feltet før eksport for at overholde GDPR/ISO-27001.

Med denne ende-til-ende opskrift får du reproducerbare, sammenhængende traces, der binder brugeroplevelse, tokenøkonomi og infrastruktur sammen - fundamentet for datadrevne forbedringer af dine AI-applikationer.


Fra data til handling: dashboards, SLO’er og løbende forbedring

Inden dashboards og alerts er der brug for et fælles sprog om, hvad “god oplevelse” egentlig er. Start med SLO’er (Service-Level Objectives), der kan måles direkte i OpenTelemetry-strømmen:

Domæne Metric SLO-eksempel Relevans
Latency llm.request.duration (ms) p95 < 800 ms Brugeroplevelse, UX-flow
Succesrate llm.request.success_ratio > 99 % Stabilitet, fejlbudget
Omkostning llm.token.cost_usd ⩾ 90 % af kald < 0,001 $ Budgetstyring
Guardrails llm.guardrail.block_rate < 0,5 % Sikkerhed & compliance
Drift-/konceptdrift llm.embedding.drift_score < 0,3 (KS-score) Datakvalitet

Når SLO’er er formaliseret, kan de omdannes til fejlbudgetter: “Hvor mange SLI-overtrædelser tåler vi pr. kvartal?” - og dermed balancere innovation (f.eks. hurtigere modelskifte) mod stabil drift.

Byg dashboards, der forbinder oplevet kvalitet med tekniske signaler

  1. Sammenkæd niveauer: Læg et “business lens” øverst (konverteringsrate, CSAT), derefter model-KPI’er (precision/recall, hallucination-score) og nederst infrastruktur (GPU-udnyttelse, cache-hit).
  2. Brug OTEL dimensions: model.name, model.version, tenant.id, prompt.template giver slicebare dashboards (“Hvilke kunder rammes af stigende latency?”).
  3. Inkludér distributionsgrafer: Box-plots for token-latency eller heatmaps over døgnet afslører kø-spidser.
  4. Flet logs og traces: Link fra tidsseriepunkt til den konkrete trace/span, så udviklere kan hoppe direkte til rå prompt/response (med PII-redaction).

Alerts, som mennesker gider reagere på

  • Alert på SLO-brud, ikke raw metrics: “Fejlbudget 50 % brugt” er mere handlingsbart end “p95 latency > 900 ms”.
  • Rate-limiter frem for pager-storm: Tail-based sampling gør det muligt at alarmerne baseres på de 5 % mest langsomme kald.
  • Runbooks i payload: Inkludér link til playbook: “Hvis GPU-queue length > 10 → skalér nodegruppe inference-a100”.

Opdag drifts- og konceptdrift samt datakvalitetsproblemer

Modelperformance ændrer sig, når virkeligheden gør. Automatisér detektion:

  • Statistisk monitorering: KS- eller PSI-score på embedding-distributionshaggle (embedding.drift_score).
  • Canary sam-/async traces: Kør 1-5 % af trafikken igennem en “skygge-model” og sammenlign kvalitets-metrics.
  • Prompt health-checks: Daglige syntetiske prompts med kendt facit afslører pludselige hallucinationer eller policy-regressioner.
  • Data lineage: Gem span.links fra databaser og feature-stores for at se, hvilke upstream-ændringer der rammer modellen.

A/b-tests & løbende prompt-tuning

  1. Routing: Lad API-gatewayen tilføje ab.group attribut til trace-context.
  2. Off-policy evaluation: Re-score svar offline med eval-modeller, og push resultatet som OTEL span.events.
  3. Rapid rollback: Når SLO’er for gruppe B underperformer 3 successive windows, autoskift til gruppe A.

Cost/performance-optimering på baggrund af telemetri

Overlay token-omkostning med latency pr. modelversion:

  • Cost heatmap: Tokens pr. svar vs. tid; identificér prompts med høj “tokens-per-word”.
  • Autoskalering: OTA (OpenTelemetry-Aware) HPA-strategi baseret på queue_depth og gpu.utilization.
  • Cache ROI: Mål llm.cache.hit_rate og cache.save_usd (beregnet attribut) for at beslutte RAM-/SSD-størrelse.

Governance: Retention, adgangsstyring og audit

  • Dataminimering: Prompt og svar lagres kun hashed eller maskeret (pii.redacted=true).
  • Retention-politik: Traces med error=true gemmes 90 dage, øvrige 30 dage.
  • RBAC/ABAC: Data-scienstists må se embeddings, men ikke rå PII; brug OTEL Collector pipelines med attributes/deny.
  • Audit-log: Hver ændring af SLO, model eller prompt-skabelon emitterer et audit.event span med Git-sha.

Trinvis udrulning: Fra pilot til fuld produktion

  1. Pilotfase: Indsaml fuld trace-dækning (100 % sample) for at kalibrere SLO’er og definere dashboards.
  2. Beta / limited GA: Indfør tail-based sampling & alerting; test incident-runbooks.
  3. Fuld GA: Slå fejlbudget-policy til; kør løbende A/B-eksperimenter; evaluer cost-SLO’er månedligt.
  4. Kontinuerlig forbedring: Kvartalsvis retro på SLO-targets, modelversioner og governance-krav.

Når observabilitetsdata bliver omsat til klare SLO’er, visuelle dashboards og automatiske feedback-loops, flytter AI-systemet sig fra “fascinerende eksperiment” til forretningskritisk tjeneste, der kan drives, skaleres og forbedres på linje med enhver anden moden software-platform.