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.
393 lines
15 KiB
Markdown
393 lines
15 KiB
Markdown
# API Versioning Strategies for AI Endpoints
|
|
|
|
**Last updated:** 2026-06-24
|
|
**Status:** GA
|
|
**Category:** API Management & AI Gateway
|
|
**Type:** reference
|
|
**Source:** https://learn.microsoft.com/azure/api-management/genai-gateway-capabilities
|
|
|
|
---
|
|
|
|
## Innhold
|
|
|
|
- [Introduksjon](#introduksjon)
|
|
- [Versjoneringsstrategier i APIM](#versjoneringsstrategier-i-apim)
|
|
- [Avviklingsfrister (Deprecation Timelines)](#avviklingsfrister-deprecation-timelines)
|
|
- [Modellversjonsmapping](#modellversjonsmapping)
|
|
- [Migreringsstrategier](#migreringsstrategier)
|
|
- [Revisjonsstyring for ikke-brytende endringer](#revisjonsstyring-for-ikke-brytende-endringer)
|
|
- [Handtering av brytende endringer](#handtering-av-brytende-endringer)
|
|
- [Referanser](#referanser)
|
|
- [For Cosmo](#for-cosmo)
|
|
|
|
## Introduksjon
|
|
|
|
API-versjonering er kritisk for AI-tjenester der underliggende modeller endres hyppig, nye kapabiliteter legges til og eldre versjoner fases ut. Azure API Management tilbyr tre versjoneringsstrategier (URL-path, header og query string) samt revisjonsstyring for ikke-brytende endringer. For AI-API-er er dette spesielt utfordrende fordi modellversjoner, API-schemaer og responsformater kan endres uavhengig av hverandre.
|
|
|
|
For norsk offentlig sektor er kontrollert versjonering essensielt. Offentlige virksomheter har ofte integrerte systemer som er avhengige av stabile API-grensesnitt, og et modellbytte kan gi annerledes output for samme prompt. En robust versjoneringssstrategi sikrer at eksisterende integrasjoner fortsetter a fungere nar nye modeller eller kapabiliteter innfores, og gir forbrukere tid til a migrere kontrollert.
|
|
|
|
APIM skiller mellom versjoner (for brytende endringer) og revisjoner (for ikke-brytende endringer). Denne referansen dekker begge konseptene i konteksten av AI-API-er, med praktiske monstre for modellversjonsmapping, migrasjon og avvikling.
|
|
|
|
---
|
|
|
|
## Versjoneringsstrategier i APIM
|
|
|
|
### Tre tilgjengelige skjemaer
|
|
|
|
| Skjema | Format | Eksempel |
|
|
|--------|--------|---------|
|
|
| **URL Path** | `/{api-path}/v1/...` | `https://api.virksomhet.no/ai/v1/chat/completions` |
|
|
| **Header** | Custom header | `Api-Version: 2024-08-01` |
|
|
| **Query String** | URL-parameter | `https://api.virksomhet.no/ai/chat/completions?api-version=2024-08-01` |
|
|
|
|
### Anbefaling for AI-API-er
|
|
|
|
| Strategi | Fordeler | Ulemper | Anbefalt for |
|
|
|----------|---------|---------|-------------|
|
|
| URL Path | Tydelig, selvdokumenterende, lett a route | Mer tungvint a migrere | Offentlige API-er med stabile versjoner |
|
|
| Header | Ren URL, fleksibelt | Ikke synlig i URL | Interne API-er, programmatisk tilgang |
|
|
| Query String | Kompatibelt med Azure OpenAI-konvensjon | Kan bli rotete med mange params | Direkte kompatibilitet med Azure OpenAI |
|
|
|
|
**Anbefaling:** For AI gateway som wrapper rundt Azure OpenAI, bruk **query string** med `api-version` for a folge Microsofts eksisterende konvensjon. For egne AI-fasade-API-er, bruk **URL path** for tydelighet.
|
|
|
|
### Konfigurere versjonering i APIM
|
|
|
|
#### URL Path-versjonering
|
|
|
|
```bicep
|
|
resource apiVersionSet 'Microsoft.ApiManagement/service/apiVersionSets@2023-09-01-preview' = {
|
|
parent: apiManagement
|
|
name: 'ai-gateway-version-set'
|
|
properties: {
|
|
displayName: 'AI Gateway API'
|
|
versioningScheme: 'Segment' // URL path
|
|
description: 'AI Gateway API versjonert med URL-path'
|
|
}
|
|
}
|
|
|
|
resource aiApiV1 'Microsoft.ApiManagement/service/apis@2023-09-01-preview' = {
|
|
parent: apiManagement
|
|
name: 'ai-gateway-v1'
|
|
properties: {
|
|
displayName: 'AI Gateway API v1'
|
|
apiVersion: 'v1'
|
|
apiVersionSetId: apiVersionSet.id
|
|
path: 'ai'
|
|
protocols: [ 'https' ]
|
|
subscriptionRequired: true
|
|
}
|
|
}
|
|
|
|
resource aiApiV2 'Microsoft.ApiManagement/service/apis@2023-09-01-preview' = {
|
|
parent: apiManagement
|
|
name: 'ai-gateway-v2'
|
|
properties: {
|
|
displayName: 'AI Gateway API v2'
|
|
apiVersion: 'v2'
|
|
apiVersionSetId: apiVersionSet.id
|
|
path: 'ai'
|
|
protocols: [ 'https' ]
|
|
subscriptionRequired: true
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Header-basert versjonering
|
|
|
|
```bicep
|
|
resource apiVersionSetHeader 'Microsoft.ApiManagement/service/apiVersionSets@2023-09-01-preview' = {
|
|
parent: apiManagement
|
|
name: 'ai-gateway-header-version-set'
|
|
properties: {
|
|
displayName: 'AI Gateway API (Header Versioned)'
|
|
versioningScheme: 'Header'
|
|
versionHeaderName: 'Api-Version'
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Query String-versjonering
|
|
|
|
```bicep
|
|
resource apiVersionSetQuery 'Microsoft.ApiManagement/service/apiVersionSets@2023-09-01-preview' = {
|
|
parent: apiManagement
|
|
name: 'ai-gateway-query-version-set'
|
|
properties: {
|
|
displayName: 'AI Gateway API (Query Versioned)'
|
|
versioningScheme: 'Query'
|
|
versionQueryName: 'api-version'
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Avviklingsfrister (Deprecation Timelines)
|
|
|
|
### Livssyklusmodell for AI-API-versjoner
|
|
|
|
```
|
|
[Preview] --> [GA] --> [Deprecated] --> [Retired]
|
|
| | | |
|
|
| 6-12 mnd | 6-12 mnd| 3-6 mnd |
|
|
| | | |
|
|
Flagg: Flagg: Flagg: Fjernet
|
|
beta stable deprecated fra gateway
|
|
```
|
|
|
|
### Fasestyring med policies
|
|
|
|
```xml
|
|
<policies>
|
|
<outbound>
|
|
<base />
|
|
<!-- Add deprecation headers based on API version -->
|
|
<choose>
|
|
<!-- Deprecated version -->
|
|
<when condition="@(context.Api.Version == "v1")">
|
|
<set-header name="Deprecation" exists-action="override">
|
|
<value>true</value>
|
|
</set-header>
|
|
<set-header name="Sunset" exists-action="override">
|
|
<value>Sat, 30 Jun 2026 00:00:00 GMT</value>
|
|
</set-header>
|
|
<set-header name="Link" exists-action="override">
|
|
<value><https://api.virksomhet.no/ai/v2/docs>; rel="successor-version"</value>
|
|
</set-header>
|
|
<!-- Log deprecation usage for tracking -->
|
|
<trace source="api-versioning" severity="warning">
|
|
<message>@($"Deprecated API v1 called by {context.Subscription.Name}")</message>
|
|
</trace>
|
|
</when>
|
|
<!-- Preview version -->
|
|
<when condition="@(context.Api.Version == "v3-preview")">
|
|
<set-header name="x-api-status" exists-action="override">
|
|
<value>preview</value>
|
|
</set-header>
|
|
<set-header name="x-api-warning" exists-action="override">
|
|
<value>This API version is in preview and may change without notice.</value>
|
|
</set-header>
|
|
</when>
|
|
</choose>
|
|
</outbound>
|
|
</policies>
|
|
```
|
|
|
|
### Standard HTTP-headere for versjonsstyring
|
|
|
|
| Header | Verdi | RFC |
|
|
|--------|-------|-----|
|
|
| `Deprecation` | `true` | RFC 8594 |
|
|
| `Sunset` | ISO 8601 dato | RFC 8594 |
|
|
| `Link` | URL til ny versjon | RFC 8288 |
|
|
| `x-api-status` | `preview` / `ga` / `deprecated` | Custom |
|
|
|
|
---
|
|
|
|
## Modellversjonsmapping
|
|
|
|
### Utfordringen med AI-modellversjoner
|
|
|
|
AI-modeller oppdateres uavhengig av API-versjoner:
|
|
|
|
| API-versjon | Modellnavn | Faktisk modellversjon | Endring |
|
|
|-------------|-----------|----------------------|---------|
|
|
| v1 | gpt-4o | 2024-05-13 | Opprinnelig |
|
|
| v1 | gpt-4o | 2024-08-06 | Modelloppgradering (transparent) |
|
|
| v2 | gpt-4o | 2024-11-20 | Ny API + ny modell |
|
|
| v2 | gpt-4o-mini | 2024-07-18 | Ny modelltype i v2 |
|
|
|
|
### Policy: Modellversjonsmapping
|
|
|
|
```xml
|
|
<policies>
|
|
<inbound>
|
|
<base />
|
|
<!-- Map API version to specific model deployment -->
|
|
<set-variable name="apiVersion" value="@(context.Api.Version)" />
|
|
<set-variable name="requestedModel"
|
|
value="@(context.Request.Body.As<JObject>(preserveContent: true)?["model"]?.ToString())" />
|
|
|
|
<choose>
|
|
<!-- v1: Map to stable, older model deployments -->
|
|
<when condition="@((string)context.Variables["apiVersion"] == "v1")">
|
|
<set-variable name="deployment" value="@{
|
|
var model = (string)context.Variables["requestedModel"];
|
|
return model switch {
|
|
"gpt-4o" => "gpt-4o-2024-05-13-stable",
|
|
"gpt-4" => "gpt-4-0613-stable",
|
|
_ => "gpt-4o-2024-05-13-stable"
|
|
};
|
|
}" />
|
|
</when>
|
|
|
|
<!-- v2: Map to latest model deployments -->
|
|
<when condition="@((string)context.Variables["apiVersion"] == "v2")">
|
|
<set-variable name="deployment" value="@{
|
|
var model = (string)context.Variables["requestedModel"];
|
|
return model switch {
|
|
"gpt-4o" => "gpt-4o-2024-11-20-latest",
|
|
"gpt-4o-mini" => "gpt-4o-mini-2024-07-18",
|
|
_ => "gpt-4o-2024-11-20-latest"
|
|
};
|
|
}" />
|
|
</when>
|
|
</choose>
|
|
|
|
<!-- Route to correct deployment -->
|
|
<rewrite-uri template="@($"/openai/deployments/{context.Variables["deployment"]}/chat/completions")" />
|
|
</inbound>
|
|
</policies>
|
|
```
|
|
|
|
---
|
|
|
|
## Migreringsstrategier
|
|
|
|
### Parallellkjoring av versjoner
|
|
|
|
Kjor gammel og ny versjon side om side med gradvis migrering:
|
|
|
|
```xml
|
|
<policies>
|
|
<inbound>
|
|
<base />
|
|
<!-- Canary: Route percentage of v1 traffic to v2 backend -->
|
|
<choose>
|
|
<when condition="@(context.Api.Version == "v1" && new Random().Next(100) < 10)">
|
|
<!-- 10% of v1 traffic gets v2 backend for shadow testing -->
|
|
<set-variable name="shadowTest" value="true" />
|
|
<set-backend-service backend-id="ai-backend-v2" />
|
|
<set-header name="x-shadow-test" exists-action="override">
|
|
<value>true</value>
|
|
</set-header>
|
|
</when>
|
|
</choose>
|
|
</inbound>
|
|
</policies>
|
|
```
|
|
|
|
### Migreringssjekkliste
|
|
|
|
| Fase | Handling | Varighet |
|
|
|------|---------|----------|
|
|
| 1. Announce | Publiser ny versjon, dokumenter endringer | Uke 0 |
|
|
| 2. Parallel | Kjor begge versjoner, monitor bruk | Uke 1-12 |
|
|
| 3. Deprecate | Merk gammel versjon som deprecated | Uke 8 |
|
|
| 4. Notify | Send varsler til aktive brukere | Uke 8, 16, 22 |
|
|
| 5. Restrict | Reduser rate limits pa gammel versjon | Uke 20 |
|
|
| 6. Sunset | Fjern gammel versjon | Uke 24 |
|
|
|
|
### KQL: Overvak versjonsbruk
|
|
|
|
```kusto
|
|
ApiManagementGatewayLogs
|
|
| where TimeGenerated > ago(30d)
|
|
| extend ApiVersion = tostring(split(ApiId, "-")[-1])
|
|
| summarize
|
|
RequestCount = count(),
|
|
UniqueSubscriptions = dcount(SubscriptionId)
|
|
by ApiVersion, bin(TimeGenerated, 1d)
|
|
| order by TimeGenerated desc, ApiVersion asc
|
|
```
|
|
|
|
---
|
|
|
|
## Revisjonsstyring for ikke-brytende endringer
|
|
|
|
### Revisjoner vs. Versjoner
|
|
|
|
| Egenskap | Revisjon | Versjon |
|
|
|----------|----------|---------|
|
|
| Type endring | Ikke-brytende | Brytende |
|
|
| URL-endring | Nei (`;rev=N` valgfri) | Ja (ny versjon i path/header/query) |
|
|
| Eksempel | Legge til valgfritt felt | Endre responsstruktur |
|
|
| Klientpavirkning | Ingen (bakoverkompatibelt) | Krever klientoppdatering |
|
|
| Publisering | Gjor revisjon "current" | Ny API-versjon |
|
|
| Change log | Valgfri endringslogg | Egen dokumentasjon |
|
|
|
|
### Bruke revisjoner for modelloppgraderinger
|
|
|
|
Nar en modell oppdateres uten API-endringer (f.eks. GPT-4o far ny snapshot):
|
|
|
|
1. Opprett ny revisjon av API-et
|
|
2. Endre backend-deployment i den nye revisjonen
|
|
3. Test grundig med nye revisjon
|
|
4. Gjor revisjon "current" nar validert
|
|
5. Publiser endringslogg
|
|
|
|
```xml
|
|
<!-- Revision-specific backend for testing -->
|
|
<policies>
|
|
<inbound>
|
|
<base />
|
|
<!-- Non-current revisions can use different backends for testing -->
|
|
<choose>
|
|
<when condition="@(context.Api.Revision == "3")">
|
|
<set-backend-service backend-id="ai-backend-new-model" />
|
|
</when>
|
|
</choose>
|
|
</inbound>
|
|
</policies>
|
|
```
|
|
|
|
---
|
|
|
|
## Handtering av brytende endringer
|
|
|
|
### Hva er en brytende endring for AI-API-er?
|
|
|
|
| Endring | Brytende? | Strategi |
|
|
|---------|-----------|---------|
|
|
| Legge til nytt valgfritt felt i response | Nei | Revisjon |
|
|
| Endre modellnavn | Ja | Ny versjon |
|
|
| Fjerne felt fra response | Ja | Ny versjon |
|
|
| Endre feilformat | Ja | Ny versjon |
|
|
| Endre token-tellemekanisme | Ja | Ny versjon |
|
|
| Legge til ny operasjon | Nei | Revisjon |
|
|
| Endre autentiseringsmetode | Ja | Ny versjon |
|
|
| Oppdatere underliggende modell (samme API) | Avhenger* | Revisjon eller versjon |
|
|
|
|
\* Modelloppgraderinger som gir vesentlig annerledes output bor behandles som brytende.
|
|
|
|
### Versjonering av OpenAPI-spesifikasjon
|
|
|
|
```yaml
|
|
openapi: 3.0.3
|
|
info:
|
|
title: AI Gateway API
|
|
version: '2.0'
|
|
description: |
|
|
## Endringslogg
|
|
### v2.0 (2026-02)
|
|
- Ny modell: gpt-4o-mini
|
|
- Endret responsformat for token_usage
|
|
- Fjernet deprecated 'prompt' field (bruk 'messages')
|
|
|
|
### v1.0 (2025-06) - DEPRECATED
|
|
- Opprinnelig versjon
|
|
- Sunset: 2026-06-30
|
|
contact:
|
|
name: AI Platform Team
|
|
email: ai-platform@virksomhet.no
|
|
```
|
|
|
|
---
|
|
|
|
## Referanser
|
|
|
|
- [Versions in Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/api-management-versions) -- versjoneringsguide
|
|
- [Tutorial: Publish multiple versions of your API](https://learn.microsoft.com/en-us/azure/api-management/api-management-get-started-publish-versions) -- hands-on tutorial
|
|
- [Revisions in Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/api-management-revisions) -- revisjonsstyring
|
|
- [Tutorial: Use revisions to make nonbreaking changes](https://learn.microsoft.com/en-us/azure/api-management/api-management-get-started-revise-api) -- revisjon-tutorial
|
|
- [API design - Versioning (Azure Architecture)](https://learn.microsoft.com/en-us/azure/architecture/microservices/design/api-design#api-versioning) -- designprinsipper
|
|
- [OWASP: Improper inventory management](https://learn.microsoft.com/en-us/azure/api-management/mitigate-owasp-api-threats#improper-inventory-management) -- sikkerhetsanbefalinger
|
|
- [AI gateway in Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/genai-gateway-capabilities) -- AI gateway-oversikt
|
|
|
|
## For Cosmo
|
|
|
|
- **Bruk denne referansen** nar kunden planlegger versjonering av sine AI-API-er, trenger a migrere mellom modellversjoner, eller vil etablere en livssyklusmodell for sine API-endepunkter.
|
|
- For AI gateway som wrapper rundt Azure OpenAI, anbefal query string-versjonering med `api-version` for kompatibilitet med Microsofts eksisterende konvensjon.
|
|
- Skill alltid mellom modellversjoner og API-versjoner -- en modelloppgradering er ikke nodvendigvis en API-versjon. Bruk revisjoner for transparente modelloppgraderinger og versjoner for brytende API-endringer.
|
|
- Anbefal minimum 6 maneders deprecation-periode for norsk offentlig sektor, der integrerte systemer ofte har lange endringssykluser.
|
|
- Bruk alltid `Deprecation` og `Sunset` HTTP-headere (RFC 8594) for a gi maskinlesbare signaler til klienter om kommende avvikling -- dette lar automatiserte systemer varsle forvaltere.
|