Initial addition of ms-ai-architect plugin to the open-source marketplace. Private content excluded: orchestrator/ (Linear tooling), docs/utredning/ (client investigation), generated test reports and PDF export script. skill-gen tooling moved from orchestrator/ to scripts/skill-gen/. Security scan: WARNING (risk 20/100) — no secrets, no injection found. False positive fixed: added gitleaks:allow to Python variable reference in output-validation-grounding-verification.md line 109. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
15 KiB
Multi-Modal RAG Architecture Patterns
Last updated: 2026-02 Status: GA / Preview (multimodal search) Category: Multi-Modal AI
Introduksjon
Multi-Modal RAG (Retrieval-Augmented Generation) utvidar tradisjonell tekstbasert RAG til å inkludere bilete, diagram, tabellar og video som datakjelder. I staden for å berre søke i tekstdokument, kan ein multi-modal RAG-pipeline hente relevante bilete, analysere diagram og bruke visuell informasjon saman med tekst for å generere presise og grunnlagda svar.
Azure AI Search introduserte multimodal search som preview i mai 2025, noko som gir native støtte for å indeksere, forstå og hente dokument som inneheld både tekst og bilete. Dette eliminerer behovet for separate system for tekst- og bildeprosessering og reduserer kompleksiteten i RAG-arkitekturen vesentleg.
For norsk offentleg sektor er multi-modal RAG særleg verdifull for scenario som analyse av offentlege dokument med innebygde diagram og tabellar, byggesøknadar med teikningar, vegdokumentasjon med kartutsnitt, og forskingsrapportar med visualiseringar. Informasjon som tidlegare berre var tilgjengeleg som visuelt innhald i PDF-filer kan no søkast i og brukast som grunnlag for AI-assisterte avgjerder.
Multi-Modal Embedding-modellar
Oversikt over embedding-tilnærmingar
Azure AI Search tilbyr to komplementære tilnærmingar for multimodal embedding:
| Tilnærming | Korleis det fungerer | Beste for | Krav |
|---|---|---|---|
| Image Verbalization + Text Embeddings | LLM beskriv bilete i naturleg språk, deretter tekst-embedding | Diagram, flowcharts, forklaringsrikt innhald | LLM + embedding-modell |
| Direct Multimodal Embeddings | Enkelt embedding-modell for tekst og bilete i same vektorrom | Visuell likheit, produktbilete, foto | Multimodal embedding-modell |
| Kombinert | Begge tilnærmingane saman | Enterprise-løysingar med variert innhald | LLM + multimodal embedding |
Image Verbalization Pipeline
GenAI Prompt-ferdigheita i Azure AI Search brukar ein LLM under indeksering for å lage natururlege tekstbeskrivelsar av kvart ekstrahert bilete:
Ekstrahert bilete → GenAI Prompt Skill → "Five-step HR workflow
starting with manager
approval"
↓
Text Embedding Skill
↓
Vektorrepresentasjon
Fordelar:
- Tolkbar — beskriving kan siterast direkte
- Semantisk djupne — forstår relasjonar i diagram
- Fungerer med standard tekst-embedding-modellar
Ulemper:
- LLM-kall per bilete aukar indekseringstid og kostnad
- Kvaliteten avheng av LLM sin evne til å tolke biletet
Direct Multimodal Embeddings
| Modell | Leverandør | Dimensjonar | Brukstilfelle |
|---|---|---|---|
| CLIP | OpenAI | 512 / 768 | Generell tekst-bilete matching |
| text-embedding-3-large | Azure OpenAI | 3 072 | Tekst embeddings (etter verbalization) |
| Azure Vision multimodal | Azure AI Vision | 1 024 | Direkte bilete + tekst embeddings |
| Foundry Models (AML) | Microsoft Foundry | Varierer | Tilpassa multimodale modellar |
# Azure AI Search: Multimodal embedding med Azure Vision
skill_definition = {
"@odata.type": "#Microsoft.Skills.Vision.VectorizeSkill",
"name": "multimodal-embedding",
"description": "Embed bilete og tekst i same vektorrom",
"context": "/document/pages/*",
"modelVersion": "2023-04-15",
"inputs": [
{"name": "image", "source": "/document/pages/*/normalized_images/*"},
{"name": "text", "source": "/document/pages/*/content"}
],
"outputs": [
{"name": "vector", "targetName": "contentVector"}
]
}
Kombinert tilnærming for enterprise
Den mest robuste arkitekturen kombinerer begge metodane:
Dokument
├── Tekst → Text Split Skill → Text Embedding → tekst_vektor
├── Diagram/Charts → GenAI Prompt (verbalize) → Text Embedding → diagram_vektor
└── Foto/Screenshots → Direct Multimodal Embedding → bilete_vektor
Chunking-strategiar for bilete og video
Dokumentekstraksjon
Azure AI Search tilbyr tre innebygde ferdigheiter for innhaldsekstraksjon:
| Ferdigheit | Tekstlokasjon | Biletelokasjon | Tabellar | Cross-page | Format |
|---|---|---|---|---|---|
| Document Extraction | Nei | Ja (PDF) | Nei | Nei | |
| Document Layout | Ja (side, polygon) | Ja (side, polygon) | Nei | Nei | PDF, DOCX, XLSX, PPTX |
| Content Understanding | Ja (side, polygon) | Ja (side, polygon) | Ja (cross-page) | Ja | PDF, DOCX, XLSX, PPTX |
Tekst-chunking
Text Split-ferdigheita delar tekst i handterbare delar for embedding:
{
"@odata.type": "#Microsoft.Skills.Text.SplitSkill",
"name": "text-splitter",
"textSplitMode": "pages",
"maximumPageLength": 2000,
"pageOverlapLength": 500,
"maximumPagesToTake": 0,
"inputs": [
{"name": "text", "source": "/document/content"}
],
"outputs": [
{"name": "textItems", "targetName": "chunks"}
]
}
Bilete-chunking-strategiar
| Strategi | Implementering | Brukstilfelle |
|---|---|---|
| Side-basert | Eitt bilete per dokumentside | PDF-analyse med diagram |
| Objekt-basert | Utsnitt rundt detekterte objekt | Tekniske teikningar |
| Grid-basert | Fast rutenett over stort bilete | Kart, satellittbilete |
| Semantisk | Basert på visuell innhaldsanalyse | Blanda dokument |
Video-chunking
For videoinnhald kombiner Azure Video Indexer med embedding:
Video → Video Indexer
├── Keyframes → Bilete-embedding
├── Scener → Scene-beskriving → Tekst-embedding
├── Transkripsjon → Tekst-chunking → Tekst-embedding
└── OCR-tekst → Tekst-embedding
| Chunking-nivå | Granularitet | Token-kostnad | Brukstilfelle |
|---|---|---|---|
| Per keyframe | Finkornet | Høg | Detaljert visuell søk |
| Per scene | Medium | Medium | Narrativ forståing |
| Per segment (5 min) | Grovkornet | Låg | Overordna innhaldssøk |
Vector Store Design for Mixed Media
Azure AI Search indeksdesign
{
"name": "multimodal-index",
"fields": [
{"name": "id", "type": "Edm.String", "key": true},
{"name": "parent_id", "type": "Edm.String", "filterable": true},
{"name": "content_type", "type": "Edm.String", "filterable": true, "facetable": true},
{"name": "text_content", "type": "Edm.String", "searchable": true},
{"name": "image_description", "type": "Edm.String", "searchable": true},
{"name": "page_number", "type": "Edm.Int32", "filterable": true, "sortable": true},
{"name": "source_file", "type": "Edm.String", "filterable": true},
{
"name": "text_vector",
"type": "Collection(Edm.Single)",
"dimensions": 3072,
"vectorSearchProfile": "text-profile",
"searchable": true
},
{
"name": "image_vector",
"type": "Collection(Edm.Single)",
"dimensions": 1024,
"vectorSearchProfile": "image-profile",
"searchable": true
},
{"name": "image_url", "type": "Edm.String"},
{"name": "bounding_region", "type": "Edm.String"}
],
"vectorSearch": {
"algorithms": [
{
"name": "hnsw-config",
"kind": "hnsw",
"hnswParameters": {
"m": 4,
"efConstruction": 400,
"efSearch": 500,
"metric": "cosine"
}
}
],
"profiles": [
{"name": "text-profile", "algorithm": "hnsw-config", "vectorizer": "text-vectorizer"},
{"name": "image-profile", "algorithm": "hnsw-config", "vectorizer": "image-vectorizer"}
],
"vectorizers": [
{
"name": "text-vectorizer",
"kind": "azureOpenAI",
"azureOpenAIParameters": {
"resourceUri": "https://<resource>.openai.azure.com",
"deploymentId": "text-embedding-3-large",
"modelName": "text-embedding-3-large"
}
},
{
"name": "image-vectorizer",
"kind": "aml",
"amlParameters": {
"uri": "https://<endpoint>.inference.ml.azure.com/score",
"modelName": "multimodal-embedding"
}
}
]
}
}
Knowledge Store for biletebevaring
{
"knowledgeStore": {
"storageConnectionString": "<connection-string>",
"projections": [
{
"objects": [
{
"storageContainer": "document-insights",
"generatedKeyName": "insight_id",
"source": "/document/insights"
}
],
"files": [
{
"storageContainer": "extracted-images",
"generatedKeyName": "image_id",
"source": "/document/normalized_images/*"
}
]
}
]
}
}
Dimensjonalitetsreduksjon
For å optimalisere lagring og ytelse:
| Teknikk | Når bruke | Kommentar |
|---|---|---|
| Matryoshka embeddings | Generelt | text-embedding-3-large støttar reduserte dimensjonar |
| PCA | Post-prosessering | Reduser dimensjonar etter embedding |
| Scalar quantization | Azure AI Search native | 4x reduksjon i lagring |
| Binary quantization | Azure AI Search native | 28x reduksjon, noko kvalitetstap |
Retrieval og Ranking Patterns
Hybrid søk
Azure AI Search sin hybride søk kombinerer fulltekst, vektorsøk og semantisk ranking:
from azure.search.documents import SearchClient
from azure.search.documents.models import VectorizableTextQuery
search_client = SearchClient(
endpoint="https://<search-service>.search.windows.net",
index_name="multimodal-index",
credential=credential
)
# Hybrid søk: tekst + vektor + semantisk ranking
results = search_client.search(
search_text="trafikksikkerheit i tunneler",
vector_queries=[
VectorizableTextQuery(
text="trafikksikkerheit i tunneler",
k_nearest_neighbors=10,
fields="text_vector,image_vector"
)
],
query_type="semantic",
semantic_configuration_name="my-semantic-config",
select=["text_content", "image_description", "image_url", "page_number", "source_file"],
filter="content_type eq 'diagram' or content_type eq 'text'",
top=10
)
for result in results:
print(f"Score: {result['@search.score']}")
print(f"Type: {result['content_type']}")
print(f"Content: {result['text_content'][:200]}")
if result.get('image_url'):
print(f"Image: {result['image_url']}")
Multimodal Ranking Pipeline
Brukar-query
├── Fulltekstsøk → BM25-score
├── Vektorsøk (tekst) → Cosine similarity
├── Vektorsøk (bilete) → Cosine similarity
└── Semantisk ranking → Cross-encoder re-ranking
↓
Reciprocal Rank Fusion (RRF)
↓
Top-K resultat (tekst + bilete)
↓
LLM (GPT-4o) med multimodalt kontekst
↓
Grunnlagd svar med kjeldereferansar
Multimodal RAG med GPT-4o
def multimodal_rag_query(query: str, search_client, openai_client):
"""Utfør multimodal RAG-query med tekst og bilete."""
# Steg 1: Hent relevante chunks (tekst + bilete)
search_results = search_client.search(
search_text=query,
vector_queries=[
VectorizableTextQuery(text=query, k_nearest_neighbors=5, fields="text_vector")
],
query_type="semantic",
top=10
)
# Steg 2: Bygg multimodalt kontekst
messages = [
{"role": "system", "content": "Du er ein AI-assistent for norsk offentleg sektor. Svar basert på konteksten."}
]
user_content = [{"type": "text", "text": f"Spørsmål: {query}\n\nKontekst:"}]
for result in search_results:
# Legg til tekst
user_content.append({
"type": "text",
"text": f"\n[Kjelde: {result['source_file']}, side {result['page_number']}]\n{result['text_content']}"
})
# Legg til bilete om tilgjengeleg
if result.get('image_url'):
user_content.append({
"type": "image_url",
"image_url": {"url": result['image_url'], "detail": "high"}
})
messages.append({"role": "user", "content": user_content})
# Steg 3: Generer svar med GPT-4o
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=messages,
max_tokens=2048
)
return response.choices[0].message.content
Filtrering etter innhaldstype
| Filter | Brukstilfelle |
|---|---|
content_type eq 'text' |
Berre tekstbaserte resultat |
content_type eq 'diagram' |
Berre diagram og charts |
content_type eq 'photo' |
Berre foto/screenshots |
content_type eq 'table' |
Berre tabellar |
page_number ge 5 and page_number le 10 |
Spesifikke sider |
End-to-End Pipeline med Azure AI Search
Fullstendig multimodal indexer-skillset
{
"name": "multimodal-skillset",
"skills": [
{
"@odata.type": "#Microsoft.Skills.Util.DocumentExtractionSkill",
"name": "document-extraction",
"parsingMode": "default",
"dataToExtract": "contentAndMetadata",
"configuration": {
"imageAction": "generateNormalizedImages",
"normalizedImageMaxWidth": 2000,
"normalizedImageMaxHeight": 2000
}
},
{
"@odata.type": "#Microsoft.Skills.Text.SplitSkill",
"name": "text-chunking",
"textSplitMode": "pages",
"maximumPageLength": 2000,
"pageOverlapLength": 500
},
{
"@odata.type": "#Microsoft.Skills.Custom.GenAIPromptSkill",
"name": "image-verbalization",
"description": "Beskriv bilete med LLM",
"context": "/document/normalized_images/*",
"inputs": [
{"name": "image", "source": "/document/normalized_images/*"}
],
"outputs": [
{"name": "description", "targetName": "imageDescription"}
],
"configuration": {
"prompt": "Beskriv dette biletet kortfatta. Fokuser på nøkkelinformasjon som er relevant for dokumentet."
}
},
{
"@odata.type": "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill",
"name": "text-embedding",
"modelName": "text-embedding-3-large",
"context": "/document/pages/*",
"inputs": [
{"name": "text", "source": "/document/pages/*/content"}
],
"outputs": [
{"name": "embedding", "targetName": "textVector"}
]
}
]
}
For Cosmo
- Image verbalization + text embeddings gir best resultat for dokumenttunge RAG-scenario i offentleg sektor, fordi diagram og flowcharts i PDF-ar inneheld kritisk informasjon som rein tekst-søk misser.
- Azure AI Search sin multimodal pipeline (preview mai 2025) forenklar arkitekturen vesentleg: Document Extraction/Layout → GenAI Prompt → Embedding → Index i ein samla skillset.
- Kombiner begge embedding-tilnærmingane for robuste enterprise-løysingar: verbalisering for diagram/charts, direkte embeddings for foto og screenshots.
- Design indeksen med
content_type-felt for filtrert søk. Ikkje bland tekst- og biletevektorar i same felt — bruk separate vektorprofilar med tilpassa dimensjonar. - Bruk hybrid søk (fulltekst + vektor + semantisk ranking) for best recall og presisjon i multimodale scenario. RRF (Reciprocal Rank Fusion) er standard i Azure AI Search.