ms-ai-architect/skills/ms-ai-engineering/references/agent-orchestration/agent-latency-optimization.md
Kjell Tore Guttormsen ddce43d8b2 feat(ms-ai-architect): Spor 1 — Port-1-substrat migrert på 4 ikke-advisor-skills (243 Source + 327 Type + 325 TOC + stale-verified poison fjernet) [skip-docs]
Steg 9 (R4): unified migrate-corpus.mjs --write over engineering/governance/
infrastructure/security. 327 filer mutert, verified=null, prosa byte-identisk
(fra første ## seksjon), advisor urørt (0 endringer).

To applier-fixes oppdaget under kjøring (TDD, RED→GREEN):
- insertHeaderFields: anker faller nå tilbake når en meta-linje selv passerer
  500B (2 filer pakket et avsnitt i **Status:** → Type/Source landet utenfor
  scan-vinduet, applierens post-write-assertion fanget + restaurerte).
- normalizeStaleVerified: fjerner nå ALLE stale non-date **Verified:** i
  500B-vinduet, inkl. stray body-dup rett under --- (9 mlops-genaiops-filer var
  ellers falskt "verified"/fresh, droppet fra worklist). Operatør-godkjent
  utvidelse av carve-out; kun stray metadata-linjer, aldri prosa.

test-transform-criterion: precondition oppdatert til post-migrasjons-sannhet
(fila bærer nå Source). Suite 728/728 grønn.
2026-07-04 10:19:11 +02:00

14 KiB

Agent Latency Optimization and Performance Tuning

Last updated: 2026-02 Status: GA Category: Agent Orchestration & Automation Type: reference


Innhold

Introduksjon

Responstid er en kritisk kvalitetsfaktor for AI-agenter. Brukere forventer sub-sekund initial respons og fullstendige svar innen få sekunder. I multi-agent-systemer akkumuleres latency gjennom hver orkestreringsbeslutning, modellkall, verktøyinvokasjon og data-retrieval. Uten bevisst optimalisering kan en agent som involverer 3-4 LLM-kall raskt nå 15-30 sekunders total responstid, noe som er uakseptabelt for interaktive scenarier.

Azure OpenAI tilbyr flere mekanismer for latency-optimalisering: modellvalg (GPT-4o mini for lavest latency), streaming for opplevd rask respons, prompt-caching for gjentatte forespørsler, og batching for asynkrone workloads. I tillegg gir Azure API Management som AI Gateway mulighet for intelligent routing, semantic caching og request-deduplication.

For agentsystemer spesifikt er de største latency-driverne antall sekvensielle LLM-kall, størrelsen på kontekstvinduer, og ventetid på eksterne verktøy. Parallellisering av uavhengige operasjoner, prefetching av sannsynlige data-behov, og async-patterns for verktøybruk er de mest effektive optimaliseringene.

Kjernekomponenter

Komponent Formål Teknologi
Streaming Reduser opplevd latency Azure OpenAI streaming, SSE
Prompt Caching Reduser time-to-first-token for gjentatte prefixer Azure OpenAI prompt caching
Request Batching Samle bulk-operasjoner Azure OpenAI Batch API
Semantic Caching Cache semantisk like forespørsler APIM semantic caching policy
Model Selection Velg riktig modell for oppgavens krav GPT-4o mini, GPT-4o, Model Router
Async Patterns Parallelliser uavhengige operasjoner C# async/await, Python asyncio

Latency-anatomi for agentsystemer

Typisk breakdown

┌─────────────────────────────────────────────────────┐
│ Total agent response: ~8-15 sekunder (uten opt.)    │
│                                                      │
│  Router LLM-kall:          ~0.5-1.5s                │
│  RAG retrieval:             ~0.3-1.0s               │
│  Specialist LLM-kall:      ~2-5s                    │
│  Tool invocation (API):    ~0.5-3s                  │
│  Response formatting:       ~0.5-1.5s               │
│  Content filtering:         ~0.1-0.3s               │
│                                                      │
│ Etter optimalisering:      ~2-5 sekunder            │
└─────────────────────────────────────────────────────┘

Latency-metrikker

Metrikk Beskrivelse Måling
Time to First Token (TTFT) Tid til første token i streamed respons Azure Monitor, streaming
End-to-End Request Time Total tid for komplett respons API Gateway metrics
Token Generation Rate Tokens per sekund under generering Calculated metric
Tool Call Latency Tid brukt på verktøyinvokasjoner Custom spans
Orchestration Overhead Tid brukt i routing/orkestrering Custom spans

Response Streaming

Implementering med Semantic Kernel

// Streaming reduserer opplevd latency dramatisk
public async IAsyncEnumerable<string> StreamAgentResponse(
    ChatCompletionAgent agent,
    string userMessage,
    AgentThread thread)
{
    var message = new ChatMessageContent(
        AuthorRole.User, userMessage);

    await foreach (var chunk in
        agent.InvokeStreamingAsync(message, thread))
    {
        if (!string.IsNullOrEmpty(chunk.Content))
        {
            yield return chunk.Content;
        }
    }
}

// Bruk med SignalR for web-klienter
public class AgentHub : Hub
{
    public async Task SendMessage(string query)
    {
        await foreach (var token in
            _orchestrator.StreamAgentResponse(query))
        {
            await Clients.Caller.SendAsync("ReceiveToken", token);
        }
        await Clients.Caller.SendAsync("ResponseComplete");
    }
}

Streaming med Azure OpenAI direkte

import asyncio
from openai import AsyncAzureOpenAI

client = AsyncAzureOpenAI(
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_key=os.environ["AZURE_OPENAI_KEY"],
    api_version="2024-12-01-preview"
)

async def stream_response(messages: list):
    stream = await client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        stream=True,
        # Optimaliseringer
        max_tokens=500,  # Begrens generering
        temperature=0.3,  # Lavere = raskere konvergens
    )

    async for chunk in stream:
        if chunk.choices[0].delta.content:
            yield chunk.choices[0].delta.content

Request Batching

Azure OpenAI Batch API

For ikke-interaktive workloads tilbyr Batch API 50% kostnadsreduksjon og høyere throughput:

# Batch API for bulk-operasjoner (24-timers SLA)
import json
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_key=os.environ["AZURE_OPENAI_KEY"],
    api_version="2024-12-01-preview"
)

# Opprett batch-fil med JSONL
batch_requests = []
for i, query in enumerate(evaluation_queries):
    batch_requests.append({
        "custom_id": f"eval-{i}",
        "method": "POST",
        "url": "/chat/completions",
        "body": {
            "model": "gpt-4o-mini",
            "messages": [
                {"role": "system", "content": "Evaluer følgende..."},
                {"role": "user", "content": query}
            ],
            "max_tokens": 200
        }
    })

# Skriv JSONL-fil
with open("batch_input.jsonl", "w") as f:
    for req in batch_requests:
        f.write(json.dumps(req) + "\n")

# Last opp og start batch
file = client.files.create(
    file=open("batch_input.jsonl", "rb"),
    purpose="batch"
)
batch = client.batches.create(
    input_file_id=file.id,
    endpoint="/chat/completions",
    completion_window="24h"
)

Prefetching Strategies

Proaktiv data-henting

import asyncio

class PrefetchingOrchestrator:
    """Parallelliser data-henting med LLM-klassifisering"""

    async def process_query(self, query: str) -> str:
        # Start routing og data-henting PARALLELT
        routing_task = asyncio.create_task(
            self.classify_intent(query)
        )
        # Prefetch de mest sannsynlige datakildene
        common_data_task = asyncio.create_task(
            self.fetch_common_context(query)
        )

        # Vent på routing-resultat
        routing = await routing_task
        common_data = await common_data_task

        # Hent spesialisert data basert på routing
        specialized_data = await self.fetch_specialized_data(
            routing.target_agent, query
        )

        # Kombiner kontekst og generer svar
        context = {**common_data, **specialized_data}
        return await self.generate_response(
            routing.target_agent, query, context
        )

    async def fetch_common_context(self, query: str) -> dict:
        """Hent data som sannsynligvis trengs uansett agent"""
        user_profile, recent_history = await asyncio.gather(
            self.get_user_profile(),
            self.get_recent_interactions(limit=3)
        )
        return {
            "user_profile": user_profile,
            "recent_history": recent_history
        }

Semantic Caching med APIM

APIM Semantic Cache Policy

<!-- Azure API Management semantic caching for AI-forespørsler -->
<policies>
    <inbound>
        <!-- Sjekk semantic cache før videresending -->
        <azure-openai-semantic-cache-lookup
            score-threshold="0.90"
            embeddings-backend-id="embedding-backend"
            embeddings-backend-auth="system-assigned" />
    </inbound>
    <outbound>
        <!-- Lagre respons i cache for fremtidige like forespørsler -->
        <azure-openai-semantic-cache-store
            duration="3600" />
    </outbound>
</policies>

Cache-invalidering

class AgentCacheManager:
    """Håndter cache-invalidering for agent-systemer"""

    def __init__(self, redis_client):
        self.redis = redis_client

    async def cache_response(
        self, query_embedding: list, response: str, ttl: int = 3600
    ):
        key = self._embedding_to_key(query_embedding)
        await self.redis.setex(key, ttl, response)

    async def invalidate_on_knowledge_update(
        self, updated_sources: list
    ):
        """Når kunnskapsbase oppdateres, invalider relaterte cacher"""
        # Fjern alle cache-entries som refererer til oppdaterte kilder
        for source in updated_sources:
            pattern = f"agent_cache:*:{source}:*"
            keys = await self.redis.keys(pattern)
            if keys:
                await self.redis.delete(*keys)

    async def invalidate_on_model_change(self):
        """Ved modellbytte, flush hele cachen"""
        await self.redis.flushdb()

Async-Awaitable Patterns

Parallell verktøyinvokasjon

// Parallelliser uavhengige tool calls
public class OptimizedAgentToolHandler
{
    public async Task<ToolResults> ExecuteToolsParallel(
        IEnumerable<ToolCall> toolCalls)
    {
        // Grupper verktøykall etter avhengigheter
        var independentCalls = toolCalls
            .Where(t => !t.HasDependencies)
            .ToList();
        var dependentCalls = toolCalls
            .Where(t => t.HasDependencies)
            .ToList();

        // Kjør uavhengige kall parallelt
        var parallelResults = await Task.WhenAll(
            independentCalls.Select(tool =>
                ExecuteToolWithTimeout(tool, TimeSpan.FromSeconds(5))
            )
        );

        // Kjør avhengige kall sekvensielt
        var sequentialResults = new List<ToolResult>();
        foreach (var tool in dependentCalls)
        {
            var result = await ExecuteToolWithTimeout(
                tool, TimeSpan.FromSeconds(5));
            sequentialResults.Add(result);
        }

        return new ToolResults(parallelResults, sequentialResults);
    }

    private async Task<ToolResult> ExecuteToolWithTimeout(
        ToolCall tool, TimeSpan timeout)
    {
        using var cts = new CancellationTokenSource(timeout);
        try
        {
            return await tool.ExecuteAsync(cts.Token);
        }
        catch (OperationCanceledException)
        {
            return ToolResult.Timeout(tool.Name);
        }
    }
}

Model Selection for Latency

Modell-latency sammenligning

Modell TTFT (median) Tokens/sek Anbefalt bruk
gpt-4o-mini ~200ms ~120 Routing, klassifisering, enkle svar
gpt-4o ~400ms ~80 Komplekse resonneringer, RAG
gpt-4.1 ~350ms ~90 Generell agent-bruk
gpt-4.1-mini ~180ms ~130 Høyvolum, lav-latency
gpt-4.1-nano ~100ms ~150 Ultra-lav latency, enkel klassifisering

Tiered Model Strategy

# Velg modell basert på oppgavens kompleksitet
MODEL_TIERS = {
    "routing": "gpt-4.1-nano",       # Ultra-rask routing
    "simple_qa": "gpt-4o-mini",       # Enkle spørsmål
    "rag_synthesis": "gpt-4o",        # RAG med resonnering
    "complex_analysis": "gpt-4.1",    # Dype analyser
    "evaluation": "gpt-4o-mini",      # Batch-evaluering
}

async def select_model_for_task(task_type: str, context: dict) -> str:
    base_model = MODEL_TIERS.get(task_type, "gpt-4o-mini")

    # Override basert på kontekst
    if context.get("token_count", 0) > 4000:
        # Store kontekster trenger kraftigere modell
        return "gpt-4o"
    if context.get("requires_reasoning", False):
        return "gpt-4.1"

    return base_model

Norsk offentlig sektor

Aspekt Krav Latency-implikasjon
Data residency Azure Norway East +20-50ms vs. West Europe
Content filtering Obligatorisk for offentlig sektor +100-200ms per request
Audit logging Full logging av alle kall +10-30ms overhead
VNet isolation Private endpoints +5-15ms for DNS resolution
Token-grenser Budget-begrensninger Bruk mindre modeller der mulig

Beslutningsrammeverk

Scenario Anbefaling Begrunnelse
Chat-bot med < 2s krav Streaming + gpt-4o-mini + semantic cache Lavest opplevd latency
Multi-agent med 3+ steg Parallelliser uavhengige steg + prefetching Reduserer sekvensielle ventetider
Høy-volum asynkront Batch API + gpt-4o-mini 50% kostnadsreduksjon, 24h SLA
RAG med store dokumenter Prompt caching + chunk-optimalisering Reduser TTFT for store prompts
Global distribusjon APIM multi-region + Front Door Nearest-region routing

For Cosmo

  • Streaming er alltid-på for interaktive agenter -- det er den enkelttiltaket som mest forbedrer brukeropplevelsen, selv om total tid forblir lik.
  • Model tiering er obligatorisk for kostnadseffektiv latency-optimalisering -- bruk nano/mini for routing og klassifisering, gpt-4o for kompleks resonnering.
  • Parallelliser aggressivt: Prefetch data mens routing pågår, kjør uavhengige verktøykall parallelt, og bruk async/await konsekvent.
  • Semantic caching i APIM gir dramatisk forbedring for repetitive forespørsler -- spesielt i kundestøtte-scenarier der mange brukere stiller lignende spørsmål.
  • Mål alltid TTFT og total latency separat -- TTFT driver brukeropplevelse, total latency driver kostnad. Optimaliser begge men prioriter TTFT for interaktive scenarier.