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.
313 lines
No EOL
13 KiB
Markdown
313 lines
No EOL
13 KiB
Markdown
# Contextual Retrieval — Kontekstuell berikelse av chunks
|
||
|
||
**Last updated:** 2026-04 | Verified: MCP 2026-04
|
||
**Status:** GA (custom skill pattern), Preview (agentic retrieval)
|
||
**Category:** RAG Architecture & Semantic Search
|
||
**Type:** reference
|
||
**Source:** https://learn.microsoft.com/azure/search/cognitive-search-custom-skill-interface
|
||
|
||
---
|
||
|
||
## Innhold
|
||
|
||
- [Introduksjon](#introduksjon)
|
||
- [Kjernekomponenter](#kjernekomponenter)
|
||
- [Arkitekturmønstre](#arkitekturmønstre)
|
||
- [Beslutningsveiledning](#beslutningsveiledning)
|
||
- [Integrasjon med Microsoft-stakken](#integrasjon-med-microsoft-stakken)
|
||
- [Offentlig sektor (Norge)](#offentlig-sektor-norge)
|
||
- [Kostnad og lisensiering](#kostnad-og-lisensiering)
|
||
- [For arkitekten (Cosmo)](#for-arkitekten-cosmo)
|
||
- [Kilder og verifisering](#kilder-og-verifisering)
|
||
|
||
## Introduksjon
|
||
|
||
Contextual Retrieval er en teknikk der hvert dokumentsegment (chunk) berikes med en LLM-generert kontekstbeskrivelse *før* embedding og indeksering. I tradisjonell RAG mister chunks kontekst når de løsrives fra kildedokumentet — pronomener, forkortelser og referanser blir tvetydige. Contextual Retrieval løser dette ved å prepende en 2-3-setningers forklaring som beskriver segmentets plass i dokumentet.
|
||
|
||
Anthropic dokumenterte teknikken i 2024 og viste at den reduserer retrieval failures med opptil 67% når den kombineres med BM25 og reranking. Microsoft Tech Community har validert tilnærmingen i Azure AI Search med 80-85% reduksjon i token-bruk per query og 31% forbedring i retrieval precision.
|
||
|
||
I Azure-stakken implementeres contextual retrieval via en **Custom Web API Skill** (Azure Functions) som genererer kontekstuell prefiks via Azure OpenAI GPT-4o, integrert i skillset-pipelinen mellom chunking og embedding.
|
||
|
||
---
|
||
|
||
## Kjernekomponenter
|
||
|
||
### Kontekstuell prefiks-generering
|
||
|
||
| Komponent | Beskrivelse |
|
||
|-----------|-------------|
|
||
| **Custom Web API Skill** | Azure Function som mottar chunk + metadata, returnerer kontekstuell prefiks |
|
||
| **LLM (GPT-4o)** | Genererer 2-3 setninger som forklarer chunkens plass i dokumentet |
|
||
| **Text Merge Skill** | Konkatenerer kontekstuell prefiks + original chunk |
|
||
| **Embedding Skill** | Embedder den berikede teksten (prefiks + chunk) |
|
||
|
||
### Eksempel
|
||
|
||
```
|
||
Original chunk: "Forskningen understreket AI"
|
||
→ Problematisk: Hvem, når, hvilken AI?
|
||
|
||
Contextual chunk: "Fra Direktoratet for digital tjenesteutvikling sin 2025-rapport om autonome
|
||
kjøretøy. Dette avsnittet diskuterer AI-teknologier for selvkjørende biler.
|
||
Forskningen understreket AI"
|
||
→ Tydelig: LLM kan nå forstå konteksten
|
||
```
|
||
|
||
### Custom Skill-konfigurasjon
|
||
|
||
```json
|
||
{
|
||
"@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
|
||
"name": "context-generation-skill",
|
||
"uri": "https://<function-app>.azurewebsites.net/api/generate-context",
|
||
"httpMethod": "POST",
|
||
"timeout": "PT90S",
|
||
"context": "/document/pages/*",
|
||
"inputs": [
|
||
{ "name": "chunk", "source": "/document/pages/*" },
|
||
{ "name": "documentTitle", "source": "/document/metadata_storage_name" },
|
||
{ "name": "documentMetadata", "source": "/document/metadata" }
|
||
],
|
||
"outputs": [
|
||
{ "name": "contextualPrefix", "targetName": "context" }
|
||
]
|
||
}
|
||
```
|
||
|
||
### Azure Function (Python)
|
||
|
||
```python
|
||
import azure.functions as func
|
||
from openai import AzureOpenAI
|
||
import json, os
|
||
|
||
client = AzureOpenAI(
|
||
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
|
||
api_key=os.getenv("AZURE_OPENAI_KEY"),
|
||
api_version="2024-10-01-preview"
|
||
)
|
||
|
||
def main(req: func.HttpRequest) -> func.HttpResponse:
|
||
values = req.get_json()['values']
|
||
results = []
|
||
|
||
for record in values:
|
||
chunk = record['data']['chunk']
|
||
doc_title = record['data']['documentTitle']
|
||
|
||
response = client.chat.completions.create(
|
||
model="gpt-4o",
|
||
messages=[{"role": "user", "content": f"""Generate a 2-3 sentence
|
||
contextual summary for this chunk.
|
||
Document: {doc_title}
|
||
Chunk: {chunk}
|
||
Include: document source/type, section/topic, temporal context."""}],
|
||
max_tokens=100,
|
||
temperature=0.3
|
||
)
|
||
|
||
context = response.choices[0].message.content
|
||
results.append({
|
||
"recordId": record['recordId'],
|
||
"data": {"contextualPrefix": context},
|
||
"errors": [], "warnings": []
|
||
})
|
||
|
||
return func.HttpResponse(
|
||
json.dumps({"values": results}),
|
||
mimetype="application/json"
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## Arkitekturmønstre
|
||
|
||
### Mønster 1: Post-chunking context enrichment (anbefalt)
|
||
|
||
**Arkitektur:** Data source → Indexer → Document Layout/Text Split → Custom Context Skill → Text Merge → Embedding → Index
|
||
|
||
**Fordeler:**
|
||
- Enklest å integrere i eksisterende pipelines
|
||
- Bruker standard Azure AI Search skillset-mekanismer
|
||
- Kompatibel med alle chunking-strategier
|
||
|
||
**Ulemper:**
|
||
- Ekstra LLM-kall per chunk (GPT-4o kostnad)
|
||
- Økt indekseringstid (90s timeout per batch)
|
||
|
||
**Anbefalt for:** Alle RAG-systemer der retrieval-kvalitet er viktigere enn indekseringskostnad.
|
||
|
||
### Mønster 2: Pre-chunking context med document summary
|
||
|
||
**Arkitektur:** Data source → Indexer → Document Summary Skill (1 per dokument) → Text Split → Inject Summary as Context → Embedding → Index
|
||
|
||
**Fordeler:**
|
||
- Kun ett LLM-kall per dokument (ikke per chunk)
|
||
- 60-80% kostnadsreduksjon vs. per-chunk context
|
||
- Caching-vennlig
|
||
|
||
**Ulemper:**
|
||
- Mindre spesifikk kontekst per chunk
|
||
- Document summary kan miste nyanser i store dokumenter
|
||
|
||
**Anbefalt for:** Kostnadsbevisste løsninger, homogene dokumentsamlinger.
|
||
|
||
### Mønster 3: Contextual Retrieval + BM25 + Reranking
|
||
|
||
**Arkitektur:** Contextual embedding + BM25 full-text indeksering → Hybrid search (RRF) → Semantic Ranker → Top-k
|
||
|
||
**Effekt (Anthropic benchmarks):**
|
||
|
||
| Metode | Retrieval failure rate | Forbedring |
|
||
|--------|------------------------|------------|
|
||
| Standard embeddings | 5.7% | Baseline |
|
||
| Contextual Embeddings | 3.7% | -35% |
|
||
| + Contextual BM25 | 2.9% | -49% |
|
||
| + Reranking | 1.9% | -67% |
|
||
|
||
**Nøkkel:** BM25 fanger kontekst-spesifikke termer (organisasjonsnavn, datoer) som embeddings kan miste.
|
||
|
||
---
|
||
|
||
## Beslutningsveiledning
|
||
|
||
### Beslutningstabell
|
||
|
||
| Scenario | Anbefalt mønster | Begrunnelse |
|
||
|----------|------------------|-------------|
|
||
| Generell enterprise RAG | Mønster 1 (post-chunking) | Best kvalitet, akseptabel kostnad |
|
||
| Høyt dokumentvolum (>100K docs) | Mønster 2 (document summary) | Kostnadseffektiv |
|
||
| Kritisk retrieval-kvalitet | Mønster 3 (full hybrid) | Maksimal reduksjon i failures |
|
||
| Budget-begrenset PoC | Ingen contextual retrieval | Start med standard hybrid search |
|
||
|
||
### Vanlige feil
|
||
|
||
| Feil | Konsekvens | Løsning |
|
||
|------|------------|---------|
|
||
| Genererer kontekst med gpt-4o-mini | Lavere kvalitet på kontekst | Bruk gpt-4o for kontekst-generering |
|
||
| Ingen caching av document summaries | Gjentatte LLM-kall for samme dokument | Cache summary og gjenbruk per chunk |
|
||
| Ignorerer BM25-indeksering av kontekst | Mister keyword-matching fordeler | Indekser berikede chunks i searchable felt |
|
||
| Overlap > timeout (PT90S) | Skill-feil ved store batcher | Reduser batch-størrelse eller øk timeout |
|
||
|
||
---
|
||
|
||
## Integrasjon med Microsoft-stakken
|
||
|
||
| Tjeneste | Integrasjonspunkt |
|
||
|----------|-------------------|
|
||
| **Azure AI Search** | Skillset pipeline (Custom Web API Skill + Text Merge + Embedding) |
|
||
| **Azure OpenAI** | GPT-4o for kontekst-generering, text-embedding-3-large for embedding |
|
||
| **Azure Functions** | Hosting av custom skill (Python/C#), consumption plan |
|
||
| **Azure AI Document Intelligence** | Document Layout skill for strukturert chunking før context enrichment |
|
||
| **Semantic Kernel** | TextChunker + custom context injection i kode-basert pipeline |
|
||
| **Application Insights** | Monitorering av skill-latency, LLM token-bruk, feilrate |
|
||
|
||
### Fullstendig skillset-pipeline
|
||
|
||
```
|
||
Blob Storage → Indexer → Skillset:
|
||
1. Document Layout skill (struktur → Markdown)
|
||
2. Text Split skill (chunk-størrelse kontroll)
|
||
3. Custom Context Generation skill (GPT-4o)
|
||
4. Text Merge skill (context + chunk)
|
||
5. Azure OpenAI Embedding skill (text-embedding-3-large)
|
||
→ Index (med index projections for parent-child)
|
||
→ Query (hybrid search + semantic ranker)
|
||
```
|
||
|
||
---
|
||
|
||
## Offentlig sektor (Norge)
|
||
|
||
### Dataplassering
|
||
|
||
- **Azure AI Search:** Norway East — data i Norge
|
||
- **Azure Functions:** Norway East — compute i Norge
|
||
- **Azure OpenAI:** Sweden Central (nærmeste region med GPT-4o) — data i EU/EØS
|
||
- **GDPR:** Kontekst-generering behandler dokumentinnhold via LLM — databehandleravtale påkrevd
|
||
|
||
### Relevante vurderinger
|
||
|
||
| Krav | Implikasjon |
|
||
|------|-------------|
|
||
| **Forvaltningsloven** | Kontekstuell prefiks skal ikke endre dokumentets meningsinnhold |
|
||
| **GDPR Art. 17** | Sletting av kildedokument kaskaderer til berikede chunks |
|
||
| **AI Act** | Dokumenter bruk av LLM i indekseringspipeline som del av AI-systemdokumentasjon |
|
||
| **Sikkerhetsloven** | Gradert informasjon kan ikke sendes til Azure OpenAI — bruk on-premises alternativ |
|
||
|
||
---
|
||
|
||
## Kostnad og lisensiering
|
||
|
||
### Kostnadskomponenter
|
||
|
||
| Komponent | Prismodell | Estimat (1 000 dokumenter, 20 chunks/doc) |
|
||
|-----------|------------|-------------------------------------------|
|
||
| Context generation (GPT-4o) | Per token | ~60 NOK (100 tokens/chunk × 20K chunks) |
|
||
| Text embedding (text-embedding-3-large) | Per token | ~5 NOK (berikede chunks er ~30% større) |
|
||
| Azure Functions (consumption) | Per invocation | ~2 NOK |
|
||
| Økt vektorlagring | Per GB | ~5 NOK/mnd (berikede chunks = større indeks) |
|
||
| **Totalt ekstra vs. standard RAG** | — | ~72 NOK per 1 000 dokumenter |
|
||
|
||
### ROI-vurdering
|
||
|
||
Hvis contextual retrieval reduserer irrelevante LLM-kall med 30%:
|
||
- Savings per 1 000 queries: 300 × 10 NOK = 3 000 NOK
|
||
- Incremental cost per 1 000 docs: ~72 NOK
|
||
- **Break-even:** >24 queries per 1 000 dokumenter (svært lav terskel)
|
||
|
||
---
|
||
|
||
## For arkitekten (Cosmo)
|
||
|
||
### Spørsmål å stille kunden
|
||
|
||
1. **"Hvor ofte er retrieval-kvaliteten utilstrekkelig i dag?"** — Contextual retrieval lønner seg mest ved dårlig baseline
|
||
2. **"Hva er typisk dokumentlengde?"** — Lange dokumenter med mange seksjoner gir størst effekt
|
||
3. **"Er det mye tvetydig innhold (pronomen, forkortelser)?"** — Indikerer høy verdi av kontekst
|
||
4. **"Hva er akseptabel indekseringskostnad?"** — GPT-4o kall per chunk er ikke gratis
|
||
5. **"Bruker dere hybrid search (BM25 + vektor)?"** — Contextual retrieval gir størst effekt med hybrid search
|
||
|
||
### Fallgruver
|
||
|
||
- **Hopper over baseline-måling:** Uten metrics på nåværende retrieval-kvalitet kan du ikke bevise forbedring
|
||
- **Kontekst som forvrenger mening:** LLM-generert kontekst kan introdusere feil — valider med stikkprøver
|
||
- **Over-investering i kontekst for enkle use cases:** Noen dokumentsamlinger er allerede godt chunket
|
||
|
||
### Anbefalinger per modenhetsnivå
|
||
|
||
| Modenhet | Anbefaling |
|
||
|----------|------------|
|
||
| **Prototyp** | Standard chunking + hybrid search. Mål baseline retrieval metrics. |
|
||
| **Pilot** | Legg til document summary-basert kontekst (mønster 2). Test med 500 docs. |
|
||
| **Produksjon** | Per-chunk contextual retrieval (mønster 1) + BM25 + semantic ranker. |
|
||
| **Enterprise** | Full mønster 3 med reranking. A/B-testing. Automated quality evaluation. |
|
||
|
||
---
|
||
|
||
## Kilder og verifisering
|
||
|
||
| Kilde | Konfidens | URL |
|
||
|-------|-----------|-----|
|
||
| Contextual Retrieval (Anthropic) | **Verified** | [anthropic.com](https://www.anthropic.com/news/contextual-retrieval) |
|
||
| Context-Aware RAG System (MS Tech Community) | **Verified** | [techcommunity.microsoft.com](https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/context-aware-rag-system-with-azure-ai-search-to-cut-token-costs-and-boost-accur/4456810) |
|
||
| Building Contextual Retrieval System (MS Tech Community) | **Verified** | [techcommunity.microsoft.com](https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/building-a-contextual-retrieval-system-for-improving-rag-accuracy/4271924) |
|
||
| Custom skill interface (Azure AI Search) | **Verified** | [learn.microsoft.com](https://learn.microsoft.com/en-us/azure/search/cognitive-search-custom-skill-interface) |
|
||
| Custom skill example (Python) | **Verified** | [learn.microsoft.com](https://learn.microsoft.com/en-us/previous-versions/azure/search/cognitive-search-custom-skill-python) |
|
||
| Retrieval failure benchmarks | **Baseline** | Anthropic research, validert av Microsoft |
|
||
|
||
|
||
### Custom Skill Interface (oppdatert 2026-04)
|
||
|
||
Custom skills integreres i Azure AI Search enrichment pipeline via `#Microsoft.Skills.Custom.WebApiSkill`.
|
||
|
||
**Interface-krav:**
|
||
- HTTPS endpoint (Azure Functions, containers, eller annen Azure-hosted tjeneste)
|
||
- Aksepterer JSON batch: `{"values": [{"recordId": "...", "data": {...}}, ...]}`
|
||
- Returnerer JSON batch: `{"values": [{"recordId": "...", "data": {...}, "errors": [], "warnings": []}]}`
|
||
- Timeout: default 30s, maks 230s (`PT230S`)
|
||
- Autentisering: API-key i URI/header, eller managed identity med `authResourceId`
|
||
|
||
**Kontekstuell berikelse via custom skill:**
|
||
Custom skills brukes for contextual retrieval der hver chunk berikes med kontekst fra omliggende tekst (f.eks. "Dette er fra kapittel 3 om sikkerhet..."). Custom skill kaller LLM med original dokument + chunk, og returnerer kontekstualisert chunk for bedre embedding-kvalitet. |