# Query Understanding and Expansion

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

---

## Introduksjon

Query understanding er den kritiske fasen i en RAG-løsning som transformerer brukerens spørsmål til optimaliserte søkespørringer før retrieval-steget. Mens direkte bruk av brukerens originale spørsmål kan fungere for enkle queries, gir query understanding betydelig forbedring av retrieval-kvalitet gjennom teknikker som query expansion, intent classification, query rewriting og sub-query decomposition.

Målet med query understanding er tredelt: (1) **forstå brukerens intensjon** gjennom kontekstuell analyse, (2) **reformulere spørringen** til å treffe den terminologien som faktisk brukes i dokumentene, og (3) **utvide søkerommet** gjennom synonymer, relaterte termer og hypoteser. Dette steget er spesielt viktig i multi-turn conversations hvor kontekst fra tidligere meldinger må integreres, og i domener med spesialisert terminologi hvor brukerens ordvalg ikke matcher dokumentenes språk.

Microsoft-stakken tilbyr flere verktøy for å implementere query understanding: Azure OpenAI for LLM-basert reformulering, Azure AI Search med innebygd fuzzy search og synonym mapping, og Semantic Kernel for orchestration av multi-step query pipelines. Kostnaden varierer basert på tilnærming — regelbaserte transformasjoner er gratis, mens LLM-basert query expansion krever ekstra tokens per spørring (typisk 200-500 input tokens + 100-300 output tokens per reformulering).

## Kjernekomponenter

Query understanding består av flere teknikker som kan kombineres i en pipeline:

### 1. Intent Classification

Klassifisering av brukerens intensjon i forhåndsdefinerte kategorier for å velge riktig retrieval-strategi.

| Kategori | Eksempel | Handling |
|----------|----------|----------|
| **Factual lookup** | "Hva er hovedstaden i Frankrike?" | Single-shot keyword search |
| **Complex analysis** | "Sammenlign økonomiske effekter av X og Y" | Query decomposition + multi-source retrieval |
| **Troubleshooting** | "Feilen ORA-12154 i produksjon" | Entity extraction → filter på feilkode |
| **Conversational followup** | "Hva med kostnaden?" | Context integration fra chat history |

**Implementering:** Bruk Azure OpenAI med strukturert output (JSON mode) for å klassifisere intent. Alternativt: lightweight classification model (fine-tuned BERT) for lavere latency.

### 2. Query Expansion

Utviding av spørringen med synonymer, relaterte termer og alternative formuleringer for bredere coverage.

**Teknikker:**

- **Synonym mapping:** Azure AI Search støtter synonym maps — definer f.eks. `"AI, kunstig intelligens, maskinlæring"` for automatisk expansion ved indexing-tid
- **LLM-basert expansion:** Be GPT om "generer 3-5 alternative formuleringer av dette spørsmålet"
- **Domain-specific thesaurus:** Bruk bransjespesifikke ordbøker (f.eks. medisinsk terminologi)

**Trade-off:** Økt recall (finner flere relevante dokumenter), men potensielt lavere precision (mer støy). Kombiner med reranking.

### 3. Query Rewriting

Reformulering av spørringen for å adressere problemer som vaghet, manglende keywords, unødvendige ord eller uklar semantikk.

**Anvendelser:**

| Problem | Originalt spørsmål | Rewritten query |
|---------|-------------------|-----------------|
| **Vagueness** | "Vis meg skjemaet" | "Vis medarbeider onboarding request form" (fra chat context) |
| **Stavefeil** | "Azur AI serch" | "Azure AI Search" |
| **Missing context** | "Hva med kostnaden?" | "Hva er kostnaden for Azure OpenAI GPT-4 i Norge?" |
| **Unnecessary words** | "Jeg lurer virkelig på om kanskje..." | "Hvilke lisenser trengs for Power Automate AI Builder?" |

**Implementering:** Multi-turn chat med `create_history_aware_retriever` i LangChain/Semantic Kernel — dette genererer standalone queries fra conversation history.

### 4. Sub-query Decomposition

Dekomponering av komplekse spørsmål i flere enkle sub-queries som kjøres uavhengig, deretter aggregering av resultater.

**Eksempel:**

```
Original: "Hvordan fungerer elbiler, og hvordan sammenlignes de med fossile biler?"

Sub-queries:
1. "Hvordan fungerer elektriske kjøretøy? Forklar motor og batteri."
2. "Hva er fordeler og ulemper med elbiler vs bensin/diesel?"
3. "Sammenlign total eierkostnad for elbil og fossil bil over 5 år"
```

**Decomposition-strategi:**

1. **Klassifiser** spørringen som "simple" eller "complex" (via LLM prompt)
2. **Dekomponér** komplekse spørsmål i ordered sub-queries (minst → mest avhengig)
3. **Kjør** hver sub-query parallelt mot vector store
4. **Aggregér** top-N resultater fra alle sub-queries som accumulated context
5. **Kjør** original query med accumulated context til LLM

**Når bruke:** Multi-part questions, sammenligninger, "hvordan X og hva er effekten av Y"-spørsmål.

### 5. Filter Extraction

Identifisering og ekstraksjon av strukturerte filtre fra naturlig språk for metadata-filtrering.

**Eksempler:**

| Spørring | Ekstraherte filtre |
|----------|-------------------|
| "Artikler om AI fra siste 6 måneder" | `date >= 2025-08-01` |
| "Power Automate-dokumentasjon på norsk" | `language = 'no', product = 'Power Automate'` |
| "Sikkerhetspolicyer for helsesektoren" | `sector = 'healthcare', category = 'security'` |

**Krav:** Metadata må være tilgjengelig i search index (konfigureres ved indexing). Kombiner med Azure AI Search `$filter` parameter.

### 6. HyDE (Hypothetical Document Embeddings)

Teknikk hvor LLM genererer hypotetiske svar på spørringen, deretter brukes embedding av disse svarene (ikke spørringen) til vector search.

**Hvorfor fungerer det:** Answer-to-answer similarity er ofte høyere enn question-to-answer similarity i embedding space.

**Implementering:**

```python
# 1. Generer hypotetisk svar
hypothetical_answer = llm.generate(f"Answer this: {user_query}")

# 2. Embed svaret (ikke spørringen)
answer_embedding = embedding_model.embed(hypothetical_answer)

# 3. Søk mot vector store
results = vector_store.similarity_search_by_vector(answer_embedding, k=5)
```

**Trade-off:** Ekstra LLM-kall (kostnad + latency), men potensielt bedre retrieval for ambiguous queries.

## Arkitekturmønstre

### Mønster 1: Single-LLM Query Rewriting

**Beskrivelse:** Én LLM-prompt tar originalspørring + chat history → genererer optimalisert søkequery.

**Fordeler:**

- Enkel å implementere
- Lavere latency (ett LLM-kall)
- Kostnadseffektiv

**Ulemper:**

- Kan feile ved komplekse multi-step logic
- Mindre kontroll over individuelle steg

**Når bruke:** Simple chatbots, enkle FAQs, begrenset domene.

### Mønster 2: Multi-step Pipeline (Intent → Extract → Rewrite)

**Beskrivelse:** Tre sekvensielle LLM-kall: (1) klassifiser intent, (2) ekstraher entities/filters, (3) rewrite basert på (1) og (2).

**Fordeler:**

- Finere kontroll over hvert steg
- Bedre debugging (kan inspisere output fra hvert steg)
- Høyere kvalitet for komplekse scenarios

**Ulemper:**

- Høyere latency (3x LLM-kall)
- Høyere kostnad
- Mer kompleks kode

**Når bruke:** Support bots, komplekse B2B applications, multi-intent queries.

### Mønster 3: Hybrid (Rules + LLM)

**Beskrivelse:** Regelbaserte transformasjoner for common cases, LLM for edge cases.

```
IF query matches regex "Hva er <term>?"
  THEN: Simple keyword search on <term>
ELSE IF query contains "sammenlign X og Y"
  THEN: Decompose into [query about X, query about Y]
ELSE:
  THEN: LLM-based rewriting
```

**Fordeler:**

- Optimalt cost/performance ratio
- Raskere for common patterns (ingen LLM-kall)
- Deterministisk oppførsel for kjente cases

**Ulemper:**

- Krever vedlikehold av rule set
- Fallback til LLM kan gi inkonsistens

**Når bruke:** High-volume production systems, kostnadsoptimalisering, deterministic requirements.

## Beslutningsveiledning

### Beslutningstabell: Hvilken teknikk når?

| Scenario | Anbefalt teknikk | Hvorfor |
|----------|-----------------|---------|
| Multi-turn chat | Query rewriting med chat history | Kontekstualisering av "Hva med X?" |
| Stavefeil og typos | Fuzzy search (Azure AI Search innebygd) | Ingen LLM-kostnad, rask |
| Vage spørsmål | Query expansion + reranking | Bredere coverage → rerank for precision |
| Komplekse sammenligninger | Sub-query decomposition | Parallell retrieval fra multiple sources |
| Spesialisert terminologi | Domain-specific synonym maps | Fast, deterministisk |
| Ambiguous queries | HyDE | Bedre embedding similarity |
| Filter-baserte spørsmål | Filter extraction + metadata filtering | Direkte $filter på index |

### Vanlige feil

1. **Over-rewriting:** Endrer brukerens intensjon ved aggressiv reformulering
   - **Løsning:** Behold original query i parallel search, rerank combined results
2. **Expansion without reranking:** For bredt søk uten prioritering
   - **Løsning:** Alltid kombiner expansion med cross-encoder reranker
3. **Missing context in multi-turn:** Glemmer tidligere chat history
   - **Løsning:** Bruk `ConversationBufferMemory` (LangChain) eller Semantic Kernel chat history
4. **LLM hallucination i query rewriting:** Legger til fakta som ikke er i original query
   - **Løsning:** Instruer LLM eksplisitt: "Do NOT add facts not present in the original query"
5. **Sub-query decomposition for simple queries:** Unødvendig overhead
   - **Løsning:** Klassifiser query først (simple vs complex) før decomposition

### Røde flagg

- 🚩 **Høy kostnad:** > 1000 tokens per query for rewriting (optimaliser prompts)
- 🚩 **Latency > 2s:** For mange sekvensielle LLM-kalls (vurder parallelisering eller caching)
- 🚩 **Retrieval precision < 60%:** Query understanding hjelper ikke hvis underliggende chunks er dårlige
- 🚩 **User frustration:** Brukere reformulerer spørsmål 3+ ganger → query understanding feiler

## Integrasjon med Microsoft-stakken

### Azure OpenAI

**Query rewriting med chat history:**

```python
from langchain.chains import create_history_aware_retriever
from langchain_openai import AzureChatOpenAI

llm = AzureChatOpenAI(
    azure_deployment="gpt-4",
    temperature=0
)

retriever_chain = create_history_aware_retriever(
    llm=llm,
    retriever=vector_store.as_retriever(),
    prompt=ChatPromptTemplate.from_messages([
        ("system", "Given chat history and latest user question, formulate a standalone question."),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}")
    ])
)
```

**Intent classification med structured output:**

```python
completion = client.chat.completions.create(
    model="gpt-4",
    messages=[
        {"role": "system", "content": "Classify user intent. Return JSON: {\"category\": \"factual|complex|troubleshooting\"}"},
        {"role": "user", "content": user_query}
    ],
    response_format={"type": "json_object"}
)
intent = json.loads(completion.choices[0].message.content)["category"]
```

### Azure AI Search

**Fuzzy search for typos (innebygd):**

```http
POST https://{search-service}.search.windows.net/indexes/{index-name}/docs/search?api-version=2026-04-01
{
  "search": "Azur~ AI~ Serch~",  // ~ = fuzzy, default edit distance 2 (max 2, Damerau-Levenshtein); ~1 for 1 edit, ~0 for exact
  "queryType": "full"
}
```

**Synonym mapping:**

```json
{
  "name": "ai-synonyms",
  "format": "solr",
  "synonyms": [
    "AI, kunstig intelligens, maskinlæring, machine learning",
    "RAG, retrieval augmented generation, retrieval-basert generering",
    "embedding, vektor, vector"
  ]
}
```

Koble til index via `synonymMaps` property på searchable fields.

### Semantic Kernel

**Multi-step query pipeline:**

```csharp
var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey)
    .Build();

// Step 1: Intent classification
var intentPlugin = kernel.ImportPluginFromPromptDirectory("IntentPlugin");
var intent = await kernel.InvokeAsync(intentPlugin["ClassifyIntent"],
    new() { ["query"] = userQuery });

// Step 2: Query rewriting based on intent
var rewritePlugin = kernel.ImportPluginFromPromptDirectory("RewritePlugin");
var rewrittenQuery = await kernel.InvokeAsync(rewritePlugin[$"Rewrite{intent}"],
    new() { ["query"] = userQuery, ["history"] = chatHistory });

// Step 3: Execute search with rewritten query
var results = await vectorStore.SearchAsync(rewrittenQuery.ToString());
```

### Copilot Studio

**Bruk "Create search query" node:** Automatisk query rewriting med conversation history — no-code løsning.

**Konfigurasjon:**

1. Legg til "Create search query" node i topic
2. Input: Current user message + conversation history
3. Output: Rewritten standalone query
4. Bruk output i "Search" eller "Custom connector" node

### Power Automate med AI Builder

**GPT-vurdering for query classification:** Bruk "Create text with GPT" action til å klassifisere intent før conditional branching.

## Offentlig sektor (Norge)

### Flerspråklige spørsmål

**Utfordring:** Brukere spør på norsk, nynorsk, samisk — dokumenter kan være på engelsk eller blandede språk.

**Løsninger:**

1. **Query translation:** Oversett spørring til engelsk før vector search (hvis dokumenter primært engelsk)
   ```python
   translated_query = azure_translator.translate(user_query, to="en")
   ```
2. **Multilingual embeddings:** Bruk `text-embedding-3-large` (støtter 100+ språk) — spørring og dokumenter i ulike språk matcher i samme vector space
3. **Language-specific indexes:** Separate indexes per språk med language-specific analyzers

**Tilgjengelighet:**

- **Klarspråk:** Query rewriting bør forenkle, ikke komplisere — sjekk WCAG 2.1 readability guidelines
- **Voice input:** Håndter ASR-feil (stavefeil) via fuzzy search

### GDPR og personvern

**Filter ut PII i queries:** Bruk Azure AI Language PII detection på user query FØR logging eller videre prosessering.

```python
from azure.ai.textanalytics import TextAnalyticsClient

pii_result = text_analytics_client.recognize_pii_entities([user_query])
redacted_query = pii_result[0].redacted_text  # Bruk denne videre
```

## Kostnad og lisensiering

### Prismodell

**Query understanding kostnader (per 1000 queries):**

| Tilnærming | Kostnad (NOK) | Latency | Kvalitet |
|------------|---------------|---------|----------|
| **Regelbasert (fuzzy, synonyms)** | 0 | ~50ms | Middels |
| **Single LLM rewrite (GPT-4o-mini)** | ~2 NOK | ~300ms | Høy |
| **Multi-step pipeline (3x GPT-4o-mini)** | ~6 NOK | ~800ms | Svært høy |
| **HyDE (GPT-4 Turbo)** | ~15 NOK | ~1.5s | Variabel |

**Antagelser:**
- GPT-4o-mini: 0.45 NOK / 1M input tokens, 1.80 NOK / 1M output tokens
- 250 input tokens + 150 output tokens per LLM-kall

### Optimaliseringstips

1. **Cache rewrites:** For common queries, cache rewritten version (Redis/Azure Cache)
2. **Batch processing:** Ved bulk-queries (f.eks. analytics), batch LLM-calls med `max_tokens` limit
3. **Fallback til billigere modeller:** GPT-4o-mini for simple rewrites, GPT-4 for complex decomposition
4. **Prompt optimization:** Reduser system prompt lengde — hver token repeteres per query

### Lisenser

| Komponent | Lisens/SKU |
|-----------|-----------|
| **Azure OpenAI** | Pay-as-you-go eller Provisioned Throughput Units (PTU) |
| **Azure AI Search** | Basic tier støtter synonym maps, Standard+ for semantic ranker |
| **Semantic Kernel** | Open-source (MIT) — ingen lisenskostnad |
| **Copilot Studio** | Per user/session (inkludert i M365 Copilot eller standalone) |

**ROI-vurdering:** Query understanding øker retrieval precision med 15-30% (typisk) → færre irrelevante svar → høyere user satisfaction → lavere support cost. Bryt-even oftest ved 5000+ queries/måned.

## For arkitekten (Cosmo)

### Spørsmål å stille kunden

1. **"Hva er typiske brukerqueries i løsningen deres? Kan jeg få 20-50 eksempler?"**
   - Analysér for common patterns (multi-turn, typos, vage spørsmål)
2. **"Finnes det bransjespesifikk terminologi eller forkortelser brukerne bruker?"**
   - Vurdér domain-specific synonym maps eller custom entity extraction
3. **"Hvor lang chat history er relevant? 3 messages? 10 messages?"**
   - Påvirker context window size for query rewriting
4. **"Hva er budsjettet for retrieval per måned? Antall forventede queries?"**
   - Bestemmer LLM-taktikk (GPT-4 vs GPT-4o-mini vs regelbasert)
5. **"Hva er akseptabel latency for et søk? 500ms? 2s? 5s?"**
   - Single-step vs multi-step pipeline trade-off
6. **"Støtter løsningen kun norsk, eller multiple språk?"**
   - Multilingual embeddings vs translation-basert approach
7. **"Hva er konsekvensen av feil retrieval? Kritisk (medical) eller informasjonell?"**
   - Høy confidence threshold + decomposition for kritiske domener
8. **"Har dere eksisterende analytics på søkeadferd? Click-through rates?"**
   - Evaluer current baseline før implementering av query understanding

### Fallgruver

- ❌ **Over-engineering:** Ikke bruk HyDE + decomposition + expansion for enkle FAQ-bots
- ❌ **Ignoring baseline:** Implementer alltid A/B test: query understanding ON vs OFF
- ❌ **LLM-avhengighet:** Regelbasert løser 60-70% av cases billigere
- ❌ **No reranking:** Query expansion uten reranker gir mer støy, ikke bedre svar
- ❌ **Context loss:** Å "reformulere" kan miste nyanser i original query
- ❌ **Token bloat:** System prompts på 1000+ tokens repeteres per query — optimaliser
- ❌ **Single evaluation metric:** Ikke kun precision — vurder recall, MRR, user satisfaction

### Anbefalinger per modenhetsnivå

**Nivå 1 — Starter (MVP):**

- Azure AI Search fuzzy search (innebygd, gratis)
- Synonym maps for top 10-20 vanlige termer
- Ingen LLM-basert query understanding (hold kostnad lav)

**Nivå 2 — Etablert (Production):**

- Single LLM rewrite med chat history (GPT-4o-mini)
- Filter extraction for common metadata (dato, kategori)
- A/B testing query understanding ON/OFF

**Nivå 3 — Optimert (Enterprise):**

- Multi-step pipeline: Intent → Extract → Rewrite
- Sub-query decomposition for komplekse spørsmål
- Cross-encoder reranking
- Continuous evaluation med precision@k, recall@k, MRR

**Nivå 4 — Avansert (Innovation):**

- HyDE for ambiguous queries
- Fine-tuned query classifier (BERT) for lavere latency
- Custom embedding model fine-tuned på domain data
- Real-time feedback loop (user clicks → retraining signal)

## Multi-Query RAG

### Konsept

Multi-Query RAG genererer *multiple spørringsvariasjoner* fra én brukerquery og kjører dem parallelt mot søkeindeksen. Resultatene dedupliseres og fusjoneres via **Reciprocal Rank Fusion (RRF)** for å gi bredere dekning enn en enkelt query.

### Forskjell fra Query Expansion

| Aspekt | Query Expansion | Multi-Query RAG |
|--------|----------------|-----------------|
| **Output** | Én beriket query | Multiple separate queries |
| **Søk** | Ett søk med utvidet query | Parallelle søk per variant |
| **Fusjon** | Ikke nødvendig | RRF / set union |
| **Dekning** | Dypere på ett konsept | Bredere over flere konsepter |
| **Kostnad** | 1 søk + 1 LLM-kall | N søk + 1 LLM-kall |

### Implementering i Azure

**Steg 1: Generer query-variasjoner med LLM**

```python
from openai import AzureOpenAI

client = AzureOpenAI(...)

def generate_query_variants(original_query: str, n: int = 3) -> list[str]:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{
            "role": "system",
            "content": f"""Generate {n} different search queries that capture
different aspects of the user's question. Return one query per line.
Original question: {original_query}"""
        }],
        temperature=0.7
    )
    variants = response.choices[0].message.content.strip().split("\n")
    return [original_query] + variants[:n]
```

**Steg 2: Parallelle søk + RRF-fusjon**

```python
import asyncio
from collections import defaultdict

async def multi_query_search(queries: list[str], k: int = 5):
    # Kjør parallelle søk
    tasks = [search_async(q, top=k*2) for q in queries]
    all_results = await asyncio.gather(*tasks)

    # Reciprocal Rank Fusion
    rrf_scores = defaultdict(float)
    rrf_constant = 60

    for results in all_results:
        for rank, doc in enumerate(results):
            rrf_scores[doc["id"]] += 1.0 / (rank + rrf_constant)

    # Sorter og returner top-k
    sorted_docs = sorted(rrf_scores.items(), key=lambda x: x[1], reverse=True)
    return sorted_docs[:k]
```

### RRF-algoritmen

Azure AI Search bruker allerede RRF internt for hybrid search (BM25 + vektor). Multi-Query RAG legger til et ekstra lag:

```
RRF_score(d) = Σ_i (1 / (rank_i(d) + k))

hvor:
  i = indeks over alle queries (original + varianter)
  rank_i(d) = dokumentets posisjon i query i
  k = konstant (typisk 60)
```

### Når bruke Multi-Query RAG

| Scenario | Bruk multi-query? | Begrunnelse |
|----------|-------------------|-------------|
| Brede, tematiske spørsmål | Ja | Dekker flere aspekter |
| Presise, fakta-baserte queries | Nei | Single query er tilstrekkelig |
| Tvetydig intent | Ja | Varianter fanger ulike tolkninger |
| Høyt volum (>10K queries/dag) | Vurder kostnad | N×søk-kostnad |
| Lav recall i eksisterende system | Ja | Øker sannsynlighet for relevante treff |

### Kostnad

Multi-Query RAG med 3 varianter = ~3x søkekostnad + 1 LLM-kall for generering.
- LLM-kall (gpt-4o-mini): ~0.01 NOK per query
- Ekstra søk: ~0.03 NOK per ekstra søk
- **Total ekstra kostnad:** ~0.10 NOK per query (for 3 varianter)

---

## Kilder og verifisering

**Microsoft Learn (Verified — search-query-fuzzy re-verifisert via MCP 2026-06-19):**

1. [Azure Databricks: Improve RAG chain quality — Query understanding](https://learn.microsoft.com/en-us/azure/databricks/generative-ai/tutorials/ai-cookbook/quality-rag-chain#query-understanding)
   **Konfidens:** Verified — Multi-step query understanding (intent, entity extraction, rewriting)

2. [Azure Architecture: RAG Information retrieval — Query translation](https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/rag/rag-information-retrieval#query-translation)
   **Konfidens:** Verified — Query augmentation, decomposition, rewriting, HyDE

3. [Azure AI Search: Fuzzy search to correct misspellings and typos](https://learn.microsoft.com/en-us/azure/search/search-query-fuzzy)
   **Konfidens:** Verified — Fuzzy query expansion med Damerau-Levenshtein distance

4. [Azure AI Search: Simple query syntax](https://learn.microsoft.com/en-us/azure/search/query-simple-syntax)
   **Konfidens:** Verified — Keyword search, phrase search, boolean operators

5. [Azure Arc Edge RAG: Search type parameters](https://learn.microsoft.com/en-us/azure/azure-arc/edge-rag/search-types#search-type-parameters)
   **Konfidens:** Verified — Query expansion, sub-query generation, hypothetical answer generation

6. [Copilot Studio: Create search query](https://learn.microsoft.com/en-us/microsoft-copilot-studio/authoring-create-search-query)
   **Konfidens:** Verified — No-code query rewriting med conversation history

**RAG Experiment Accelerator (GitHub — Microsoft):**

7. [microsoft/rag-experiment-accelerator](https://github.com/microsoft/rag-experiment-accelerator)
   **Konfidens:** Verified — Query classification, decomposition, rewriting prompts (Python)

**Seksjoner med baseline-kunnskap (modellkunnskap, ikke MCP-verifisert):**

- **Semantic Kernel C# eksempel:** Baseline — ikke funnet i MCP-søk, basert på SK pattern library
- **Token cost estimater:** Baseline — basert på Azure OpenAI pricing (januar 2026)
- **ROI-tall (15-30% precision improvement):** Baseline — industry benchmarks, ikke Microsoft-spesifikk data

**Totalt antall kilder:** 7 Microsoft Learn URLer (Verified) + 1 GitHub repo (Verified) = 8 kilder


### Simple Query Syntax for RAG (oppdatert 2026-06)

Azure AI Search simple query syntax er default parser for full-text søk i RAG:

**Boolske operatorer (tegn-basert):**
- `+` — AND (påkrevd term)
- `|` — OR (alternativ term)
- `-` — NOT (ekskluder term) — `searchMode=all` anbefales for presis NOT-atferd

**Prefix queries:** `lingui*` — matcher "linguistic", "linguini" etc.

**Phrase search:** `"eksakt frase"` — krever eksakt ordrekkefølge

**Begrensninger:** Ingen fuzzy search, ingen suffix/infix wildcard (bruk full Lucene syntax for det).

**Bruk i RAG query expansion:**
Simple syntax egner seg for keyword-delen av hybrid queries. For agentic RAG bruker LLM query planning til å generere fokuserte subqueries som kombinerer full-text + vector search parallelt.