# Hybrid Search - Full-Text and Vector Combined

**Last updated:** 2026-04 | Verified: MCP 2026-04
**Status:** GA
**Category:** RAG Architecture & Semantic Search

---

## Introduksjon

Hybrid search i Azure AI Search kombinerer full-text (BM25) søk med vektorsøk i en enkelt spørring. De to søkemetodene kjøres parallelt, og resultatene fusjoneres via **Reciprocal Rank Fusion (RRF)**-algoritmen. Dette gir bedre relevans enn enten keyword- eller vektorsøk alene, fordi BM25 fanger eksakte termer mens vektorsøk fanger semantisk mening.

RRF-algoritmen beregner en samlet score basert på formelen `1/(rank + k)`, der `rank` er dokumentets posisjon i hver resultatliste og `k` er en konstant (typisk 60). Dokumenter som rangerer høyt på tvers av begge metoder prioriteres. Dette gjør hybrid search robust for varierte spørringstyper — fra eksakte nøkkelord-søk til vage, konseptuelle spørsmål.

Hybrid search er tilgjengelig fra Basic-tier og oppover i Azure AI Search, og krever ingen ekstra kostnad utover standard spørringsoperasjoner. Funksjonen er GA siden 2023, med kontinuerlige forbedringer i scoring og ytelse.

## Kjernekomponenter

### Scoring-modeller

| Søkemetode | Score-property | Algoritme | Område |
|------------|----------------|-----------|--------|
| Full-text | `@search.score` | BM25 | 0 til ubegrenset |
| Vector | `@search.score` | HNSW/KNN | 0.333–1.00 (Cosine) |
| Hybrid | `@search.score` | RRF | 0 til ~1/k per query |
| Semantic ranking | `@search.rerankerScore` | ML comprehension | 0.00–4.00 |

### Vektervekting

Vector queries støtter `weight`-parameter for å justere relativ viktighet:

- **Default:** 1.0
- **Redusere:** 0.5 (halverer vektorens bidrag til RRF-scoren)
- **Øke:** 2.0 (dobler vektorens bidrag)

```python
from azure.search.documents.models import VectorizedQuery

vector_query = VectorizedQuery(
    vector=query_vector,
    k_nearest_neighbors=10,
    fields="DescriptionVector",
    weight=2.0  # Prioriter semantisk likhet
)
```

### maxTextRecallSize

Kontrollerer hvor mange BM25-resultater som mates inn i RRF:

- **Default:** 1000
- **Justérbar:** Høyere verdi = mer tekst-recall, men økt latency
- **Anbefaling:** Default er tilstrekkelig for de fleste scenarioer

## Arkitekturmønstre

### Mønster 1: Hybrid Search uten semantic ranking

**Flyt:** Brukerquery → BM25 + Vector (parallelt) → RRF-fusjon → Topp-N resultater

**Fordeler:**
- Lavere latency (ingen L2-reranking)
- Fungerer på alle tier (Basic+)
- Ingen ekstra kostnad for semantic ranking

**Ulemper:**
- RRF er en generell ranking-algoritme, ikke domene-optimert
- Lavere relevans for komplekse, naturnlige spørsmål

**Beste for:** Høy-volum søk der latency er kritisk, eller der BM25+vector gir tilstrekkelig relevans.

### Mønster 2: Hybrid Search med Semantic Ranking (anbefalt)

**Flyt:** Brukerquery → BM25 + Vector (parallelt) → RRF-fusjon → Semantic Ranker (topp 50) → Topp-N resultater

**Fordeler:**
- Best mulig relevans (dokumentert i benchmarks)
- Semantiske captions og answers inkludert
- Scoring profile kan legges på etter semantic ranking

**Ulemper:**
- Krever S1-tier eller høyere
- Ekstra kostnad per query (etter 1000 gratis/måned)
- Noe høyere latency (~50–200ms ekstra)

**Beste for:** Enterprise RAG, kunnskapsportaler, dokumentsøk i offentlig sektor.

### Mønster 3: Hybrid Search med filtrering og facettering

**Flyt:** Brukerquery + filter/facet → Prefilter/Postfilter → BM25 + Vector → RRF → Resultater med facets

```python
results = client.search(
    search_text="luxury hotel",
    vector_queries=[vector_query],
    filter="Rating gt 4 and ParkingIncluded eq true",
    vector_filter_mode="postFilter",
    facets=["Category", "Address/StateProvince"],
    select=["HotelName", "Description", "Rating"],
    top=10
)
```

**Fordeler:**
- Kombinerer semantisk søk med strukturert filtrering
- Støtter faceted navigation for brukergrensesnitt

**Ulemper:**
- `preFilter` kan redusere vektorkandidater for mye
- `postFilter` kan returnere færre resultater enn forventet

**Beste for:** E-commerce-liknende søk, sakssystemer med metadata-filtre.

## Beslutningsveiledning

### Når bruke hybrid search vs. alternativer

| Scenario | Anbefaling | Begrunnelse |
|----------|------------|-------------|
| Generell enterprise-søk | Hybrid + semantic | Best relevans dokumentert |
| Eksakt ID/kode-søk | Kun BM25 | Vektor tilfører ingen verdi for eksakte treff |
| Konseptuelle spørsmål | Hybrid + semantic | BM25 fanger nøkkelord, vektor fanger mening |
| Multilingual søk | Hybrid med fokus på vektor | Vektor bypasser språk-analysatorer |
| Strukturert data | BM25 + filtre | Vektor er designet for ustrukturert tekst |
| Høy-volum, lav-latency | Hybrid uten semantic | Semantic ranking legger til latency |

### Vanlige feil

1. **Ikke sette k=50 for vektor-queries med semantic ranking** — Semantic ranker jobber med topp 50, så `k` bør være minst 50
2. **Bruke `preFilter` med semantic ranking** — Kan eliminere relevante resultater før ranking
3. **Sammenligne scores på tvers av indekser** — BM25-scores er relative til dokumentfrekvens i indeksen
4. **Ignorere vekter** — Default-vekter (1.0/1.0) passer ikke alltid domenet

### Røde flagg

- Lav relevans med hybrid search → Sjekk om embedding-modellen er trent for domenet
- Høy latency → Vurder om semantic ranking er nødvendig for dette use caset
- Uventede resultater med filtre → Sjekk `preFilter` vs. `postFilter` modus

## Integrasjon med Microsoft-stakken

| Tjeneste | Integrasjon |
|----------|-------------|
| **Azure OpenAI** | Embedding-modeller (text-embedding-3-large) for vektordelen |
| **Azure AI Foundry** | Integrert vektorisering via skills i indekserings-pipeline |
| **Copilot Studio** | Azure AI Search som grounding-kilde for Copilot-agenter |
| **Semantic Kernel** | `AzureAISearchVectorStore` connector for hybrid queries |
| **Power Platform** | AI Builder kan bruke Azure AI Search via custom connectors |

## Offentlig sektor (Norge)

### Datasuverenitet
- Azure AI Search er tilgjengelig i **Norway East** og **Norway West**
- All indeksdata forblir i valgt region
- Fullt GDPR-kompatibelt via Azures rammeverk
- Microsofts EU Data Boundary gjelder for norske deployments

### Sikkerhetsfunksjoner
- **Azure Private Link:** Isoler search service fra offentlig internett
- **Managed Identity:** Sikker autentisering via Entra ID (ingen API-nøkler)
- **Customer-managed keys:** Krypter data med egne nøkler i Azure Key Vault
- **Dokumentnivå-sikkerhet:** Filtrer resultater basert på brukeridentitet
- **RBAC:** Rollebasert tilgangskontroll for indeks- og spørringsoperasjoner

### Relevante use cases
- **Regelverk og retningslinjer:** Kombinér eksakt match (§-referanser) med semantisk søk
- **Sakssystemer:** Hybrid search med metadata-filtrering per sakstype
- **Publikumstjenester:** Multilingual search der vektor bypasser språkbarrierer
- **Arkivsøk:** Historisk dokumentasjon med varierende terminologi

## Kostnad og lisensiering

### Tier-krav
| Funksjon | Minimumstier |
|----------|-------------|
| Hybrid search (BM25 + vektor) | Basic |
| Scoring profiles | Alle tier |
| Semantic ranking | S1+ (1000 gratis/mnd) |
| Integrert vektorisering | Basic+ |

### Kostnadsoptimering
- **Scalar/binary quantization** reduserer vektorlagring med opptil 50% (preview)
- **`stored: false`** på vektorfelt sparer lagring hvis du ikke trenger å hente embeddings
- **Narrower data types** for vektorfelt der presisjon tillater det
- **Tune `k`-parameter** — færre naboer = lavere kostnad
- Hybrid queries teller som **én spørringsoperasjon** (ingen prisøkning vs. enkelt søk)

## For arkitekten (Cosmo)

### Spørsmål å stille kunden
1. Hvilke typer søk gjør brukerne deres — eksakte nøkkelord, naturlige spørsmål, eller begge deler?
2. Hvor viktig er latency vs. relevans for dette use caset?
3. Har dere strukturerte metadata (kategorier, datoer, avdelinger) som bør filtreres?
4. Hvilket tier bruker dere i dag, og er semantic ranking et alternativ?
5. Trengs multilingual support?
6. Hvor store er dokumentene, og hvordan chunkes de?

### Fallgruver
- Å starte med ren vektor-search og legge til BM25 etterpå er vanskeligere enn å starte med hybrid
- Scoring profiles og semantic ranking interagerer på ikke-åpenbare måter — test grundig
- Vektervekting krever eksperimentering; det finnes ingen universell "riktig" vekt

### Anbefalinger per modenhetsnivå
| Nivå | Anbefaling |
|------|------------|
| **Starter** | Hybrid search med default-vekter, uten semantic ranking |
| **Intermediær** | Legg til semantic ranking, tune vekter basert på evaluering |
| **Avansert** | Scoring profiles, A/B-testing med debug-modus, custom reranking |

### Debug-tips
Bruk `debug: "vector"` eller `debug: "semantic"` i API-kallet for å pakke ut subscores og forstå ranking-bidrag fra hver komponent.

## Kilder og verifisering

### Verified (MCP-research)
- [Hybrid Search Overview](https://learn.microsoft.com/en-us/azure/search/hybrid-search-overview)
- [RRF Ranking Algorithm](https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking)
- [Hybrid Query How-To](https://learn.microsoft.com/en-us/azure/search/hybrid-search-how-to-query)
- [Relevance Overview](https://learn.microsoft.com/en-us/azure/search/search-relevance-overview)
- [BM25 Scoring Details](https://learn.microsoft.com/en-us/azure/search/index-similarity-and-scoring)
- [Vector Search Overview](https://learn.microsoft.com/en-us/azure/search/vector-search-overview)

### Baseline (modellkunnskap)
- Kostnadsoptimerings-tips basert på generell Azure-erfaring
- Offentlig sektor-anbefalinger basert på norsk kontekst


### Hybrid Search — Konfigurasjon og Tuning (oppdatert 2026-04)

**Anbefalt startpunkt:** Balanced hybrid med `k=30-50`, `top=10-20`, semantic ranking etter relevans-test.

**maxTextRecallSize (preview):** Kontrollerer BM25-bidrag til RRF
- Default: 1000, Max: 10000
- Reduser hvis vector dominerer; øk for store indekser der default ikke gir nok dekning
- `countAndFacetMode: "countRetrievableResults"` scope-r teller til maxTextRecallSize-vinduet

**Ytelsesmønstre:**
- Recall-first: øk `maxTextRecallSize` gradvis
- Precision-first: lav `k` og `top`, unngå unødvendig semantic ranker

**Filter-moduser i hybrid:**
- `preFilter` (default) — filtrerer FØR query, reduserer søkerom for begge subqueries
- `postFilter` — filtrerer ETTER, men kan gi <50 docs til semantic ranker
- `strictPostFilter` (preview) — strengeste modus, ikke anbefalt med semantic ranker
- `filterOverride` (preview) — per-vectorQuery filter, overstyrer globalt filter

**SDK-støtte:** Python (`azure-search-documents`), C# (`Azure.Search.Documents`), Java, JavaScript.

**API-versjoner:** `2025-09-01` (stable), `2025-11-01-preview` (maxTextRecallSize, filterOverride, etc.)