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.