To operasjoner, én økt (⊥ R7), begge ren metadata-normalisering (verdi aldri fabrikkert). Premiss-korreksjon (ground truth 2026-07-07): roadmap sa «27 none + 4 ai-act». Målt: 29 mangler bold **Status:** = 25 rene none + 4 ai-act (plain Status: GA). De «27» inkluderte 2 for mye — 2 filer (custom-dashboards-ai-operations, zero-trust-ai-services) har bold **Status:** KUN forbi byte 500 (present for full-fil-audit, usynlig for 500B header-parser) → egen header-slanking-residual (§8-register), utenfor Enhet 3. Op A — Status-backfill 25 rene none: utvidet backfill-status.mjs MANIFEST 14→39 (samme statusForFile + insertMetaField + hard per-fil-invariant, idempotent skip på de 14 R21-gjorte). Alle 25 → **Status:** Established Practice (ingen matcher template|matrix|benchmarks|register). Diff +25/-0. Op B — ai-act dual-header-dedup (4 filer): ny driver dedup-plain-header.mjs + 2 rene primitiver i transform.mjs — boldifyPlainField (plain→bold, verdi bevart byte-eksakt, header-scoped, idempotent) + dropRedundantPlainField (sletter plain KUN når bold m/ identisk verdi beviser redundans; kaster ved avvik/manglende bold). Per fil: plain Last updated: + Status: GA → bold (2026-06-18/2026-02, GA bevart), redundant plain Category: fjernet. Hard per-fil-invariant (net -1 linje, begge felt bold m/ bevart verdi, ingen plain-header igjen, body byte-identisk). Diff -12/+8. Verifisering: test-backfill-status 8/8 + test-dedup-plain-header 13/13; audit Missing Status 29→0, Missing English Last updated 4→0; skills-diff 29 filer +33/-12 (kun **Status:** + 8 bold-swaps), diff-kontekst inspisert per fil; begge drivere idempotent (re-run 0 writes); suite 806/806 exit 0; none=8 uendret (Enhet 4).
618 lines
24 KiB
Markdown
618 lines
24 KiB
Markdown
# Token Usage Tracking and Attribution
|
||
|
||
**Category:** Monitoring & Observability
|
||
**Last updated:** 2026-06-19
|
||
**Versjon:** 1.0
|
||
**Type:** reference
|
||
**Source:** https://learn.microsoft.com/azure/foundry/concepts/manage-costs
|
||
**Status:** Established Practice
|
||
|
||
## Innhold
|
||
|
||
- [Introduksjon](#introduksjon)
|
||
- [Token Counting og Logging](#token-counting-og-logging)
|
||
- [Usage Attribution per Applikasjon/Bruker](#usage-attribution-per-applikasjonbruker)
|
||
- [Budget Monitoring og Alerts](#budget-monitoring-og-alerts)
|
||
- [Token Efficiency Metrics](#token-efficiency-metrics)
|
||
- [Chargeback Reporting](#chargeback-reporting)
|
||
- [RAG-spesifikke Considerations](#rag-spesifikke-considerations)
|
||
- [Fine-tuned Models: Spesialkonsiderasjoner](#fine-tuned-models-spesialkonsiderasjoner)
|
||
- [Provisioned Throughput Units (PTU): Tracking](#provisioned-throughput-units-ptu-tracking)
|
||
- [Integrasjon med FinOps Practices](#integrasjon-med-finops-practices)
|
||
- [Best Practices](#best-practices)
|
||
- [Relaterte Referanser](#relaterte-referanser)
|
||
- [Kilder (Microsoft Learn)](#kilder-microsoft-learn)
|
||
- [For Cosmo](#for-cosmo)
|
||
|
||
## Introduksjon
|
||
|
||
Token usage tracking og cost attribution er kritiske kapabiliteter for å styre kostnader, implementere chargeback-modeller, og optimalisere ressursbruk i Microsoft AI-løsninger. Denne referansen dekker teknikker for nøyaktig token-måling, brukerattribuering, og kostnadsrapportering.
|
||
|
||
## Token Counting og Logging
|
||
|
||
### Basis Token Tracking
|
||
|
||
Azure OpenAI API returnerer token usage i response-objektet:
|
||
|
||
```python
|
||
response = client.chat.completions.create(
|
||
model="gpt-4o",
|
||
messages=[{"role": "user", "content": "Your prompt"}]
|
||
)
|
||
|
||
# Token-data fra response
|
||
input_tokens = response.usage.prompt_tokens
|
||
output_tokens = response.usage.completion_tokens
|
||
total_tokens = response.usage.total_tokens
|
||
```
|
||
|
||
**Viktig:** Token-telling varierer per modell og er basert på modell-spesifikk tokenizer (GPT-2 tokenizer som baseline).
|
||
|
||
### Token Estimering (Pre-call)
|
||
|
||
For å estimere tokens før API-kall:
|
||
|
||
```python
|
||
import tiktoken
|
||
|
||
class TokenEstimator(object):
|
||
GPT2_TOKENIZER = tiktoken.get_encoding("gpt2")
|
||
|
||
def estimate_tokens(self, text: str) -> int:
|
||
return len(self.GPT2_TOKENIZER.encode(text))
|
||
|
||
# Bruk
|
||
estimator = TokenEstimator()
|
||
token_count = estimator.estimate_tokens(input_text)
|
||
```
|
||
|
||
**Bruksområder:**
|
||
- Pre-validering mot rate limits
|
||
- Kostnadsestimering før kall
|
||
- Budsjett-gating i applikasjoner
|
||
|
||
### Azure Monitor Platform Metrics
|
||
|
||
Azure OpenAI samler automatisk token-baserte metrics:
|
||
|
||
**Tilgjengelige metrics:**
|
||
- `TokenTransaction` — Total token count (input + output)
|
||
- `InputTokens` — Input tokens
|
||
- `OutputTokens` — Output tokens
|
||
- `ProcessedPromptTokens` — Tokens faktisk prosessert (kan avvike ved caching)
|
||
|
||
**Aksess via:**
|
||
- Azure Portal → Azure OpenAI resource → Metrics
|
||
- Azure Monitor Metrics Explorer
|
||
- REST API (`/metrics` endpoint)
|
||
|
||
**Dashboards:**
|
||
Azure OpenAI tilbyr out-of-box dashboards med "Tokens-Based Usage" kategori som viser:
|
||
- Token consumption over tid
|
||
- Breakdown per modell
|
||
- Comparison mot quota limits
|
||
|
||
## Usage Attribution per Applikasjon/Bruker
|
||
|
||
### Utfordring: Native Telemetri-begrensninger
|
||
|
||
**Problem:**
|
||
Azure OpenAI logger IP-adresse med siste oktet masket (f.eks. `192.168.1.xxx`), noe som gjør det vanskelig å knytte token-bruk til spesifikk applikasjon eller business unit.
|
||
|
||
**Løsning:** Introduser gateway-pattern for fullstendig attributering.
|
||
|
||
### Gateway-basert Attribution (Azure API Management)
|
||
|
||
**Arkitektur:**
|
||
```
|
||
Client → API Management Gateway → Azure OpenAI
|
||
↓
|
||
Token usage logged med:
|
||
- Client IP (full adresse)
|
||
- Microsoft Entra ID identity
|
||
- Custom business unit/app identifier
|
||
```
|
||
|
||
**Fordeler:**
|
||
1. **Fullstendig IP-adresse** — Identifiser klient-applikasjon
|
||
2. **Identity-data** — Entra ID user/app principal
|
||
3. **Custom metadata** — Business unit, cost center, tenant ID
|
||
4. **Sentralisert logging** — Aggreger data fra multiple Azure OpenAI instances
|
||
|
||
**Kusto Query for Usage Monitoring (APIM):**
|
||
|
||
```kusto
|
||
ApiManagementGatewayLogs
|
||
| where tolower(OperationId) in ('completions_create','chatcompletions_create')
|
||
| extend model = tostring(parse_json(BackendResponseBody)['model'])
|
||
| extend prompttokens = parse_json(parse_json(BackendResponseBody)['usage'])['prompt_tokens']
|
||
| extend completiontokens = parse_json(parse_json(BackendResponseBody)['usage'])['completion_tokens']
|
||
| extend totaltokens = parse_json(parse_json(BackendResponseBody)['usage'])['total_tokens']
|
||
| extend ip = CallerIpAddress
|
||
| summarize
|
||
sum(todecimal(prompttokens)),
|
||
sum(todecimal(completiontokens)),
|
||
sum(todecimal(totaltokens)),
|
||
avg(todecimal(totaltokens))
|
||
by ip, model
|
||
```
|
||
|
||
**Output:** Tabell med IP, model, sum(prompt tokens), sum(completion tokens), sum(total tokens).
|
||
|
||
### Application Insights Telemetry Enrichment
|
||
|
||
For applikasjoner uten gateway, bruk Application Insights med custom telemetry:
|
||
|
||
```python
|
||
import logging
|
||
from azure.monitor.opentelemetry import configure_azure_monitor
|
||
|
||
# Sett opp Application Insights
|
||
configure_azure_monitor()
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
def log_token_usage(response, user_id, business_unit):
|
||
usage = response.usage
|
||
|
||
# Log med custom properties for attribution
|
||
logger.info(
|
||
"Token usage",
|
||
extra={
|
||
"custom_dimensions": {
|
||
"user_id": user_id,
|
||
"business_unit": business_unit,
|
||
"model": response.model,
|
||
"prompt_tokens": usage.prompt_tokens,
|
||
"completion_tokens": usage.completion_tokens,
|
||
"total_tokens": usage.total_tokens
|
||
}
|
||
}
|
||
)
|
||
```
|
||
|
||
**Advarsel:** Application Insights bruker [sampling](https://learn.microsoft.com/en-us/azure/azure-monitor/app/sampling) i high-volume scenarios, noe som ikke er egnet for nøyaktig billing/metering. For billing-data, bruk dedikert data store (Event Hubs + Stream Analytics).
|
||
|
||
### Resource Tags for Attribution
|
||
|
||
For deployment-level attribution:
|
||
|
||
```bash
|
||
# Tag Azure OpenAI resource
|
||
az openai account update \
|
||
--name myopenai \
|
||
--resource-group myrg \
|
||
--tags CostCenter=Finance AppName=ChatBot Environment=Prod
|
||
```
|
||
|
||
**Bruk i Azure Cost Management:**
|
||
Filtrer kostnadsanalyse per tag for å allokere Azure-kostnader til business units.
|
||
|
||
**Begrensning:** Dette gir deployment-level attribution, ikke per-request granularitet.
|
||
|
||
## Budget Monitoring og Alerts
|
||
|
||
### Azure Monitor Budget Alerts
|
||
|
||
**Oppsett:**
|
||
|
||
1. **Opprett diagnostic setting** for Azure OpenAI resource:
|
||
- Send metrics til Log Analytics workspace
|
||
- Velg `AllMetrics` kategori
|
||
|
||
2. **Sett opp metric alert** på token usage:
|
||
```
|
||
Metric: ProcessedPromptTokens
|
||
Aggregation: Sum
|
||
Threshold: 1000000 (1M tokens)
|
||
Period: 1 hour
|
||
Action: Send email / webhook
|
||
```
|
||
|
||
3. **Opprett budget i Cost Management:**
|
||
- Scope: Azure OpenAI resource eller subscription
|
||
- Budget amount: NOK 10,000/måned
|
||
- Alert thresholds: 50%, 80%, 100%, 120%
|
||
|
||
**Kusto query for budget monitoring:**
|
||
|
||
```kusto
|
||
AzureMetrics
|
||
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
|
||
| where MetricName == "TokenTransaction"
|
||
| summarize TotalTokens = sum(Total) by bin(TimeGenerated, 1h), Resource
|
||
| extend EstimatedCost = TotalTokens * 0.0001 // Eksempel: $0.0001 per token
|
||
| project TimeGenerated, Resource, TotalTokens, EstimatedCost
|
||
```
|
||
|
||
### Programmatic Budget Enforcement
|
||
|
||
**API-level rate limiting:**
|
||
|
||
```python
|
||
import logging
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# Konfigurasjon
|
||
MONTHLY_TOKEN_BUDGET = 10_000_000
|
||
DAILY_TOKEN_BUDGET = 500_000
|
||
ITPM_LIMIT = 100_000 # Input tokens per minute
|
||
OTPM_LIMIT = 50_000 # Output tokens per minute
|
||
|
||
def log_token_usage(response, current_usage):
|
||
usage = response.usage
|
||
|
||
# Log current usage
|
||
logger.info(f"Input tokens: {usage.prompt_tokens}")
|
||
logger.info(f"Output tokens: {usage.completion_tokens}")
|
||
logger.info(f"Total tokens: {usage.total_tokens}")
|
||
|
||
# Check against limits
|
||
if usage.prompt_tokens > ITPM_LIMIT * 0.8:
|
||
logger.warning("Approaching ITPM limit")
|
||
|
||
if usage.completion_tokens > OTPM_LIMIT * 0.8:
|
||
logger.warning("Approaching OTPM limit")
|
||
|
||
# Budget enforcement
|
||
new_usage = current_usage + usage.total_tokens
|
||
if new_usage > DAILY_TOKEN_BUDGET:
|
||
raise Exception("Daily token budget exceeded")
|
||
|
||
return new_usage
|
||
```
|
||
|
||
**Best practice:** Kombiner soft limits (warnings) med hard limits (enforcement) for å balansere reliability og cost control.
|
||
|
||
## Token Efficiency Metrics
|
||
|
||
### Nøkkel-metrikker for Optimalisering
|
||
|
||
1. **Token-to-response ratio**
|
||
`average_tokens_per_request = total_tokens / request_count`
|
||
|
||
2. **Input/output ratio**
|
||
`io_ratio = completion_tokens / prompt_tokens`
|
||
Høy ratio = efficient prompt design
|
||
|
||
3. **Cost per request**
|
||
`cost_per_request = (prompt_tokens * input_price + completion_tokens * output_price) / 1000`
|
||
|
||
4. **Tokens per user session**
|
||
`session_tokens = sum(tokens) GROUP BY session_id`
|
||
|
||
5. **Prompt efficiency score**
|
||
`efficiency = output_quality_score / total_tokens`
|
||
|
||
### Kusto Query for Efficiency Analysis
|
||
|
||
```kusto
|
||
AzureDiagnostics
|
||
| where Category == "RequestResponse"
|
||
| extend model = tostring(parse_json(properties_s)['model'])
|
||
| extend prompt_tokens = toint(parse_json(properties_s)['usage']['prompt_tokens'])
|
||
| extend completion_tokens = toint(parse_json(properties_s)['usage']['completion_tokens'])
|
||
| extend total_tokens = toint(parse_json(properties_s)['usage']['total_tokens'])
|
||
| summarize
|
||
AvgPromptTokens = avg(prompt_tokens),
|
||
AvgCompletionTokens = avg(completion_tokens),
|
||
AvgTotalTokens = avg(total_tokens),
|
||
IOEfficiency = avg(todecimal(completion_tokens) / todecimal(prompt_tokens)),
|
||
RequestCount = count()
|
||
by model, bin(TimeGenerated, 1d)
|
||
| project TimeGenerated, model, AvgPromptTokens, AvgCompletionTokens, IOEfficiency, RequestCount
|
||
```
|
||
|
||
## Chargeback Reporting
|
||
|
||
### Chargeback Model Components
|
||
|
||
**1. Data Collection:**
|
||
- Gateway logs (APIM) eller Application Insights
|
||
- Token usage per business unit/app
|
||
- Model pricing data (per 1K tokens)
|
||
|
||
**2. Cost Calculation:**
|
||
```python
|
||
# Eksempel pricing (GPT-4o, januar 2026)
|
||
INPUT_PRICE_PER_1K = 0.005 # USD
|
||
OUTPUT_PRICE_PER_1K = 0.015 # USD
|
||
NOK_EXCHANGE_RATE = 10.5
|
||
|
||
def calculate_cost(prompt_tokens, completion_tokens):
|
||
input_cost = (prompt_tokens / 1000) * INPUT_PRICE_PER_1K
|
||
output_cost = (completion_tokens / 1000) * OUTPUT_PRICE_PER_1K
|
||
total_usd = input_cost + output_cost
|
||
total_nok = total_usd * NOK_EXCHANGE_RATE
|
||
return total_nok
|
||
```
|
||
|
||
**3. Attribution Logic:**
|
||
- Per user: Group by user_id
|
||
- Per app: Group by application_name
|
||
- Per business unit: Group by cost_center tag
|
||
|
||
**4. Report Generation:**
|
||
|
||
```kusto
|
||
// Monthly chargeback report
|
||
ApiManagementGatewayLogs
|
||
| where TimeGenerated >= startofmonth(now())
|
||
| where tolower(OperationId) in ('completions_create','chatcompletions_create')
|
||
| extend business_unit = tostring(parse_json(RequestHeaders)['X-Business-Unit'])
|
||
| extend model = tostring(parse_json(BackendResponseBody)['model'])
|
||
| extend prompt_tokens = toint(parse_json(parse_json(BackendResponseBody)['usage'])['prompt_tokens'])
|
||
| extend completion_tokens = toint(parse_json(parse_json(BackendResponseBody)['usage'])['completion_tokens'])
|
||
| summarize
|
||
TotalPromptTokens = sum(prompt_tokens),
|
||
TotalCompletionTokens = sum(completion_tokens),
|
||
RequestCount = count()
|
||
by business_unit, model
|
||
| extend InputCostUSD = (TotalPromptTokens / 1000.0) * 0.005
|
||
| extend OutputCostUSD = (TotalCompletionTokens / 1000.0) * 0.015
|
||
| extend TotalCostUSD = InputCostUSD + OutputCostUSD
|
||
| extend TotalCostNOK = TotalCostUSD * 10.5
|
||
| project business_unit, model, TotalPromptTokens, TotalCompletionTokens,
|
||
RequestCount, TotalCostUSD, TotalCostNOK
|
||
| order by TotalCostNOK desc
|
||
```
|
||
|
||
### Showback vs Chargeback
|
||
|
||
| Aspekt | Showback | Chargeback |
|
||
|--------|----------|------------|
|
||
| **Formål** | Informasjon og bevisstgjøring | Faktisk fakturering |
|
||
| **Nøyaktighet** | Estimert (akseptabelt med sampling) | Høy presisjon påkrevd |
|
||
| **Data store** | Application Insights OK | Event Hubs + dedikert DB |
|
||
| **Frekvens** | Ukentlig/månedlig report | Real-time tracking |
|
||
| **Implementering** | Enklere | Mer kompleks |
|
||
|
||
**Anbefaling:** Start med showback for å bygge kostnadsbevissthet, deretter implementer chargeback når forretningskrav og infrastruktur er på plass.
|
||
|
||
## RAG-spesifikke Considerations
|
||
|
||
### Token Usage i RAG-pipelines
|
||
|
||
Azure OpenAI On Your Data (RAG) gjør **to** LLM-kall per brukerforespørsel:
|
||
|
||
**1. Intent Prompt** — Reformulering av query til search intents
|
||
**2. Generation Prompt** — Generering av svar basert på retrieved chunks
|
||
|
||
**Token breakdown:**
|
||
|
||
| Komponent | Beskrivelse | Token impact |
|
||
|-----------|-------------|--------------|
|
||
| Meta prompt | System instructions (inScope param avhengig) | 400-4000 tokens (modell-avhengig) |
|
||
| User question + history | Input fra bruker | Cap: 2000 tokens |
|
||
| Retrieved chunks | Dokumenter fra search (5-10 chunks @ 1024 tokens) | 5000-10000 tokens |
|
||
| Intent generation | Output fra første LLM-kall | ~25 tokens |
|
||
| Final response | Output fra andre LLM-kall | ~110 tokens |
|
||
|
||
**Eksempel (gpt-35-turbo-16k):**
|
||
- Generation prompt: 4297 tokens
|
||
- Intent prompt: 1366 tokens
|
||
- Response output: 111 tokens
|
||
- Intent output: 25 tokens
|
||
- **Total: ~5800 tokens per spørsmål**
|
||
|
||
**Optimaliseringstekniker:**
|
||
1. Reduser `retrieved_document_count` (default 5)
|
||
2. Juster `chunk_size` (default 1024)
|
||
3. Øk `strictness` (filtrer irrelevante chunks)
|
||
4. Bruk `inScope=True` for kortere meta prompt
|
||
|
||
### Monitoring RAG Token Usage
|
||
|
||
```kusto
|
||
// Dedicated query for RAG scenarios
|
||
AzureDiagnostics
|
||
| where Category == "RequestResponse"
|
||
| where properties_s contains "data_sources" // RAG indicator
|
||
| extend prompt_tokens = toint(parse_json(properties_s)['usage']['prompt_tokens'])
|
||
| extend completion_tokens = toint(parse_json(properties_s)['usage']['completion_tokens'])
|
||
| extend total_tokens = toint(parse_json(properties_s)['usage']['total_tokens'])
|
||
| extend retrieved_docs = toint(parse_json(properties_s)['data_sources'][0]['parameters']['top_n_documents'])
|
||
| summarize
|
||
AvgPromptTokens = avg(prompt_tokens),
|
||
AvgCompletionTokens = avg(completion_tokens),
|
||
AvgTotalTokens = avg(total_tokens),
|
||
AvgRetrievedDocs = avg(retrieved_docs),
|
||
RequestCount = count()
|
||
by bin(TimeGenerated, 1h)
|
||
```
|
||
|
||
## Fine-tuned Models: Spesialkonsiderasjoner
|
||
|
||
### Tre Kostnadskomponenter
|
||
|
||
1. **Training cost** — Per token i training file
|
||
2. **Hosting cost** — Timepris mens deployed (uansett bruk)
|
||
3. **Inference cost** — Per 1000 tokens (input + output)
|
||
|
||
**Kritisk:** Fine-tuned modeller akkumulerer hosting cost **selv når de ikke brukes**. Etter 15 dager inaktivitet slettes deployment automatisk (modellen bevares, kan redeployes).
|
||
|
||
**Best practice:**
|
||
- Monitor deployment utilization
|
||
- Slett unused deployments promptly
|
||
- Bruk automation for deployment lifecycle
|
||
|
||
### Tracking Fine-tuning Costs
|
||
|
||
```kusto
|
||
AzureMetrics
|
||
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
|
||
| where MetricName in ("FineTuningHours", "FineTuningTokens")
|
||
| summarize
|
||
TotalTrainingTokens = sumif(Total, MetricName == "FineTuningTokens"),
|
||
TotalHostingHours = sumif(Total, MetricName == "FineTuningHours")
|
||
by Resource, bin(TimeGenerated, 1d)
|
||
| extend TrainingCostUSD = TotalTrainingTokens * 0.00008 // Eksempel pricing
|
||
| extend HostingCostUSD = TotalHostingHours * 2.0 // Eksempel: $2/hour
|
||
| extend TotalCostUSD = TrainingCostUSD + HostingCostUSD
|
||
```
|
||
|
||
## Provisioned Throughput Units (PTU): Tracking
|
||
|
||
### PTU vs. Consumption-based Billing
|
||
|
||
| Billing Model | Token Tracking Approach |
|
||
|---------------|-------------------------|
|
||
| **Pay-as-you-go** | Track individual tokens, calculate variable cost |
|
||
| **PTU** | Track utilization percentage against reserved capacity |
|
||
|
||
**PTU Metrics:**
|
||
- `AzureOpenAIProvisionedManagedUtilizationV2` — Percentage of reserved capacity used
|
||
- `ProcessedPromptTokens` — Input tokens processed
|
||
- Input TPM per PTU — Model-specific (f.eks. 8450 TPM for Llama-3.3-70B)
|
||
|
||
**Cost model:**
|
||
- Fixed monthly cost for PTU reservation
|
||
- Cost per token = (Monthly PTU cost) / (Total tokens processed)
|
||
|
||
### PTU Efficiency Monitoring
|
||
|
||
```kusto
|
||
AzureMetrics
|
||
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
|
||
| where MetricName == "AzureOpenAIProvisionedManagedUtilizationV2"
|
||
| summarize AvgUtilization = avg(Average), MaxUtilization = max(Maximum)
|
||
by Resource, bin(TimeGenerated, 1h)
|
||
| extend EfficiencyStatus = case(
|
||
AvgUtilization < 50, "Underutilized",
|
||
AvgUtilization >= 50 and AvgUtilization < 80, "Optimal",
|
||
AvgUtilization >= 80, "Consider scaling"
|
||
)
|
||
```
|
||
|
||
**Anbefaling:** Kombiner PTU for baseline workload med pay-as-you-go for overflow traffic (via gateway pattern).
|
||
|
||
## Integrasjon med FinOps Practices
|
||
|
||
### FinOps Framework Alignment
|
||
|
||
**1. Inform:**
|
||
- Real-time dashboards med token usage
|
||
- Trend analysis og forecasting
|
||
- Anomaly detection på usage spikes
|
||
|
||
**2. Optimize:**
|
||
- Token efficiency metrics (se "Token Efficiency Metrics")
|
||
- Prompt optimization basert på cost/quality ratio
|
||
- Model selection guidance (GPT-4o vs. GPT-4o-mini)
|
||
|
||
**3. Operate:**
|
||
- Automated budget enforcement
|
||
- Chargeback/showback reporting
|
||
- Cost allocation til business units
|
||
|
||
### Azure Cost Management Integration
|
||
|
||
**1. Tag Strategy:**
|
||
```bash
|
||
# Standardized tagging
|
||
CostCenter: <code>
|
||
BusinessUnit: <name>
|
||
Application: <name>
|
||
Environment: Prod|Dev|Test
|
||
Owner: <email>
|
||
```
|
||
|
||
**2. Cost Analysis Views:**
|
||
- Filtrer per tag dimension
|
||
- Group by resource, subscription, eller custom tag
|
||
- Sammenlign faktisk vs. budsjett
|
||
|
||
**3. Budgets:**
|
||
- Opprett per resource group eller subscription
|
||
- Sett alert thresholds (50%, 80%, 100%, 120%). WAF anbefaler som minimum 90% (ideelt forbruk), 100% (mål) og 110% (mindre ideelt) for budget alerts, og 110% for forecast alerts. *(Verified MCP 2026-06-19)*
|
||
- Action groups for automated response (webhook, Logic App)
|
||
|
||
**4. FOCUS-basert eksport og analyse** *(Verified MCP 2026-06-19)*:
|
||
- Azure Cost Management beholder kostnadsdata i **13 måneder**. For lengre historikk: planlegg Cost Management-eksport til et Azure Data Lake Storage Gen2-lager (daglig/månedlig) med **FOCUS**-malen (FinOps Open Cost and Usage Specification — leverandøragnostisk, standardisert skjema).
|
||
- Skill mellom **actual costs** (som fakturert, 24–72 t ingestion-forsinkelse) og **amortized costs** (commitment-baserte kjøp fordelt jevnt over perioden). Samle inn begge for å avstemme faktura mot effektiv kostnad.
|
||
- Avansert rapportering: pipeline **Cost Management exports → ADLS Gen2 → Fabric Lakehouse → Power BI** skalerer til store datasett og muliggjør egendefinert FOCUS-rapportering. For høyvolum-tjenester: bruk ingestion-time transformation i Log Analytics for å redusere loggvolum.
|
||
|
||
## Best Practices
|
||
|
||
### 1. Data Store Selection
|
||
|
||
| Use Case | Recommended Store | Rationale |
|
||
|----------|-------------------|-----------|
|
||
| Showback (informasjon) | Application Insights | Enkel, innebygd, sampling OK |
|
||
| Chargeback (fakturering) | Event Hubs + Synapse/Fabric | Høy presisjon, no sampling |
|
||
| Real-time monitoring | Stream Analytics + Power BI | Low latency, streaming dashboards |
|
||
| Long-term audit | Azure Storage (cold tier) | Billig, compliance-friendly |
|
||
|
||
### 2. Attribution Hierarchy
|
||
|
||
**Prioriter:**
|
||
1. **User-level** — Mest granulær, best for interne chargeback
|
||
2. **Application-level** — God for multi-tenant SaaS
|
||
3. **Business unit-level** — Standard for enterprise showback
|
||
4. **Subscription-level** — Minst granulær, enklest å implementere
|
||
|
||
### 3. Monitoring Frequency
|
||
|
||
| Metric Type | Collection Frequency | Retention |
|
||
|-------------|---------------------|-----------|
|
||
| Real-time alerts | Per request | 7 dager |
|
||
| Operational dashboards | 1 minutt aggregation | 30 dager |
|
||
| Cost reporting | 1 time aggregation | 1 år |
|
||
| Audit logs | Per request (full fidelity) | 7 år (compliance) |
|
||
|
||
### 4. Gateway Pattern Decision Matrix
|
||
|
||
**Bruk gateway hvis:**
|
||
- ✅ Multiple clients eller multiple Azure OpenAI instances
|
||
- ✅ Chargeback requirement (nøyaktig attribution)
|
||
- ✅ Centralized policy enforcement (rate limiting, content filtering)
|
||
- ✅ Near real-time monitoring requirement
|
||
|
||
**Unngå gateway hvis:**
|
||
- ❌ Single client, single Azure OpenAI instance
|
||
- ❌ Latency er kritisk (gateway adds ~10-50ms)
|
||
- ❌ Simple showback er sufficient
|
||
|
||
### 5. Cost Optimization Triggers
|
||
|
||
**Alerts når:**
|
||
- Token usage øker >20% week-over-week (anomaly)
|
||
- Cost per user > baseline + 2 standard deviations
|
||
- PTU utilization < 50% (consider downscaling)
|
||
- Fine-tuned model har 0 requests i 7 dager (delete deployment)
|
||
|
||
## Relaterte Referanser
|
||
|
||
- **cost-optimization/token-optimization.md** — Teknikker for å redusere token consumption
|
||
- **cost-optimization/ptu-vs-payg.md** — Billing model selection
|
||
- **monitoring-observability/azure-monitor-integration.md** — Azure Monitor oppsett
|
||
- **monitoring-observability/alerting-strategies.md** — Alert configuration patterns
|
||
- **architecture/gateway-patterns.md** — API Management for AI workloads
|
||
- **mlops-genaiops/evaluation-metrics.md** — Quality vs. cost trade-offs
|
||
|
||
## Kilder (Microsoft Learn)
|
||
|
||
1. [Monitor Azure OpenAI](https://learn.microsoft.com/en-us/azure/foundry-classic/openai/how-to/monitor-openai) — Official monitoring guide
|
||
2. [Implement advanced monitoring for Azure OpenAI in Foundry Models through a gateway](https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/azure-openai-gateway-monitoring) *(Verified MCP 2026-04)* — Gateway patterns for usage tracking. Ny brukscase dokumentert: audit av model inputs/outputs for threat detection og data exfiltration detection. Merk: gateway monitoring kan bli single point of failure — vurder redundans.
|
||
3. [Plan to manage costs for Azure OpenAI](https://learn.microsoft.com/en-us/azure/foundry/concepts/manage-costs) — Cost management strategies
|
||
4. [Token usage estimation for Azure OpenAI On Your Data](https://learn.microsoft.com/en-us/azure/foundry-classic/openai/concepts/use-your-data#token-usage-estimation-for-azure-openai-on-your-data) — RAG-specific token calculations
|
||
5. [Understanding costs associated with PTU](https://learn.microsoft.com/en-us/azure/foundry/openai/concepts/provisioned-throughput-billing) — PTU billing model
|
||
6. [Application design for AI workloads](https://learn.microsoft.com/en-us/azure/well-architected/ai/application-design#consider-nonfunctional-requirements) — Cost and chargeback scenarios
|
||
7. [Architecture strategies for cost data](https://learn.microsoft.com/en-us/azure/well-architected/cost-optimization/collect-review-cost-data#generate-cost-reports) — Chargeback vs. showback. *(Verified MCP 2026-06-19 — FOCUS-eksport, actual vs amortized costs, Cost Management 13-mnd retention, Fabric/Power BI-pipeline, budget/forecast alert-terskler)*
|
||
|
||
## For Cosmo
|
||
|
||
Når du diskuterer token usage tracking og attribution, vektlegg **gateway-pattern** som game-changer for chargeback-scenarioer. Mange organisasjoner undervurderer betydningen av nøyaktig attribution før de skalerer AI-løsninger til produksjon.
|
||
|
||
**Key talking points:**
|
||
1. Native Azure OpenAI telemetri har **masket IP** — ikke sufficient for per-app attribution
|
||
2. Gateway (APIM) gir **full observability** + centralized policy enforcement
|
||
3. Forskjellen mellom **showback** (informasjon) og **chargeback** (fakturering) krever ulik data fidelity
|
||
4. RAG-workloads har **2x token overhead** (intent + generation) — må planlegges inn i budsjett
|
||
5. Fine-tuned models har **hosting cost uavhengig av bruk** — krev proaktiv lifecycle management
|
||
|
||
Hvis løsningen skal brukes av **flere business units** eller krever **intern fakturering**, er gateway pattern ikke optional — det er kritisk arkitektur-komponent.
|
||
|
||
**Norsk offentlig sektor-vinkling:**
|
||
For offentlige virksomheter med krav til internprising (eks. NAV, Skatteetaten, fylkeskommuner med delte IT-tjenester), er nøyaktig cost attribution **ikke bare best practice — det er governance-krav**. Kombiner med Azure Cost Management tags for å oppfylle økonomiregelverket sitt krav til transparent ressursbruk.
|