ms-ai-architect/skills/ms-ai-engineering/references/rag-architecture/multi-index-federation.md
Kjell Tore Guttormsen 3a73eeafdc refactor(ms-ai-architect): R13 del 1 — nøytraliser Cosmo-personaen i ref-korpusets headinger, etter å ha rettet en gate som var målt usann to ganger
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>
2026-09-12 22:12:28 +02:00

344 lines
14 KiB
Markdown

# Multi-Index Federation and Cross-Search
**Last updated:** 2026-06-19
**Status:** GA (single-index), Not supported (native cross-index)
**Category:** RAG Architecture & Semantic Search
**Type:** reference
**Source:** https://learn.microsoft.com/azure/search/search-multi-region
---
## 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
Et av de vanligste spørsmålene fra enterprise-arkitekter er: "Kan vi søke på tvers av flere Azure AI Search-indekser i en enkelt spørring?" Svaret er **nei** — Azure AI Search støtter ikke native multi-index federation. Hvert søk er alltid avgrenset til én enkelt indeks.
Dette er en bevisst designbeslutning, ikke en begrensning. Enkelt-indeks-søk gir konsistente scorer, unified ranking, og forutsigbar ytelse. Cross-index-søk ville kreve score-normalisering, resultat-merging, og distribuert ranking — noe som introduserer betydelig kompleksitet og uforutsigbarhet.
For scenarioer der data logisk tilhører separate indekser (ulike skjemaer, compliance-krav, eller ulike formål), må applikasjonslaget implementere orkestrering. Denne filen beskriver arkitekturmønstre, routing-strategier og best practices for slike scenarioer.
**Viktig funn:** Microsofts offisielle FAQ sier eksplisitt: *"Can I search across multiple indexes? No. A query is always scoped to a single index."*
**Multi-region støtte:** Azure AI Search er en single-region service, men du kan oppnå høyere reliability ved å deploye identiske search services i flere regioner. Data synkroniseres via push eller pull (indexer) APIer. Load balancing håndteres av Azure Front Door, Traffic Manager, eller Application Gateway. Data residency: innhold lagres i regionen du velger, uten kryssregional dataflyt uten eksplisitt autorisasjon.
**Multi-vector fields (Preview):** Azure AI Search støtter nå multiple vektorer i ett dokumentfelt via `Collection(Edm.ComplexType)` — opp til 100 vektorer per dokument. Nyttig for multimodal data og lange dokumenter. `perDocumentVectorLimit`-parameteren kontrollerer antall matchende vektorer per dokument i query-resultater.
## Kjernekomponenter
### Hvorfor Azure AI Search ikke støtter cross-index queries
| Utfordring | Forklaring |
|-----------|------------|
| **Scoring-isolasjon** | BM25-scores er relative til dokumentfrekvens *innenfor* indeksen — scorer fra ulike indekser kan ikke sammenlignes direkte |
| **Skjema-forskjeller** | Ulike indekser kan ha helt ulike felt, datatyper og analysatorer |
| **Ingen unified ranking** | Ingen innebygd mekanisme for å re-ranke resultater på tvers av indekser |
| **Ingen distribuerte transaksjoner** | Oppdateringer til flere indekser er ikke atomiske |
### Enkelt-indeks vs. multi-indeks
| Aspekt | Enkelt indeks | Multiple indekser |
|--------|--------------|-------------------|
| Query-logikk | Enkel, unified | Kompleks, krever orkestrering |
| Scoring | Konsistent | Inkonsistent mellom indekser |
| Vedlikehold | Enklere | Mer komplekst |
| Filtrering | Native, effektiv | Per-indeks, applikasjons-merging |
| Sikkerhet | Dokumentnivå-filtrering | Indeks-nivå isolasjon |
| Skalerbarhet | Vertikal (større tier) | Horisontal (flere services) |
### Nyere relevante features (2025)
| Feature | Status | Relevans |
|---------|--------|----------|
| Multi-vector field support | GA (2025) | Lagre multiple vektorer per dokument i én indeks |
| Agentic Retrieval | Preview | LLM-assistert query planning, men fremdeles single-index |
| Targeted vector filters | Preview | Filtre spesifikt for vektor-subqueries |
## Arkitekturmønstre
### Mønster 1: Enkelt indeks med filtrering (anbefalt)
**Flyt:** Data fra multiple kilder → Felles indeks med type/kilde-felt → Filtrering ved søk
```python
# Alle dokumenttyper i én indeks med type-felt
results = client.search(
search_text="anskaffelsesregler",
filter="doc_type eq 'regelverk' and department eq 'HR'",
select=["title", "content", "doc_type", "department"],
top=10
)
```
**Fordeler:**
- Enklest implementering
- Unified scoring og ranking
- Native filtrering, facettering
- Ingen orkestreringskode nødvendig
**Ulemper:**
- Skjemaet må være tilstrekkelig fleksibelt for alle dokumenttyper
- Indeksen kan bli stor (skalering vertikalt)
- Alle dokumenter deler analysatorer og innstillinger
**Beste for:** De fleste enterprise-scenarioer der data har lignende struktur.
### Mønster 2: Parallell query med applikasjons-merging
**Flyt:** Query → Fork til N indekser (parallelt) → Samle resultater → Score-normalisering → Merged resultat
```python
from azure.search.documents import SearchClient
from azure.identity import DefaultAzureCredential
import asyncio
async def query_multiple_indexes(query_text, indexes):
credential = DefaultAzureCredential()
async def query_index(index_name):
client = SearchClient(
endpoint=endpoint,
index_name=index_name,
credential=credential
)
results = []
async for result in client.search(search_text=query_text, top=10):
results.append({
"source_index": index_name,
"score": result["@search.score"],
**result
})
return results
# Parallelle queries
tasks = [query_index(idx) for idx in indexes]
all_results = await asyncio.gather(*tasks)
# Flatten og normaliser
merged = []
for results in all_results:
merged.extend(results)
# MERK: Score-normalisering nødvendig her
merged = normalize_scores(merged)
merged.sort(key=lambda x: x["normalized_score"], reverse=True)
return merged[:10]
def normalize_scores(results):
"""Min-max normalisering per indeks."""
by_index = {}
for r in results:
idx = r["source_index"]
if idx not in by_index:
by_index[idx] = []
by_index[idx].append(r)
for idx, items in by_index.items():
scores = [i["score"] for i in items]
min_s, max_s = min(scores), max(scores)
range_s = max_s - min_s if max_s != min_s else 1
for item in items:
item["normalized_score"] = (item["score"] - min_s) / range_s
return results
```
**Fordeler:**
- Støtter fundamentalt ulike skjemaer
- Compliance-isolasjon mellom indekser
- Horisontal skalering
**Ulemper:**
- Score-normalisering er heuristisk, ikke eksakt
- Økt latency (selv med parallellisering)
- Kompleks kode å vedlikeholde
- Resultater kan "konkurrere" unfairly mellom indekser
**Beste for:** Scenarioer med fundamentalt ulike datatyper (HR-håndbok vs. produktkatalog).
### Mønster 3: Query routing basert på intent
**Flyt:** Query → Intent-analyse (LLM/classifier) → Route til riktig indeks → Enkelt-indeks søk → Resultat
```python
def route_query(query_text):
"""Bestem hvilken indeks som er mest relevant."""
# Enkel keyword-basert routing
if any(word in query_text.lower() for word in ["anskaffelse", "kontrakt", "anbud"]):
return "regelverk-index"
elif any(word in query_text.lower() for word in ["personal", "ferie", "lønn"]):
return "hr-index"
else:
return "general-index"
# Eller med LLM-basert intent-klassifisering
def route_query_llm(query_text):
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": "Classify the query into one of: regelverk, hr, general"
}, {
"role": "user",
"content": query_text
}]
)
intent = response.choices[0].message.content.strip()
return f"{intent}-index"
```
**Fordeler:**
- Kun én indeks queries per request (lavest latency)
- Tydelig domene-separasjon
- Skalerbar routing-logikk
**Ulemper:**
- Routing-feil betyr at brukeren ikke finner det de leter etter
- LLM-basert routing legger til latency og kostnad
- Krever vedlikehold av routing-logikk
**Beste for:** Klart adskilte domener med liten overlapp.
### Mønster 4: Multi-region search services
**Flyt:** Query → Nearest region service (via Traffic Manager) → Lokalt søk → Resultat
For geo-distribuerte brukere der latency er kritisk:
- Identiske indekser i flere regioner
- Synkronisering via push/pull API
- Azure Traffic Manager, Front Door, eller Application Gateway for routing
**Beste for:** Globale applikasjoner med latency-krav.
## Beslutningsveiledning
### Valg av indeks-topologi
```
Trenger du ulike skjemaer per datakilde?
├── Nei → Enkelt indeks med filtrering (Mønster 1)
└── Ja → Er datakildene compliance-adskilt?
├── Ja → Multi-indeks med routing (Mønster 3)
└── Nei → Kan skjemaene generaliseres?
├── Ja → Enkelt indeks med complex types
└── Nei → Multi-indeks med parallell query (Mønster 2)
```
### Vanlige feil
1. **Opprette separate indekser for hvert datasett** — Start med filtrering i én indeks
2. **Sammenligne BM25-scores direkte mellom indekser** — Scores er relative, ikke absolutte
3. **Sekvensiell querying av multiple indekser** — Bruk alltid parallell utførelse
4. **Implementere cross-index joins** — Azure AI Search støtter ikke dette
5. **Ignorere skjema-denormalisering** — Dupliser data hvis nødvendig for søkbarhet
### Røde flagg
- Behov for mer enn 3-4 indekser → Vurder om indeksdesignet er suboptimalt
- Brukere klager over manglende resultater → Mulig routing-feil i multi-indeks-oppsett
- Inkonsistente scorer mellom søk → Score-normalisering trenger kalibrering
## Integrasjon med Microsoft-stakken
| Tjeneste | Rolle |
|----------|-------|
| **Azure Traffic Manager** | Geo-basert routing mellom search services |
| **Azure Front Door** | Lastbalansering og CDN for multi-region |
| **Azure Application Gateway** | L7 load balancing for search requests |
| **Azure API Management** | API-gateway med routing-logikk for multi-indeks |
| **Semantic Kernel** | Orchestration-framework for multi-indeks RAG |
## Offentlig sektor (Norge)
### Data-klassifisering og indeks-separasjon
- **Ugradert data:** Kan samles i én indeks med filtrering
- **Fortrolig/begrenset:** Bør ha egen indeks med strengere tilgangskontroll
- **Sikkerhetsgradert:** Kan kreve egen search service i isolert nettverk
### Compliance-krav
- **Arkivloven:** Dokumenter fra ulike arkivserier kan kreve logisk separasjon
- **Forvaltningsloven:** Tilgangskontroll per sak/avdeling
- **GDPR:** Persondata kan kreve egen indeks for enklere sletting (right to be forgotten)
### Anbefalt tilnærming
For de fleste offentlige virksomheter:
1. **Primærindeks:** All ugradert dokumentasjon i én indeks med avdelings-/kategori-filtrering
2. **Sekundærindeks:** Persondata eller begrenset informasjon med RBAC
3. **Routing:** Intent-basert routing for å bestemme hvilken indeks som søkes
## Kostnad og lisensiering
### Kostnadsimplikasjoner av multi-indeks
| Topologi | Kostnadsfaktorer |
|----------|-----------------|
| Enkelt indeks | Én search service, standard lagring og query-kostnad |
| Multiple indekser (én service) | Delte ressurser, men økt lagring |
| Multiple search services | Separate kostnader per service, duplikert lagring |
| Multi-region | Multiplisert lagring + synkroniseringskostnad |
### Kostnadsoptimering
- **Start med enkelt indeks** — Unngå unødvendig kompleksitet og kostnad
- **Bruk replika-fordeling** fremfor separate services der mulig
- **Vurder search service tier** basert på samlet indeksstørrelse og query-volum
- **Synkroniser incrementally** i multi-region — ikke full re-indeksering
## For arkitekten
### Spørsmål å stille kunden
1. Hvor mange datakikylder har dere, og har de lignende eller ulik struktur?
2. Er det compliance-krav som krever fysisk separasjon av data?
3. Trenger brukerne å søke på tvers av alle datakilder, eller er domenene adskilte?
4. Hva er latency-kravene — kan parallell multi-indeks query aksepteres?
5. Har dere geo-distribuerte brukere som trenger multi-region?
6. Hva er budsjett — én stor service vs. flere mindre?
### Fallgruver
- Å designe for cross-index fra start uten å vurdere filtrering i enkelt indeks
- Å underestimere kompleksiteten i score-normalisering og resultat-merging
- Å anta at fremtidige Azure-oppdateringer vil løse cross-index — dette er et bevisst designvalg
- Å bruke LLM for query routing uten fallback til bredere søk
### Anbefalinger per modenhetsnivå
| Nivå | Anbefaling |
|------|------------|
| **Starter** | Enkelt indeks med filtrering — alltid start her |
| **Intermediær** | Legg til separate indekser kun ved compliance-krav, med intent-routing |
| **Avansert** | Multi-region med synkronisering, custom orkestrering, semantic reranking av merged resultater |
### Viktig designprinsipp
> **Default til enkelt indeks med filtrering.** Opprett separate indekser kun når du har en konkret, dokumentert grunn — ikke "for sikkerhets skyld."
Grunner som rettferdiggjør separate indekser:
- Fundamentalt ulikt skjema (tekst vs. strukturert data)
- Compliance-krav til fysisk separasjon
- Ulik livsyklus (hyppig vs. sjelden oppdatering)
- Ulike tilgangsmodeller (intern vs. ekstern)
## Kilder og verifisering
### Verified (MCP-research)
- [Azure AI Search FAQ — Cross-index queries](https://learn.microsoft.com/en-us/azure/search/search-faq-frequently-asked-questions)
- [Multi-region deployments](https://learn.microsoft.com/en-us/azure/search/search-multi-region)
- [Grounding data design — Index topology](https://learn.microsoft.com/en-us/azure/well-architected/ai/grounding-data-design)
- [Multi-vector field support](https://learn.microsoft.com/en-us/azure/search/vector-search-multi-vector-fields)
- [Tutorial: Index from multiple data sources](https://learn.microsoft.com/en-us/azure/search/tutorial-multiple-data-sources)
- [GitHub: Multiple search services (.NET)](https://github.com/Azure-Samples/azure-search-dotnet-scale/tree/main/multiple-search-services)
### Baseline (modellkunnskap)
- Score-normaliserings-kode
- Routing-eksempler
- Offentlig sektor-anbefalinger