Reference files, test fixtures, the playground demo project and one design document now use generic, fictitious examples (buildings, energy, water, grants, municipal services). The playground demo (17 fixtures plus the embedded demo state) tells one consistent story: a municipal customer chatbot that pre-screens housing-benefit applications, classified under Annex III point 5(a). The embedded demo copies were edited in place rather than regenerated, because they already carry newer AI Act dates than the fixture files. Legal text is unchanged. Test semantics are unchanged. Four dark-theme onboarding screenshots with outdated placeholder text are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
15 KiB
Prompt Caching for Performance
Last updated: 2026-06-19 Status: GA Category: Performance & Scalability Type: reference Source: https://learn.microsoft.com/azure/foundry/openai/concepts/provisioned-throughput
Innhold
- Introduksjon
- Kjernekomponenter
- Cache Eligibility Requirements
- Prefix Strategy Design
- Cost Reduction Calculation
- Cache Invalidation
- Norsk offentlig sektor
- Beslutningsrammeverk
- Referanser
- For arkitekten
Introduksjon
Azure OpenAI prompt caching er en innebygd mekanisme som reduserer latens og kostnad for forespørsler med identiske prefixer. Når de første 1024+ tokens i en prompt er identiske med en tidligere forespørsel, gjenbruker tjenesten de allerede beregnede token-representasjonene i stedet for å prosessere dem på nytt. Dette gir raskere time-to-first-token (TTFT) og lavere kostnad — cached tokens faktureres med rabatt for Standard deployments og opptil 100% rabatt for Provisioned (PTU) deployments.
Prompt caching er automatisk aktivert for alle støttede modeller (GPT-4o og nyere) uten ekstra konfigurasjon. Cachen er basert på en hash av de første ~256 tokens og krever minimum 1024 identiske tokens for å trigge. Etter den initiale 1024-token terskelen caches ytterligere identiske tokens i blokker på 128. Cacher tømmes typisk innen 5-10 minutter uten aktivitet og alltid innen 24 timer.
For norsk offentlig sektor der AI-applikasjoner ofte har lange, statiske system-prompts (inkludert regelverk, instruksjoner og eksempler), er prompt caching en svært effektiv optimaliseringsstrategi som kan gi 30-50% kostnadsreduksjon uten noen endring i output-kvalitet.
Kjernekomponenter
| Komponent | Formål | Teknologi |
|---|---|---|
| Prompt Cache | Automatisk caching av identiske prefixer | Azure OpenAI |
| prompt_cache_key | Valgfri parameter for å påvirke cache routing | Azure OpenAI API |
| cached_tokens | API-respons felt som viser cache hits | prompt_tokens_details |
| Semantic Cache | Ekstern cache for semantisk like forespørsler | Azure Cosmos DB |
| Multi-layer Caching | Kombinert caching-strategi | Arkitektur-mønster |
Cache Eligibility Requirements
Tekniske krav for prompt caching
# Krav for at prompt caching skal fungere:
CACHE_REQUIREMENTS = {
"minimum_prefix_length": 1024, # Tokens
"hash_prefix_length": 256, # Tokens brukt for routing-hash
"subsequent_block_size": 128, # Etter 1024, cache i 128-blokker
"cache_ttl_inactive": "5-10 min",
"cache_ttl_max": "24 timer",
"cross_subscription": False, # Cache deles IKKE mellom abonnement
"supported_models": [
"gpt-4o-*",
"gpt-4o-mini-*",
"gpt-4.1-*",
"gpt-4.1-mini-*",
"gpt-4.1-nano-*",
"o1-*",
"o3-*",
"o3-mini-*"
],
"supported_operations": [
"chat-completions",
"completions",
"responses",
"real-time"
]
}
# Sjekk om en prompt er cache-eligible
def is_cache_eligible(messages: list[dict], model: str = "gpt-4o") -> dict:
"""Check if a prompt is eligible for caching."""
import tiktoken
enc = tiktoken.encoding_for_model(model)
# Beregn total tokens for alle meldinger
total_tokens = 0
for msg in messages:
total_tokens += len(enc.encode(msg["content"]))
total_tokens += 4 # Role tokens overhead
return {
"total_tokens": total_tokens,
"eligible": total_tokens >= 1024,
"cacheable_tokens": max(0, (total_tokens // 128) * 128)
if total_tokens >= 1024 else 0,
"recommendation": (
"Eligible for caching" if total_tokens >= 1024
else f"Need {1024 - total_tokens} more tokens in prefix"
)
}
Prefix Strategy Design
Optimaliser prompt-struktur for caching
def design_cacheable_prompt(
system_instructions: str,
few_shot_examples: list[dict],
reference_documents: str,
user_query: str
) -> tuple[list[dict], dict]:
"""
Design prompt with optimal structure for caching.
Prinsipp: Statisk innhold FØRST, dynamisk innhold SIST.
Alt fra starten til det dynamiske innholdet caches.
"""
messages = []
# --- CACHEABLE PREFIX START ---
# 1. System prompt (statisk per applikasjon)
messages.append({
"role": "system",
"content": system_instructions
})
# 2. Few-shot eksempler (statisk per oppgave)
for example in few_shot_examples:
messages.append({"role": "user", "content": example["input"]})
messages.append({"role": "assistant", "content": example["output"]})
# 3. Referansedokumenter (statisk per sesjon)
if reference_documents:
messages.append({
"role": "user",
"content": f"Referansemateriale:\n\n{reference_documents}"
})
messages.append({
"role": "assistant",
"content": "Forstått. Jeg vil bruke referansematerialet."
})
# --- CACHEABLE PREFIX SLUTT ---
# 4. Dynamisk brukerforespørsel (varierer — IKKE cached)
messages.append({
"role": "user",
"content": user_query
})
# Beregn cache-statistikk
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4o")
static_tokens = sum(
len(enc.encode(m["content"])) + 4
for m in messages[:-1] # Alt unntatt siste melding
)
dynamic_tokens = len(enc.encode(user_query)) + 4
stats = {
"static_prefix_tokens": static_tokens,
"dynamic_tokens": dynamic_tokens,
"cache_eligible": static_tokens >= 1024,
"cache_hit_savings_pct": round(
static_tokens / (static_tokens + dynamic_tokens) * 100, 1
) if static_tokens >= 1024 else 0
}
return messages, stats
# Eksempel: Saksbehandler-assistent for Direktoratet for digital tjenesteutvikling
messages, stats = design_cacheable_prompt(
system_instructions="""Du er en AI-assistent for saksbehandlere i
Direktoratet for digital tjenesteutvikling. Du hjelper med å analysere klager på vedtak om
tilskudd, vurdere om klagen har grunnlag, og foreslå svar.
Regelverk du skal referere til:
- Tilskuddsordningens forskrift
- Reglement for økonomistyring i staten
- Forvaltningsloven § 28-36 (klagebehandling)
Format: Alltid bruk overskrifter, vurder hvert punkt separat,
og avslutt med en samlet anbefaling.""",
few_shot_examples=[
{
"input": "Klage: Jeg fikk avslag på søknad om driftstilskudd...",
"output": "## Vurdering\n### Regelverksvurdering..."
},
{
"input": "Klage: Tilskuddet mitt ble krevd tilbakebetalt...",
"output": "## Vurdering\n### Regelverksvurdering..."
}
],
reference_documents="Vedtaket av 15.01.2025 om avslag...",
user_query="Analyser denne nye klagen: ..."
)
print(f"Cacheable prefix: {stats['static_prefix_tokens']} tokens")
print(f"Cache savings: ~{stats['cache_hit_savings_pct']}%")
prompt_cache_key for forbedret hit rate
from openai import AzureOpenAI
client = AzureOpenAI(
azure_endpoint="https://my-aoai.openai.azure.com",
api_key="...",
api_version="2024-12-01-preview"
)
# Bruk prompt_cache_key for å forbedre routing
# Forespørsler med samme key og prefix routes til samme cache
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
prompt_cache_key="ddt-complaint-handler-v2", # Gruppert caching
max_tokens=1000
)
# Sjekk cache hit
cached = response.usage.prompt_tokens_details.cached_tokens
total_prompt = response.usage.prompt_tokens
print(f"Cached tokens: {cached} / {total_prompt}")
print(f"Cache hit rate: {cached / total_prompt * 100:.1f}%")
# Advarsel: Mer enn ~15 RPM med samme prefix + cache_key
# kan overflow til andre maskiner og redusere cache-effektivitet
Cost Reduction Calculation
Beregn besparelser fra prompt caching
def calculate_caching_savings(
monthly_requests: int,
avg_total_input_tokens: int,
avg_cached_tokens: int, # Tokens som treffer cache
model: str = "gpt-4o",
deployment_type: str = "standard" # "standard" eller "provisioned"
) -> dict:
"""Calculate cost savings from prompt caching."""
# Priser (USD per 1M tokens, estimater)
pricing = {
"gpt-4o": {
"standard": {"input": 2.50, "cached_discount": 0.50},
"provisioned": {"input": 0, "cached_discount": 1.0}
},
"gpt-4.1": {
"standard": {"input": 2.00, "cached_discount": 0.50},
"provisioned": {"input": 0, "cached_discount": 1.0}
},
"gpt-4o-mini": {
"standard": {"input": 0.15, "cached_discount": 0.50},
"provisioned": {"input": 0, "cached_discount": 1.0}
}
}
p = pricing.get(model, pricing["gpt-4o"])
dt = p.get(deployment_type, p["standard"])
non_cached_tokens = avg_total_input_tokens - avg_cached_tokens
# Uten caching
cost_without_cache = (
monthly_requests * avg_total_input_tokens / 1_000_000 * dt["input"])
# Med caching
cached_cost = (
monthly_requests * avg_cached_tokens / 1_000_000 *
dt["input"] * (1 - dt["cached_discount"]))
non_cached_cost = (
monthly_requests * non_cached_tokens / 1_000_000 * dt["input"])
cost_with_cache = cached_cost + non_cached_cost
savings = cost_without_cache - cost_with_cache
return {
"monthly_requests": monthly_requests,
"cache_hit_rate": round(
avg_cached_tokens / avg_total_input_tokens * 100, 1),
"cost_without_cache_nok": round(cost_without_cache * 11, 2),
"cost_with_cache_nok": round(cost_with_cache * 11, 2),
"monthly_savings_nok": round(savings * 11, 2),
"savings_pct": round(savings / max(cost_without_cache, 0.01) * 100, 1),
"note": (
"PTU: cached tokens er 100% rabatt" if deployment_type == "provisioned"
else "Standard: cached tokens er 50% rabatt")
}
# Eksempel: 50K forespørsler/mnd med RAG-pipeline
savings = calculate_caching_savings(
monthly_requests=50_000,
avg_total_input_tokens=3000,
avg_cached_tokens=2000, # System prompt + examples cached
model="gpt-4o",
deployment_type="standard"
)
print(f"Månedlig besparelse: {savings['monthly_savings_nok']} NOK")
print(f"Besparelse: {savings['savings_pct']}%")
Cache Invalidation
Håndtering av cache-endringer
class CacheAwarePromptManager:
"""Manage prompts with cache invalidation awareness."""
def __init__(self, base_system_prompt: str, version: str = "v1"):
self.base_system_prompt = base_system_prompt
self.version = version
self._prefix_hash = self._compute_hash(base_system_prompt)
def _compute_hash(self, text: str) -> str:
import hashlib
return hashlib.sha256(text.encode()).hexdigest()[:16]
def update_system_prompt(self, new_prompt: str):
"""
Oppdater system prompt. MERK: Dette invaliderer ALL cache
for denne applikasjonen fordi prefix endres.
Anbefaling: Gjør endringer i off-peak timer.
"""
new_hash = self._compute_hash(new_prompt)
if new_hash != self._prefix_hash:
print(f"WARNING: System prompt endret. "
f"Cache invalideres for alle forespørsler.")
print(f"Gammel hash: {self._prefix_hash}")
print(f"Ny hash: {new_hash}")
print(f"Anbefaling: Deploy endringen i off-peak timer "
f"for å minimere cache miss-kostnaden.")
self.base_system_prompt = new_prompt
self._prefix_hash = new_hash
def get_cache_key(self) -> str:
"""Get cache key for prompt_cache_key parameter."""
return f"app-{self.version}-{self._prefix_hash}"
# Cache invalidation triggers:
# 1. Endring i system prompt → Umiddelbar invalidering
# 2. Endring i few-shot examples → Invalidering fra det punktet
# 3. Inaktivitet > 5-10 min → Automatisk tømming
# 4. > 24 timer siden siste bruk → Garantert tømming
# 5. En eneste endret karakter i prefix → Full cache miss
Norsk offentlig sektor
- Kostnadseffektivitet: Prompt caching er "gratis" optimalisering — ingen konfigurasjon nødvendig, bare riktig prompt-design. Spar 30-50% på input-token kostnader.
- PTU-deployments: For PTU er cached tokens 100% gratis — dette betyr at riktig prefix-design kan doble effektiv throughput.
- Personvern: Prompt caches er isolert per Azure-abonnement og deles ikke mellom kunder. Data i cache følger samme databehandling som vanlige forespørsler.
- Forutsigbarhet: Cache hit rate kan monitoreres via
cached_tokensi API-responsen — bygg dashboards for å spore cache-effektivitet over tid.
Beslutningsrammeverk
| Scenario | Anbefaling | Begrunnelse |
|---|---|---|
| Lang system prompt (>500 tokens) | Design for caching | Mest å vinne |
| Mange few-shot examples | Flytt til prefix, bruk caching | Reduser input-kostnad |
| RAG med statisk kontekst | Cache system + kontekst, varier spørsmål | Høy hit rate |
| Unik prompt per forespørsel | Caching gir lite | Prefix endres for ofte |
| PTU deployment | Maksimer caching | 100% rabatt på cached tokens |
| Høy RPM (>15 per prefix) | Bruk prompt_cache_key | Forbedrer routing |
Referanser
- Prompt caching — Offisiell guide
- Provisioned throughput — PTU caching-fordeler
- Semantic cache with Cosmos DB — Ekstern caching
- Application design for AI workloads — Multi-layer caching
For arkitekten
- Bruk denne referansen når kunden vil redusere kostnader eller latens for Azure OpenAI-workloads med repetitive prompt-strukturer.
- Hovedregelen: Statisk innhold FØRST i prompten, dynamisk innhold SIST — alt statisk prefix caches automatisk.
- Minimum 1024 tokens i identisk prefix for cache hit — legg til referansemateriale eller detaljerte instruksjoner for å nå terskelen.
- For PTU: cached tokens teller 100% rabatt mot utilization — dette er den mest effektive optimaliseringen for PTU-deployments.
- En eneste endret karakter i prefix gir full cache miss — vær forsiktig med dynamiske elementer (timestamps, request-IDs) i starten av prompts.