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>
17 KiB
Streaming and Real-Time RAG Responses
Last updated: 2026-02 Status: GA Category: RAG Architecture & Semantic Search
Introduksjon
Streaming av RAG-responser innebærer å returnere generert innhold token-for-token eller i små chunks mens modellen prosesserer, fremfor å vente på hele svaret. Dette gir dramatisk redusert opplevd latency og bedre brukeropplevelse ved at tekst vises progressivt på samme måte som ChatGPT og andre moderne AI-grensesnitt.
I tradisjonelle RAG-implementeringer sender klienten en forespørsel, systemet søker i vektordatabasen, augmenterer prompten med kontekst, og LLM-en genererer et komplett svar før noe returneres. Dette kan ta flere sekunder eller minutter for komplekse spørsmål. Med streaming begynner teksten å vises umiddelbart etter første token er generert, noe som gir brukeren tilbakemelding om at systemet arbeider og lar dem begynne å lese svaret mens resten genereres.
Azure OpenAI Service støtter streaming via Server-Sent Events (SSE) i både Chat Completions API og den nyere Responses API. SSE er en HTTP-basert protokoll som holder en langvarig forbindelse åpen og sender datachunks til klienten etterhvert som de blir tilgjengelige. For RAG-applikasjoner betyr dette at retrieval-fasen skjer først (vanligvis ikke-streamet), deretter starter streaming av generert tekst umiddelbart når LLM-en begynner å produsere output.
Kjernekomponenter
Server-Sent Events (SSE)
SSE er den primære teknologien for streaming fra Azure OpenAI:
| Komponent | Beskrivelse |
|---|---|
| Protokoll | Enveiskommunikasjon over HTTP (server → klient) |
| Content-Type | text/event-stream |
| Event format | data: <JSON>\n\n per event |
| Avslutning | data: [DONE] signal når streaming er ferdig |
| Forbindelse | Langvarig HTTP-tilkobling med Connection: keep-alive |
| Chunk-kodning | Transfer-Encoding: chunked uten Content-Length |
Azure OpenAI Streaming API
Chat Completions API (stream: true):
- Enkleste implementasjon for streaming
- Returnerer
ChatCompletionChunkobjekter - Hver chunk inneholder delta med ny tekst (
choices[0].delta.content) - Støtter function calling (argumenter streams også)
- Eksempel response:
{"choices":[{"delta":{"content":"Hello"},"index":0}]}
Responses API (stream: true):
- Nyere API som kombinerer Chat Completions og Assistants
- Støtter både synkron og asynkron (background) streaming
- Event-basert format:
response.output_text.delta - Kan gjenoppta streaming fra en
sequence_numberved avbrudd - Støtter stateful conversations med
previous_response_id
Streaming Content Types
I Semantic Kernel Agent Framework brukes spesialiserte content-typer:
| Type | Formål |
|---|---|
StreamingChatMessageContent |
Container for streaming-meldinger |
StreamingTextContent |
Token-by-token tekstchunks |
StreamingFileReferenceContent |
Filreferanser under streaming |
StreamingAnnotationContent |
Metadata og citations i stream |
Client-side Buffering
Progressive rendering krever håndtering av:
- Partial tokens — inkomplette ord eller JSON-strukturer
- UI updates — effektiv re-render av chunks uten flimmering
- Function calls — pause i streaming når modellen kaller en funksjon
- Error handling — reconnect-logikk ved avbrudd
Arkitekturmønstre
Mønster 1: Standard RAG med Chat Completions Streaming
Bruk når: Enkel RAG-applikasjon med Azure Cognitive Search eller annen vektordb.
Fordeler:
- Enklest å implementere (én API-kall med
stream=true) - Lavest latency fra første token til bruker
- Kompatibel med alle Azure OpenAI modeller
Ulemper:
- Retrieval-fasen er ikke streambar (må vente på søkeresultater før streaming starter)
- Ingen innebygd støtte for gjenopptagelse ved avbrudd
Arkitektur:
User Query → Azure Cognitive Search (vector search)
→ Prompt augmentation (inject context)
→ Azure OpenAI Chat Completions (stream=true)
→ SSE stream → Client (progressive display)
Implementering:
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
# 1. Retrieval phase (ikke streamet)
search_results = azure_search_client.search(query, top=5)
context = "\n".join([doc['content'] for doc in search_results])
# 2. Augmentation + streaming generation
messages = [
{"role": "system", "content": f"Answer based on: {context}"},
{"role": "user", "content": query}
]
stream = client.chat.completions.create(
model="gpt-4o",
messages=messages,
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end='', flush=True)
Mønster 2: Responses API med Background Streaming
Bruk når: Lange prosesser (reasoning modeller, kompleks research) som kan ta minutter.
Fordeler:
- Unngår timeouts på langvarige operasjoner
- Kan gjenoppta streaming fra
sequence_numberved avbrudd - Støtter async workflows (brukeren kan komme tilbake senere)
Ulemper:
- Høyere time-to-first-token latency enn synkron streaming
- Krever polling-logikk eller WebSocket for status-oppdateringer
Arkitektur:
User Query → RAG retrieval → Responses API (background=true, stream=true)
→ Poll status (in_progress) → Resume stream fra sequence_number
→ Display chunks progressivt → Final status (completed)
Implementering:
# Start background streaming response
response = client.responses.create(
model="o3",
input=augmented_prompt,
background=True,
stream=True
)
cursor = None
for event in response:
if event.type == 'response.output_text.delta':
print(event.delta, end='', flush=True)
cursor = event["sequence_number"]
# Ved avbrudd: gjenoppta fra cursor
# GET /responses/{response_id}?stream=true&starting_after={cursor}
Mønster 3: Semantic Kernel Agent med Callback
Bruk når: RAG med function calling, multi-turn conversations, behov for å håndtere intermediate steps.
Fordeler:
- Håndterer function call results i streaming-flyten
- Callback for intermediate messages (tool calls, partial results)
- Innebygd support i Semantic Kernel Agent Framework
Ulemper:
- Mer kompleks setup (krever agent framework)
- Overhead fra framework kan øke latency marginalt
Arkitektur:
User → Agent (invoke_stream) → RAG retrieval (via function)
→ Streaming response + callback for function results
→ Progressive display + intermediate step logging
Implementering:
from semantic_kernel.agents import AzureResponsesAgent
async def handle_intermediate(message: ChatMessageContent) -> None:
for item in message.items:
if isinstance(item, FunctionResultContent):
print(f"Retrieved: {item.result[:100]}...")
async for response in agent.invoke_stream(
messages=user_input,
thread=thread,
on_intermediate_message=handle_intermediate
):
print(response.content, end='', flush=True)
Beslutningsveiledning
Velg Streaming-mønster
| Scenario | Anbefalt mønster | Begrunnelse |
|---|---|---|
| RAG med Azure Cognitive Search, < 10s responstid | Chat Completions streaming | Enklest, lavest latency |
| RAG med reasoning modeller (o3, o1-pro), > 1 min | Responses API background streaming | Unngår timeouts |
| Agentic RAG med function calling | Semantic Kernel Agent | Callback-støtte for intermediate steps |
| RAG med flere søk (multi-hop) | Responses API stateful | Reuse context med previous_response_id |
| Real-time RAG med WebSocket | Custom med SSE → WebSocket bridge | Bedre browser-support, bidireksjonell kommunikasjon |
Vanlige feil
| Feil | Symptom | Løsning |
|---|---|---|
| Buffer timeout | Stream stopper midt i token | Sett request_timeout > 120s i backend settings |
| UI flimmering | Tekst hopper eller blinker | Bruk React/Vue streaming-biblioteker (react-markdown streaming) |
| Connection drop | Stream mister forbindelse | Implementer reconnect med sequence_number resume |
| Partial JSON | Function call argumenter er inkomplette | Buffer chunks til finish_reason == "function_call" |
| Cache interference | CDN cacher SSE-responser | Sett Cache-Control: no-cache header |
Røde flagg
- Streaming før retrieval er ferdig — vises som tomme eller irrelevante første tokens
- Ingen progress indicator — brukeren tror systemet har hengt seg
- Manglende error streaming — errors bør også vises progressivt (ikke bare status 500)
- Synkron retrieval i async context — blokkerer streaming-start
Integrasjon med Microsoft-stakken
Azure OpenAI Service
| Feature | Support | Notes |
|---|---|---|
| Chat Completions streaming | GA | stream=true parameter |
| Responses API streaming | GA | Event-based format |
| Background streaming | GA | For o3, o1-pro modeller |
| Resume streaming | GA | Via sequence_number |
| Function calling streaming | GA | Arguments streams token-by-token |
Azure Application Gateway
For SSE-trafikk gjennom Application Gateway:
Kritiske innstillinger:
- Response buffers — må være
disabled(ellers bufres hele responsen) - Request timeout — sett > streaming-forventet tid (f.eks. 300s)
- Backend headers —
Connection: keep-alive,Transfer-Encoding: chunked
Konfigurasjon:
{
"backendHttpSettings": {
"requestTimeout": 300,
"responseBuffering": false
}
}
Azure API Management
SSE-konfigurasjon krever:
- Route timeout — øk fra standard 30s til 300s+
- No caching — disable cache policies for SSE endpoints
- Passthrough mode — ikke transformer SSE events
Semantic Kernel
Agent Framework (C#, Python):
from semantic_kernel.agents import ChatCompletionAgent
agent = ChatCompletionAgent(...)
async for response in agent.invoke_stream(message, thread):
# response er StreamingChatMessageContent
print(response.content, end='', flush=True)
ChatHistory oppdateres kun etter full response er mottatt (ikke per chunk).
Power Platform
Power Automate støtter ikke native SSE-streaming. Workaround:
- Bruk polling-flow (sjekk status hver 2s)
- Eller WebSocket via Azure Functions bridge
Copilot Studio støtter streaming via SSE for custom connectors (preview).
Offentlig sektor (Norge)
Network Policies
SSE krever langvarige HTTP-forbindelser som kan trigge firewall-regler:
| Policy | Anbefaling |
|---|---|
| Idle timeout | Min. 300s for SSE-forbindelser |
| Connection limits | Whitelist Azure OpenAI FQDN for lengre forbindelser |
| Proxy compatibility | Test med organisasjonens proxy (noen buffer SSE) |
| TLS requirements | TLS 1.2+ (SSE over HTTPS) |
Kompetanse Norges nettverk: Hvis proxy buffer disabler SSE, bruk Azure API Management som mellommann med custom buffering.
Tilgjengelighet (WCAG)
Streaming text må være skjermleser-vennlig:
- ARIA live regions —
aria-live="polite"på streaming-container - Focus management — ikke flytt focus mens tekst streams
- Pause/resume — brukeren må kunne pause streaming (tilgjengelighetskrav)
- Skip to end — shortcut for å hoppe til ferdig svar
Eksempel:
<div role="log" aria-live="polite" aria-atomic="false">
<!-- Streaming text appends here -->
</div>
Personvern (GDPR)
Streaming påvirker logging:
- Ikke logg partial responses — vent til
[DONE]før logging - Redaction — PII-filtrering må skje server-side før streaming starter
- Audit trail — logg
sequence_numberfor replay-evne
Kostnad og lisensiering
Prismodell
Streaming koster det samme per token som ikke-streaming:
| Modell | Input (NOK/1K tokens) | Output (NOK/1K tokens) |
|---|---|---|
| gpt-4o | ~0.28 | ~1.12 |
| gpt-4o-mini | ~0.014 | ~0.056 |
| o3 (reasoning) | ~1.68 | ~6.72 |
Kostnadsoptimalisering:
- Stream kun når bruker venter (ikke for background jobs)
- Bruk
max_tokensfor å begrense lange responses - Cache retrieval-resultater (reduserer total tokens ved re-prompts)
Code Interpreter (Responses API)
Ved bruk av streaming med code_interpreter tool:
- Tilleggskostnad: 0.28 NOK/session (utover tokens)
- Session lifetime: 1 time (idle timeout 20 min)
- Simultane sessions: Hver parallel streaming med code_interpreter = ny session
Lisenskrav
| Tjeneste | Lisenskrav |
|---|---|
| Azure OpenAI | Azure subscription + OpenAI resource |
| Semantic Kernel | Open source (MIT) — ingen lisenskostnad |
| Application Gateway | Azure-kostnad (per gateway-time) |
| API Management | Per call/måned tier (Consumption for lavt volum) |
For arkitekten (Cosmo)
Spørsmål å stille kunden
- Forventet responstid? — Hvis > 30s, vurder background streaming.
- Brukerkontekst? — Chatbot (streaming obligatorisk) vs. batch report (streaming unødvendig).
- Network environment? — Proxy, firewall, idle timeouts kan blokkere SSE.
- Function calling? — Krever callback-logikk for å håndtere intermediate steps.
- Mobile vs. web? — Mobile app kan ha ustabil forbindelse → trenger resume-logikk.
- WCAG-krav? — Streaming må være pause-bar og skjermleser-kompatibel.
- Error handling? — Hvordan skal partial failures vises? (stream error chunks vs. abort)
- Token budget? — Streaming gjør det vanskelig å stoppe ved token-limit (pre-calculate max_tokens).
Fallgruver
| Fallgruve | Konsekvens | Unngå ved |
|---|---|---|
| Stream før retrieval | Tomme/irrelevante første tokens | Buffer retrieval-resultater før streaming starter |
| Ingen reconnect-logikk | Brukeren ser halvferdig svar | Implementer sequence_number resume |
| Synkron I/O i async context | Blokkerer streaming | Bruk asyncio i Python, async/await i C# |
Manglende Cache-Control |
CDN cacher SSE | Sett no-cache header på backend |
| Ingen progress feedback | Brukeren venter uten tilbakemelding | Vis spinner til første chunk arrives |
Anbefalinger per modenhetsnivå
Nivå 1 (POC):
- Bruk Chat Completions API med
stream=true - Ignorer error handling (fail fast)
- Bruk
print()for debugging (console output)
Nivå 2 (Pilot):
- Implementer reconnect-logikk med timeout
- Legg til ARIA live regions for tilgjengelighet
- Test med organisasjonens proxy/firewall
Nivå 3 (Produksjon):
- Bruk Responses API med background streaming for lange prosesser
- Implementer full observability (logg sequence_number, latency per chunk)
- A/B-test streaming vs. ikke-streaming for UX-gevinst
- Set opp Application Gateway med optimale SSE-innstillinger
Nivå 4 (Skalering):
- Implementer custom WebSocket-bridge for bedre mobile support
- Bruk Azure SignalR for multi-region streaming med fallback
- Implementer adaptive streaming (juster chunk-størrelse basert på nettverkshastighet)
Kilder og verifisering
Verified (fra MCP microsoft-learn)
- Azure OpenAI Responses API streaming: https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/responses (Verified: 2026-02)
- Semantic Kernel Agent streaming: https://learn.microsoft.com/en-us/semantic-kernel/frameworks/agent/agent-streaming (Verified: 2026-02)
- SSE med Application Gateway: https://learn.microsoft.com/en-us/azure/application-gateway/use-server-sent-events (Verified: 2026-02)
- Azure OpenAI REST API reference: https://learn.microsoft.com/en-us/azure/ai-foundry/openai/reference (Verified: 2026-02)
- Chat Completions API streaming: https://learn.microsoft.com/en-us/azure/ai-foundry/openai/reference#chat-completions (Verified: 2026-02)
Baseline (modellkunnskap)
- SSE standard (W3C EventSource): Baseline (standard protocol knowledge)
- WebSocket vs. SSE tradeoffs: Baseline (industry best practices)
- React streaming patterns: Baseline (frontend framework knowledge)
- WCAG streaming requirements: Baseline (accessibility standards)
Konfidensnivå per seksjon:
- Introduksjon: High (Verified via Responses API docs)
- Kjernekomponenter: High (Verified via REST API reference + Semantic Kernel docs)
- Arkitekturmønstre: High (Verified code samples from microsoft-learn)
- Beslutningsveiledning: Medium (Kombinasjon av verified patterns + experience-based)
- Integrasjon med Microsoft-stakken: High (Verified via Application Gateway + API Management docs)
- Offentlig sektor: Medium (Verified network policies + baseline tilgjengelighet)
- Kostnad: High (Verified via Azure OpenAI pricing 2026-02)
- For arkitekten: Medium (Experience-based best practices)
Denne kunnskapsreferansen er generert med MCP microsoft-learn search/fetch (2026-02) og representerer siste tilgjengelige dokumentasjon fra Microsoft Learn.