ms-ai-architect/skills/ms-ai-advisor/references/prompt-engineering/structured-output-formatting.md
Kjell Tore Guttormsen 3a73eeafdc refactor(ms-ai-architect): R13 del 1 — nøytraliser Cosmo-personaen i ref-korpusets headinger, etter å ha rettet en gate som var målt usann to ganger
Ordre 20260912T193441Z-7358817909. Steg 1 var ikke transformen, men å rette
roadmapens R13-gate og få den ratifisert. Gaten `grep -rl "Cosmo"
skills/*/references -> 0` var usann på to uavhengige måter:

1. Ordren fanget den første: 451 av forekomstene er Azure Cosmos DB, ekte
   produktinnhold. Diskriminatoren er ikke bokstaven «s» — `Cosmos <norsk
   substantiv>` er genitiv av personaen (`### Cosmos tonalitet`), mens
   `Cosmos DB`/`CosmosClient`/`cosmos_ru` er produkt.
2. Denne økten fant den andre: 132 persona-forekomster ligger i prosa,
   tabeller, dialog-replikker og proveniens-linjer. Heading-nøytralisering
   kan ikke nå dem, så «0 persona» er uoppnåelig også under den ratifiserte
   formen. Operatøren ratifiserte alternativ A: gaten speiler formen, og de
   132 bokføres til R13b/R14.

Tre korreksjoner av premisser som sto i ordren og STATE:
  «ca 320 produkt»   -> 451 (case-sensitivt nett manglet 327 lowercase
                        TOC-ankre + 99 identifikatorer; sann nevner 1 638)
  «169 headinger»    -> 401. 169 var `^## For Cosmo`-prefikset (168) og var
                        internt inkonsistent med sin egen topp-variant (204)
  «417 matcher ingen
   populasjon»       -> 417 er cosmo-headinger utenfor kodefences; briefens
                        nevner var reell hele tiden

Fence-bevissthet er målt skadelig, ikke nødvendig: begge toggle-regler er
gale på dette korpuset (naiv toggle skjuler en ekte heading i
chain-of-thought-prompting.md, CommonMark-regelen ubalanserer
service-level-documentation-dr.md). Fence-agnostisk deteksjon finner 401
heading-linjer i nøyaktig de samme 40 variantene som fence-bevisst finner
400 i — ingen kodeblokk-linje er byte-identisk til en persona-heading. Derfor
nøkles transformen på 40 enumererte heading-tekster og ignorerer fences. En
ukjent variant kaster; en slug-kollisjon kaster. Ingenting auto-fikses.

TOC-en regenereres ikke, den rettes kirurgisk: alle 327 persona-lenker hadde
lenketekst lik én av de 40 heading-tekstene og anker lik slugify av den
(327/327, 0 avvik), så heading og TOC-entry skrives i samme operasjon og
ingen mellomtilstand etterlater en død lenke.

Ratifisert målform: `For Cosmo`, `For Cosmo Skyberg` og `For arkitekten
(Cosmo)` konvergerer på `For arkitekten`. To filer kolliderte og er adjudisert
ved å lese dem, ikke ved regel.

Verifisering (alle 7 kriterier fra ordren):
  G1 persona på heading-linjer   401 -> 0
  G2 døde fragmentlenker         1 -> 1 (pre-eksisterende, unntatt)
  G3 produkt-forekomster         451 -> 451; `Cosmos DB|Azure Cosmos` 308 = 308
  de 3 kun-produkt-filene        byte-identiske
  nettet validert begge veier    injisert persona feller G1; genitiv feller G1;
                                 produkt-heading og de 3 filene passerer
  hele diffen                    802 heading-linjer + 654 TOC-linjer, ANNET = 0
  linjeantall                    728 lagt til = 728 slettet
  suite                          1120/1120 (1097 + 23 nye)
  validate-plugin                250 PASS / 0 FAIL
  stikkprøve                     10 filer, alle 5 skills, inkl. de 3 mest
                                 produkt-tunge (26/20/19) — kun heading+TOC

Utenfor scope, urørt: de 4 SKILL.md, de 23 commands, CLAUDE.md, README.md,
NOTICE.md, docs/ (alt R14).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 22:12:28 +02:00

17 KiB

Structured Output and JSON Mode

Last updated: 2026-06-24 Status: GA Category: Prompt Engineering & LLM Optimization


Introduksjon

Strukturert output er en teknikk som tvinger LLM-modeller til å følge et spesifikt JSON Schema som du definerer i API-kallet ditt. Dette er en betydelig forbedring over den eldre JSON Mode-funksjonen, som kun garanterte syntaktisk gyldig JSON, men ikke kunne sikre at outputen følger et bestemt skjema.

Strukturert output gjør det mulig å:

  • Definere nøyaktig hvilken datastruktur modellen skal returnere
  • Eliminere parsing-feil og validerings-overhead
  • Bygge robuste multi-steg workflows og integrasjoner
  • Bruke type-safe objekter direkte i koden (via Pydantic i Python, for eksempel)

JSON Mode (eldre metode) garanterer kun at outputen er gyldig JSON, men gir ingen kontroll over strukturen. Microsoft anbefaler å bruke structured outputs fremfor JSON mode for alle nye implementasjoner på GPT-4o og nyere modeller.

Viktig begrensning: Strukturert output støttes for øyeblikket ikke med "bring your own data"-scenarier (Azure AI Search-integrasjon), Assistants API, eller Foundry Agents Service.


Kjernekomponenter

Response Format Types

Type Beskrivelse Anbefalt bruk
text Standard tekstformat, ingen spesifikk struktur Generelle tekstrespons, kreativ skriving
json_object Garanterer syntaktisk gyldig JSON, men ingen schema-validering Legacy — erstattet av json_schema
json_schema Tvinger modellen til å følge et JSON Schema med strict mode Anbefalt for alle strukturerte output-behov

Structured Outputs med JSON Schema

Python-eksempel (Microsoft Entra ID auth):

from pydantic import BaseModel
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

token_provider = get_bearer_token_provider(
    DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"
)

client = OpenAI(
  base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
  api_key=token_provider,
)

class CalendarEvent(BaseModel):
    name: str
    date: str
    participants: list[str]

completion = client.beta.chat.completions.parse(
    model="gpt-4o",  # GPT-4o 2024-08-06 eller nyere
    messages=[
        {"role": "system", "content": "Extract the event information."},
        {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
    ],
    response_format=CalendarEvent,
)

event = completion.choices[0].message.parsed
print(event)  # name='Science Fair' date='Friday' participants=['Alice', 'Bob']

REST API-eksempel:

curl -X POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1/chat/completions \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [
      {"role": "system", "content": "Extract the event information."},
      {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "CalendarEventResponse",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "date": {"type": "string"},
            "participants": {
              "type": "array",
              "items": {"type": "string"}
            }
          },
          "required": ["name", "date", "participants"],
          "additionalProperties": false
        }
      }
    }
  }'

Function Calling med Structured Outputs

For function calling, aktiver structured outputs ved å sette strict: true i function-definisjonen.

Viktig: Strukturert output støtter ikke parallell function calling. Sett parallel_tool_calls: false når du bruker strict mode.

from pydantic import BaseModel
import openai
from openai import OpenAI

class GetDeliveryDate(BaseModel):
    order_id: str

tools = [openai.pydantic_function_tool(GetDeliveryDate)]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "You are a helpful customer support assistant."},
        {"role": "user", "content": "What's the delivery date for order #12345?"}
    ],
    tools=tools,
    parallel_tool_calls=False  # Påkrevd for structured outputs
)

Arkitekturmønstre

1. Data Extraction Pattern

Bruksområde: Trekk strukturert informasjon fra ustrukturert tekst (e-poster, kundehenvendelser, dokumenter).

Fordeler:

  • Ingen parsing-logikk nødvendig i applikasjonskoden
  • Type-safe objekter direkte fra API-et
  • Reduserer feilrate drastisk

Ulemper:

  • Krever GPT-4o eller nyere modeller
  • Økt token-forbruk sammenlignet med fritekst-output (marginal)

Eksempel:

class CustomerFeedback(BaseModel):
    sentiment: str  # "positive", "neutral", "negative"
    product_mentioned: list[str]
    issues: list[str]
    satisfaction_score: int  # 1-5

completion = client.beta.chat.completions.parse(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "Extract feedback details from customer email."},
        {"role": "user", "content": email_text}
    ],
    response_format=CustomerFeedback,
)

2. Multi-Step Workflow Pattern

Bruksområde: Bygge komplekse workflows der hvert steg produserer strukturert output som input til neste steg.

Fordeler:

  • Lettere debugging og logging
  • Kan cache mellomresultater
  • Enklere å parallellisere uavhengige steg

Ulemper:

  • Flere API-kall (økt latency og kostnad)
  • Må håndtere feil i hvert steg

Eksempel-workflow (fakta-sjekking):

  1. Steg 1: Trekk ut faktiske påstander fra tekst → list[Claim]
  2. Steg 2: Generer søkespørsmål for hver påstand → list[SearchQuery]
  3. Steg 3: Vurder pålitelighet basert på søkeresultater → FactCheckReport

3. Form-Filling Pattern

Bruksområde: Chatbots og assistenter som samler strukturert informasjon over flere meldinger.

Fordeler:

  • Garanterer at alle påkrevde felter fylles ut
  • Kan validere input underveis
  • Enklere å integrere med backend-systemer

Ulemper:

  • Kan føles rigid for brukere hvis ikke godt designet
  • Krever state management på klientsiden

Beslutningsveiledning

Når bruke Structured Outputs vs JSON Mode

Kriterium Bruk Structured Outputs Bruk JSON Mode Bruk fritekst
Trenger eksakt schema? ✅ ❌ ❌
Kun syntaktisk gyldig JSON? ✅ ✅ ❌
Kreativ eller fleksibel output? ❌ ❌ ✅
Integreres direkte med database? ✅ ⚠️ (må validere) ❌
Eldre modeller (GPT-3.5)? ❌ ✅ ✅
GPT-4o eller nyere? ✅ ⚠️ (deprecated) ✅

JSON Schema-begrensninger (strict mode)

Begrensning Detaljer
Nestingdybde Maks 5 nivåer
Totalt antall properties Maks 100 properties på tvers av hele schemat
Required fields Alle fields MÅ være required (bruk ["string", "null"] for optional)
additionalProperties MÅ være false for alle objekter
Root type Kan ikke være anyOf
Parallell function calling Ikke støttet med strict: true
Usupporterte keywords String: minLength, maxLength, pattern, format. Number: minimum, maximum, multipleOf. Objects: patternProperties, unevaluatedProperties, propertyNames, minProperties, maxProperties. Arrays: minItems, maxItems, uniqueItems, contains, minContains, maxContains, unevaluatedItems

Støttede typer: String, Number, Boolean, Integer, Object, Array, Enum, anyOf (nested).

Recursive schemas: Støttes via $ref og # (root recursion).


Integrasjon med Microsoft-stakken

Microsoft Foundry / Azure OpenAI

API-versjon: Structured outputs introdusert i 2024-08-01-preview, tilgjengelig i GA-versjon v1.

Støttede modeller (per 2026-06):

  • GPT-5-serien: gpt-5, gpt-5.1, gpt-5.1-chat, gpt-5.1-codex, gpt-5-pro, gpt-5-codex, gpt-5-mini, gpt-5-nano (hele serien støtter structured outputs)
  • GPT-4-serien: gpt-4o (2024-08-06, 2024-11-20), gpt-4.1, gpt-4.1-mini, gpt-4.1-nano
  • o-serien: o1, o3-mini, o3-pro, o4-mini
  • Codex: codex-mini (2025-05-16)

Ikke støttet med:

  • Assistants API
  • Foundry Agents Service
  • "Bring your own data" (Azure AI Search)
  • Audio-preview modeller (gpt-4o-audio-preview og gpt-4o-mini-audio-preview, versjon 2024-12-17)

Semantic Kernel

Semantic Kernel støtter structured outputs via AzureAssistantAgent.configure_response_format():

from pydantic import BaseModel

class ResponseModel(BaseModel):
    response: str
    items: list[str]

client, model = AzureAssistantAgent.setup_resources()

definition = await client.beta.assistants.create(
    model=model,
    name="DataExtractor",
    instructions="Extract structured data from text.",
    response_format=AzureAssistantAgent.configure_response_format(ResponseModel),
)

Fordel: Enklere å integrere med plugins og orchestration-logikk.

Power Platform / Copilot Studio

Status: Structured outputs er ikke direkte eksponert i Copilot Studio low-code interface per 2026-02. Må brukes via custom connectors eller Power Automate med HTTP-actions mot Azure OpenAI REST API.

Workaround:

  1. Opprett custom connector med OpenAI-endepunkt
  2. Send response_format i request body
  3. Parse JSON-output i Power Automate

Offentlig sektor (Norge)

Dataminimering og GDPR

Strukturert output kan hjelpe med dataminimering (GDPR Art. 5.1c) ved å:

  • Kun trekke ut spesifikt definerte datafelter
  • Unngå at modellen returnerer persondata som ikke er nødvendig
  • Lettere å implementere anonymisering i output-schema

Anbefaling: Definer schema slik at sensitive felter (personnummer, helseopplysninger) kun inkluderes hvis eksplisitt nødvendig.

AI Act (EU)

Strukturert output kan bidra til traceability (Art. 12):

  • Logg input-schema og output-schema for hver request
  • Enklere å demonstrere at modellen ikke produserer uventet output
  • Støtter risikovurdering ved å definere "tillatt" output-format

Forvaltningsloven og forsvarlighetskrav

§ 6 (Forsvarlighetskravet): Strukturert output øker forutsigbarheten i automatiserte vedtak:

  • Reduserer risiko for at LLM-output ikke kan valideres
  • Gjør det enklere å dokumentere hvordan AI-systemet fungerer
  • Støtter krav om transparens i automatiserte beslutninger

Eksempel (saksbehandling):

class CaseAssessment(BaseModel):
    case_id: str
    decision: str  # "approve", "reject", "manual_review"
    legal_basis: list[str]  # Lovparagrafer
    reasoning: str
    confidence_score: float  # 0.0-1.0

# Output er strukturert og kan logges/auditeres

Schrems II og datasuverenitet

Strukturert output endrer ikke hvor data prosesseres, men:

  • Kan brukes til å filtrere ut sensitive data før de sendes til Azure OpenAI
  • Gjør det enklere å implementere "privacy-preserving prompts"

Anbefaling: Kombiner med Azure Private Endpoint og Customer Managed Keys for maksimal kontroll.


Kostnad og lisensiering

Prismodell

Strukturert output medfører ingen ekstra kostnad utover standard token-prising for Azure OpenAI. Du betaler for:

  • Input tokens (prompt + schema-definisjon)
  • Output tokens (JSON-strukturert output)

Observasjon: Schema-definisjonen (JSON Schema) legges til som del av system-prompt, så den teller mot input tokens. For komplekse schemas med mange properties, kan dette øke kostnadene marginalt (typisk 50-200 tokens per request).

Lisensiering

Krever Azure OpenAI-ressurs med støttet modell (se over). Ingen spesiell lisens eller feature flag nødvendig.

Microsoft 365 Copilot: Structured outputs er ikke tilgjengelig via M365 Copilot API per 2026-02. Må bruke Azure OpenAI direkte.


For arkitekten

Spørsmål å stille kunden

  1. Datakvalitet og validering

    • Hvilke datafelter er kritiske, og hvilke er "nice to have"?
    • Trenger dere streng validering av output, eller kan dere tolerere noe fleksibilitet?
    • Finnes det eksisterende JSON schemas dere bruker (OpenAPI, JSON Schema, etc.)?
  2. Workflow-kompleksitet

    • Er dette en enkel "input → output"-transformasjon, eller del av en flerstegs pipeline?
    • Trenger dere å cache eller persistere mellomresultater?
    • Skal outputen integreres direkte med database, API, eller annet system?
  3. Modenhet og risikotoleranse

    • Hva skjer hvis modellen ikke klarer å generere gyldig output? (fallback-strategi)
    • Har dere logging og monitoring for å oppdage schema-violations?
    • Trenger dere human-in-the-loop for kritiske beslutninger?
  4. Ytelse og kostnad

    • Hva er volumet av requests? (viktig for å estimere kostnader)
    • Hva er akseptabel latency? (structured outputs kan være noe tregere enn fritekst)
    • Kan dere cache schemas på klientsiden for å redusere input tokens?
  5. Sikkerhets- og compliance-krav

    • Inneholder outputen persondata eller forretningskritisk informasjon?
    • Må outputen logges for audit-trail (Forvaltningsloven)?
    • Trenger dere å filtrere ut sensitive data i output-schema?

Fallgruver å unngå

Fallgruve Hvorfor det skjer Hvordan unngå
For komplekse schemas Over 100 properties eller 5 nestingsnivåer → request feiler Bryt ned i mindre schemas, bruk multi-step workflow
Alle fields som required Glemmer at JSON Schema strict mode krever alle fields i required Bruk ["string", "null"] for optional fields
Glemmer additionalProperties: false Strict mode krever dette for alle objekter Valider schema med tool før prod
Parallell function calling Kombinerer strict: true med parallel_tool_calls: true Sett parallel_tool_calls: false eksplisitt
JSON Mode vs Structured Outputs Bruker deprecated json_object for GPT-4o Migrer til json_schema med strict: true
Manglende feilhåndtering Anta at modellen alltid returnerer gyldig output Sjekk finish_reason for "length" eller "content_filter"

Anbefalinger per modenhetsnivå

Nivå 1: Utforsker (PoC)

  • Start med enkle schemas (< 10 properties, flat struktur)
  • Bruk Pydantic i Python for rask prototyping
  • Test mot GPT-4o-mini for kostnadseffektiv utvikling
  • Eksperimenter med JSON Mode først hvis dere er usikre på schema-design

Nivå 2: Pilot (Testing i prod-lignende miljø)

  • Definer strenge schemas med alle required fields
  • Implementer validering av output (selv om structured outputs garanterer schema)
  • Logg schema-violations (hvis modellen returnerer finish_reason: "length")
  • Mål latency og token-forbruk for å optimalisere

Nivå 3: Produksjon (Skala og drift)

  • Bruk caching for schemas som gjenbrukes ofte
  • Implementer fallback til JSON Mode hvis strict mode feiler
  • Overvåk error rates og juster schemas basert på faktisk bruk
  • Dokumenter schema-endringer i API-contract (versjonering)

Nivå 4: Optimalisert (Kontinuerlig forbedring)

  • Bruk recursive schemas for dynamiske datastrukturer (trær, grafer)
  • Kombiner med function calling for agentic workflows
  • Implementer A/B-testing av ulike schema-designs
  • Automatiser schema-generering fra eksisterende datamodeller (SQL, OpenAPI, etc.)

Kilder og verifisering

Microsoft Learn (Verified)

URL Tema Konfidensnivå
Structured Outputs Guide Hovedguide, API-eksempler, schema-begrensninger Verified (2026-02)
JSON Mode Guide JSON Mode (legacy), sammenlikning med structured outputs Verified (2026-02)
API Reference (v1) REST API-detaljer, response_format konfigurasjon Verified (2026-02)
Prompt Engineering Guide Output structure best practices Verified (2026-02)

Azure OpenAI API-versjon

  • Introduced: 2024-08-01-preview
  • GA: v1 (2026-02)

Konfidensvurdering per seksjon

Seksjon Konfidens Kilde
Kjernekomponenter Verified Microsoft Learn, code samples
Arkitekturmønstre Baseline Generalisert fra best practices
Beslutningsveiledning Verified Microsoft Learn, API docs
Microsoft-integrasjon Verified Microsoft Learn, Semantic Kernel docs
Offentlig sektor Baseline GDPR/AI Act-prinsipper, ikke AI-spesifikk guidance
Kostnad og lisensiering Verified Azure OpenAI prising (2026-02)
For arkitekten Baseline Erfaring og best practices

Oppsummering: Structured outputs er anbefalt standard for alle nye implementasjoner som krever strukturert data fra Azure OpenAI. JSON Mode bør kun brukes for legacy-støtte eller der strict schema-validering ikke er nødvendig.