Ordre 20260912T193441Z-7358817909. Steg 1 var ikke transformen, men å rette
roadmapens R13-gate og få den ratifisert. Gaten `grep -rl "Cosmo"
skills/*/references -> 0` var usann på to uavhengige måter:
1. Ordren fanget den første: 451 av forekomstene er Azure Cosmos DB, ekte
produktinnhold. Diskriminatoren er ikke bokstaven «s» — `Cosmos <norsk
substantiv>` er genitiv av personaen (`### Cosmos tonalitet`), mens
`Cosmos DB`/`CosmosClient`/`cosmos_ru` er produkt.
2. Denne økten fant den andre: 132 persona-forekomster ligger i prosa,
tabeller, dialog-replikker og proveniens-linjer. Heading-nøytralisering
kan ikke nå dem, så «0 persona» er uoppnåelig også under den ratifiserte
formen. Operatøren ratifiserte alternativ A: gaten speiler formen, og de
132 bokføres til R13b/R14.
Tre korreksjoner av premisser som sto i ordren og STATE:
«ca 320 produkt» -> 451 (case-sensitivt nett manglet 327 lowercase
TOC-ankre + 99 identifikatorer; sann nevner 1 638)
«169 headinger» -> 401. 169 var `^## For Cosmo`-prefikset (168) og var
internt inkonsistent med sin egen topp-variant (204)
«417 matcher ingen
populasjon» -> 417 er cosmo-headinger utenfor kodefences; briefens
nevner var reell hele tiden
Fence-bevissthet er målt skadelig, ikke nødvendig: begge toggle-regler er
gale på dette korpuset (naiv toggle skjuler en ekte heading i
chain-of-thought-prompting.md, CommonMark-regelen ubalanserer
service-level-documentation-dr.md). Fence-agnostisk deteksjon finner 401
heading-linjer i nøyaktig de samme 40 variantene som fence-bevisst finner
400 i — ingen kodeblokk-linje er byte-identisk til en persona-heading. Derfor
nøkles transformen på 40 enumererte heading-tekster og ignorerer fences. En
ukjent variant kaster; en slug-kollisjon kaster. Ingenting auto-fikses.
TOC-en regenereres ikke, den rettes kirurgisk: alle 327 persona-lenker hadde
lenketekst lik én av de 40 heading-tekstene og anker lik slugify av den
(327/327, 0 avvik), så heading og TOC-entry skrives i samme operasjon og
ingen mellomtilstand etterlater en død lenke.
Ratifisert målform: `For Cosmo`, `For Cosmo Skyberg` og `For arkitekten
(Cosmo)` konvergerer på `For arkitekten`. To filer kolliderte og er adjudisert
ved å lese dem, ikke ved regel.
Verifisering (alle 7 kriterier fra ordren):
G1 persona på heading-linjer 401 -> 0
G2 døde fragmentlenker 1 -> 1 (pre-eksisterende, unntatt)
G3 produkt-forekomster 451 -> 451; `Cosmos DB|Azure Cosmos` 308 = 308
de 3 kun-produkt-filene byte-identiske
nettet validert begge veier injisert persona feller G1; genitiv feller G1;
produkt-heading og de 3 filene passerer
hele diffen 802 heading-linjer + 654 TOC-linjer, ANNET = 0
linjeantall 728 lagt til = 728 slettet
suite 1120/1120 (1097 + 23 nye)
validate-plugin 250 PASS / 0 FAIL
stikkprøve 10 filer, alle 5 skills, inkl. de 3 mest
produkt-tunge (26/20/19) — kun heading+TOC
Utenfor scope, urørt: de 4 SKILL.md, de 23 commands, CLAUDE.md, README.md,
NOTICE.md, docs/ (alt R14).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
301 lines
12 KiB
Markdown
301 lines
12 KiB
Markdown
# Hierarchical RAG Patterns — Multi-nivå retrieval
|
|
|
|
**Last updated:** 2026-06-19
|
|
**Status:** GA (index projections), Preview (agentic retrieval)
|
|
**Category:** RAG Architecture & Semantic Search
|
|
**Type:** reference
|
|
**Source:** https://learn.microsoft.com/azure/search/retrieval-augmented-generation-overview
|
|
|
|
---
|
|
|
|
## 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](#for-arkitekten)
|
|
- [Kilder og verifisering](#kilder-og-verifisering)
|
|
|
|
## Introduksjon
|
|
|
|
Hierarchical RAG organiserer kunnskap i multi-nivå strukturer i stedet for flat chunk-indeksering. Ved å etablere relasjoner mellom parent-dokumenter, seksjoner og chunks muliggjøres en «zoom inn/ut»-mekanisme der søk starter bredt (dokumentnivå) og driller ned til relevante segmenter.
|
|
|
|
Azure AI Search implementerer hierarkisk RAG gjennom **index projections** som håndterer one-to-many relasjoner mellom kildedokumenter og chunks. Document Intelligence Layout skill bevarer dokumentstruktur (headings, avsnitt) som muliggjør hierarkisk navigasjon.
|
|
|
|
Forskning (2025-2026) viser at hierarkisk retrieval gir 47% høyere Hit@1 og opptil 250x reduksjon i token-kostnad sammenlignet med flat retrieval, fordi søkeområdet reduseres gjennom coarse-to-fine filtrering.
|
|
|
|
---
|
|
|
|
## Kjernekomponenter
|
|
|
|
### Parent-child relasjoner i Azure AI Search
|
|
|
|
Azure AI Search tilbyr tre arkitekturmønstre for parent-child indeksering:
|
|
|
|
| Mønster | Beskrivelse | Brukstilfelle |
|
|
|---------|-------------|---------------|
|
|
| **Single index, repeating parent fields** | Parent-metadata repeteres per chunk | Standard RAG, enkel query-logikk (anbefalt) |
|
|
| **Single index, mixed document shapes** | Parents og chunks co-eksisterer | Fulldokument-søk + chunk-søk i én indeks |
|
|
| **Separate parent-child indexes** | Dedikert parent-index + child-index | Enterprise med strikt separasjon, compliance |
|
|
|
|
### Index projection-konfigurasjon
|
|
|
|
```json
|
|
{
|
|
"indexProjections": {
|
|
"selectors": [
|
|
{
|
|
"targetIndexName": "my_consolidated_index",
|
|
"parentKeyFieldName": "parent_id",
|
|
"sourceContext": "/document/pages/*",
|
|
"mappings": [
|
|
{ "name": "chunk", "source": "/document/pages/*" },
|
|
{ "name": "chunk_vector", "source": "/document/pages/*/chunk_vector" },
|
|
{ "name": "title", "source": "/document/title" }
|
|
]
|
|
}
|
|
],
|
|
"parameters": {
|
|
"projectionMode": "skipIndexingParentDocuments"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Nøkkelparametere:**
|
|
|
|
| Parameter | Verdier | Beskrivelse |
|
|
|-----------|---------|-------------|
|
|
| `projectionMode` | `skipIndexingParentDocuments` / `includeIndexingParentDocuments` | Kun chunks eller begge |
|
|
| `parentKeyFieldName` | `parent_id`, `text_parent_id` | Felt som kobler chunk → parent |
|
|
| `sourceContext` | `/document/pages/*` | Enrichment path for granularitet |
|
|
|
|
### Automatisk chunk-ID generering
|
|
|
|
Azure AI Search genererer chunk-IDer basert på parent-ID:
|
|
- Parent: `aa1b22c33`
|
|
- Chunk 1: `aa1b22c33_pages_0`
|
|
- Chunk 2: `aa1b22c33_pages_1`
|
|
|
|
Hash-komponenten endres ved parent-oppdatering → sikrer change tracking.
|
|
|
|
---
|
|
|
|
## Arkitekturmønstre
|
|
|
|
### Mønster 1: Single index med parent-metadata (anbefalt)
|
|
|
|
**Arkitektur:** Data source → Indexer → Document Layout → Text Split → Embedding → Index projections (parent fields repeteres per chunk)
|
|
|
|
**Index-schema:**
|
|
```json
|
|
{
|
|
"fields": [
|
|
{ "name": "chunk_id", "type": "Edm.String", "key": true },
|
|
{ "name": "parent_id", "type": "Edm.String", "filterable": true },
|
|
{ "name": "chunk", "type": "Edm.String", "searchable": true },
|
|
{ "name": "chunk_vector", "type": "Collection(Edm.Single)" },
|
|
{ "name": "title", "type": "Edm.String", "filterable": true },
|
|
{ "name": "section_heading", "type": "Edm.String", "filterable": true },
|
|
{ "name": "page_number", "type": "Edm.Int32", "filterable": true }
|
|
]
|
|
}
|
|
```
|
|
|
|
**Fordeler:**
|
|
- Enklest å implementere og vedlikeholde
|
|
- Én query gir chunks med full parent-kontekst
|
|
- Metadata-filtrering (tittel, seksjon) for hierarkisk drill-down
|
|
|
|
**Anbefalt for:** 80% av RAG-løsninger, spesielt ved enkel dokumentstruktur.
|
|
|
|
### Mønster 2: Multi-resolution retrieval med lookup-queries
|
|
|
|
**Arkitektur:** Child index (chunks) + Parent index (summaries/metadata) → Vector search på child → Lookup til parent
|
|
|
|
**Implementering:**
|
|
```python
|
|
# Steg 1: Hent relevante chunks
|
|
child_results = child_client.search(
|
|
vector_queries=[VectorQuery(vector=query_embedding, k=5)],
|
|
select=["chunk_id", "parent_id", "chunk"]
|
|
)
|
|
|
|
# Steg 2: Lookup parent-dokumenter
|
|
parent_ids = {r["parent_id"] for r in child_results}
|
|
parent_docs = parent_client.search(
|
|
filter=f"parent_id in ({','.join(parent_ids)})",
|
|
select=["parent_id", "title", "summary"]
|
|
)
|
|
|
|
# Steg 3: Assembler kontekst
|
|
context = []
|
|
for chunk in child_results:
|
|
parent = next(p for p in parent_docs if p["parent_id"] == chunk["parent_id"])
|
|
context.append({
|
|
"chunk": chunk["chunk"],
|
|
"source": parent["title"],
|
|
"summary": parent["summary"]
|
|
})
|
|
```
|
|
|
|
**Fordeler:**
|
|
- «Zoom ut» fra chunk til fullt dokument
|
|
- Parent-summary gir LLM bedre kontekstuell forståelse
|
|
- Sporbarhet for citation og audit
|
|
|
|
**Anbefalt for:** Enterprise RAG med krav til kildehenvisning og compliance.
|
|
|
|
### Mønster 3: Retrieval cascade (Summary → Section → Chunk)
|
|
|
|
**Arkitektur:** Tre indeksnivåer med progressiv filtrering:
|
|
|
|
```
|
|
Nivå 1: Document summaries → Velg relevante dokumenter (top-10)
|
|
Nivå 2: Section headings → Velg relevante seksjoner (top-20)
|
|
Nivå 3: Chunks → Hent detaljerte segmenter (top-5)
|
|
```
|
|
|
|
**Fordeler:**
|
|
- Drastisk reduksjon av søkerom (10-100x)
|
|
- Minimerer «lost in the middle»-problemet
|
|
- Opptil 250x reduksjon i token-kostnad
|
|
|
|
**Ulemper:**
|
|
- Tre separate søkeoperasjoner (økt latency)
|
|
- Kompleks indeksstruktur
|
|
- Krever generering av summaries per dokument/seksjon
|
|
|
|
**Anbefalt for:** Store dokumentsamlinger (>100K docs) der flat søk gir dårlig precision.
|
|
|
|
---
|
|
|
|
## Beslutningsveiledning
|
|
|
|
### Beslutningstabell
|
|
|
|
| Scenario | Volum | Anbefalt mønster |
|
|
|----------|-------|------------------|
|
|
| Standard RAG | <50K docs | Mønster 1 (single index, parent fields) |
|
|
| Krav til citation/sporbarhet | Alle | Mønster 2 (lookup queries) |
|
|
| Stort volum, lav precision | >100K docs | Mønster 3 (retrieval cascade) |
|
|
| Compliance/audit | Alle | Mønster 2 med `dataDeletionDetectionPolicy` |
|
|
|
|
### Vanlige feil
|
|
|
|
| Feil | Konsekvens | Løsning |
|
|
|------|------------|---------|
|
|
| Ingen parent-child mapping | Kan ikke spore chunk → kildedokument | Bruk index projections med `parentKeyFieldName` |
|
|
| Ignorerer `dataDeletionDetectionPolicy` | GDPR right to erasure brytes | Konfigurer cascade deletion på data source |
|
|
| Flat index for >100K docs | Dårlig precision, høy token-kostnad | Vurder retrieval cascade |
|
|
| Manglende metadata (section, page) | Ingen mulighet for hierarkisk filtrering | Legg til `section_heading` og `page_number` |
|
|
|
|
---
|
|
|
|
## Integrasjon med Microsoft-stakken
|
|
|
|
| Tjeneste | Integrasjonspunkt |
|
|
|----------|-------------------|
|
|
| **Azure AI Search** | Index projections, parent-child mapping, lookup queries |
|
|
| **Azure AI Document Intelligence** | Document Layout skill med `markdownHeaderDepth: "h3"` |
|
|
| **Azure Content Understanding** | Semantisk chunking med kryssende sider |
|
|
| **Azure OpenAI** | Summary-generering for retrieval cascade |
|
|
| **Semantic Kernel** | TextSearchProvider med namespace-filtrering |
|
|
| **Azure Cosmos DB** | Alternativ parent-child storage med hierarkisk query |
|
|
|
|
### Document Layout skill for hierarkisk chunking
|
|
|
|
> **Anbefaling (2026-06):** For **nye** skillsets anbefaler Microsoft nå **Azure Content Understanding-skill** (`#Microsoft.Skills.Util.ContentUnderstandingSkill`) i stedet for Document Layout-skill — den samler semantisk chunking, AI-genererte bildebeskrivelser og forbedret tabelluttrekk i én skill. Document Layout-skill (under) er fortsatt støttet og dokumentert for **eksisterende** pipelines.
|
|
|
|
```json
|
|
{
|
|
"@odata.type": "#Microsoft.Skills.Util.DocumentIntelligenceLayoutSkill",
|
|
"context": "/document",
|
|
"outputMode": "oneToMany",
|
|
"markdownHeaderDepth": "h3",
|
|
"inputs": [{"name": "file_data", "source": "/document/file_data"}],
|
|
"outputs": [{"name": "markdown_document", "targetName": "markdownDocument"}]
|
|
}
|
|
```
|
|
|
|
Output: Markdown med `# H1`, `## H2`, `### H3` som bevarer hierarkisk dokumentstruktur.
|
|
|
|
---
|
|
|
|
## Offentlig sektor (Norge)
|
|
|
|
### Dataplassering
|
|
|
|
- **Azure AI Search:** Norway East — hierarkisk indeks forblir i Norge
|
|
- **Document Intelligence:** West Europe — dokument-parsing i EU
|
|
|
|
### Relevante vurderinger
|
|
|
|
| Krav | Implikasjon |
|
|
|------|-------------|
|
|
| **Forvaltningsloven** | Chunks må spores til kildedokument — krev parent-child mapping |
|
|
| **GDPR Art. 17** | Sletting av kildedokument MÅ kaskadere til alle chunks |
|
|
| **AI Act** | Hierarkisk sporbarhet støtter forklarbarhetskrav |
|
|
| **Arkivloven** | Parent-index bevarer dokumentkontekst for arkivformål |
|
|
|
|
---
|
|
|
|
## Kostnad og lisensiering
|
|
|
|
### Kostnadskomponenter
|
|
|
|
| Komponent | Kostnad | Notat |
|
|
|-----------|---------|-------|
|
|
| Index projections | Inkludert i AI Search | Ingen ekstra kostnad |
|
|
| Document Layout skill | ~$0.01-0.05/side | Document Intelligence-prising |
|
|
| Summary-generering (cascade) | GPT-4o per dokument | ~$0.01-0.05/dokument |
|
|
| Ekstra indekslagring (parent-felter) | Per GB | ~20-30% økning ved repeterte felter |
|
|
|
|
### Optimaliseringstips
|
|
|
|
1. **Bruk `projectionMode: skipIndexingParentDocuments`** for å unngå dobbelt lagring
|
|
2. **Generer summaries off-peak** for å minimere compute-kostnad
|
|
3. **Sett `stored: false` på vektorfelt** for å spare lagringsplassn
|
|
|
|
---
|
|
|
|
## For arkitekten
|
|
|
|
### Spørsmål å stille kunden
|
|
|
|
1. **"Trenger brukerne å se hvilke dokumenter et svar kommer fra?"** — Hvis ja, krev parent-child mapping
|
|
2. **"Hvor mange dokumenter er i samlingen?"** — >100K → vurder cascade
|
|
3. **"Er det compliance-krav til sletting (GDPR)?"** — Krev cascade deletion
|
|
4. **"Har dokumentene tydelig struktur (headings, kapitler)?"** — Bruk Document Layout skill
|
|
5. **"Hva er akseptabel query-latency?"** — Cascade = 2-3x latency
|
|
|
|
### Fallgruver
|
|
|
|
- **Over-engineering for småskala:** Single index med parent fields er nok for <50K docs
|
|
- **Glemmer deletion policy:** GDPR-brudd hvis chunks overlever parent-sletting
|
|
- **Cascade uten summaries:** Første nivå i cascade trenger AI-genererte summaries for å fungere
|
|
|
|
### Anbefalinger per modenhetsnivå
|
|
|
|
| Modenhet | Anbefaling |
|
|
|----------|------------|
|
|
| **Prototyp** | Single index med `parent_id` felt. Ingen cascade. |
|
|
| **Pilot** | Index projections med parent fields + Document Layout. |
|
|
| **Produksjon** | Mønster 2 (lookup queries) + cascade deletion policy. |
|
|
| **Enterprise** | Retrieval cascade + AI-summaries + automated quality evaluation. |
|
|
|
|
---
|
|
|
|
## Kilder og verifisering
|
|
|
|
| Kilde | Konfidens | URL |
|
|
|-------|-----------|-----|
|
|
| Define index projections (Azure AI Search) | **Verified** | [learn.microsoft.com](https://learn.microsoft.com/en-us/azure/search/search-how-to-define-index-projections) |
|
|
| Chunk and vectorize by document layout | **Verified** | [learn.microsoft.com](https://learn.microsoft.com/en-us/azure/search/search-how-to-semantic-chunking) |
|
|
| RAG and generative AI (Azure AI Search) | **Verified** | [learn.microsoft.com](https://learn.microsoft.com/en-us/azure/search/retrieval-augmented-generation-overview) |
|
|
| Model complex data types | **Verified** | [learn.microsoft.com](https://learn.microsoft.com/en-us/azure/search/search-howto-complex-data-types) |
|
|
| Hierarchical RAG research | **Baseline** | [emergentmind.com](https://www.emergentmind.com/topics/hierarchical-rag) |
|