Steg 9 (R4): unified migrate-corpus.mjs --write over engineering/governance/ infrastructure/security. 327 filer mutert, verified=null, prosa byte-identisk (fra første ## seksjon), advisor urørt (0 endringer). To applier-fixes oppdaget under kjøring (TDD, RED→GREEN): - insertHeaderFields: anker faller nå tilbake når en meta-linje selv passerer 500B (2 filer pakket et avsnitt i **Status:** → Type/Source landet utenfor scan-vinduet, applierens post-write-assertion fanget + restaurerte). - normalizeStaleVerified: fjerner nå ALLE stale non-date **Verified:** i 500B-vinduet, inkl. stray body-dup rett under --- (9 mlops-genaiops-filer var ellers falskt "verified"/fresh, droppet fra worklist). Operatør-godkjent utvidelse av carve-out; kun stray metadata-linjer, aldri prosa. test-transform-criterion: precondition oppdatert til post-migrasjons-sannhet (fila bærer nå Source). Suite 728/728 grønn.
484 lines
17 KiB
Markdown
484 lines
17 KiB
Markdown
# Multi-Modal Prompt Engineering Techniques
|
|
|
|
**Last updated:** 2026-02
|
|
**Status:** GA
|
|
**Category:** Multi-Modal AI
|
|
**Type:** reference
|
|
|
|
---
|
|
|
|
## Innhold
|
|
|
|
- [Introduksjon](#introduksjon)
|
|
- [Kjernekomponentar](#kjernekomponentar)
|
|
- [Visual Grounding og Spatial Reasoning i Prompts](#visual-grounding-og-spatial-reasoning-i-prompts)
|
|
- [Few-shot Examples with Images](#few-shot-examples-with-images)
|
|
- [Chain-of-Thought Reasoning with Visuals](#chain-of-thought-reasoning-with-visuals)
|
|
- [System Messages for Multi-Modal Tasks](#system-messages-for-multi-modal-tasks)
|
|
- [Image Tokenization og Kostnadsoptimalisering](#image-tokenization-og-kostnadsoptimalisering)
|
|
- [Norsk offentleg sektor](#norsk-offentleg-sektor)
|
|
- [Beslutningsrammeverk](#beslutningsrammeverk)
|
|
- [For Cosmo](#for-cosmo)
|
|
|
|
## Introduksjon
|
|
|
|
Multimodal prompt engineering er kunsten å skrive effektive instruksjonar som kombinerer tekst og bilete for å utnytte kapabilitetane til vision-enabled modellar som GPT-4o, GPT-4o mini og GPT-4 Turbo with Vision. Desse modellane aksepterer både tekst og bilete som input, og kan utføre oppgåver som bildeanalyse, visuelt resonnement, dokumentforståing og diagramtolking.
|
|
|
|
Microsoft sin offisielle rettleiing for image prompt engineering identifiserer seks grunnprinsipp: kontekstuell spesifisitet, oppgåveorienterte prompts, handtering av nekting (refusals), eksempelbruk, oppdeling av komplekse oppgåver, og definering av output-format. Desse prinsippa er like relevante for norsk offentleg sektor, der multimodale modellar kan nyttast til alt frå byggesaksanalyse til kvalitetssikring av veginfrastruktur.
|
|
|
|
Microsoft Foundry Playground tilbyr eit interaktivt miljø for å eksperimentere med multimodale prompts, og GPT-4o sin image tokenization-mekanisme påverkar både kostnader og ytelse. Forståing av korleis bilete vert konvertert til tokens er kritisk for kostnadsoptimalisering i produksjonssystem.
|
|
|
|
---
|
|
|
|
## Kjernekomponentar
|
|
|
|
| Komponent | Formål | Teknologi |
|
|
|-----------|--------|-----------|
|
|
| GPT-4o / GPT-4o mini | Multimodal chat med tekst + bilete | Azure OpenAI Service |
|
|
| Image Tokenization | Konvertering av bilete til tokens | Intern GPT-4o-mekanisme |
|
|
| System Messages | Kontekstsetting for visuelle oppgåver | Chat Completions API |
|
|
| Structured Output | JSON/schema-basert output frå visuell analyse | Response format |
|
|
| Vision Fine-tuning | Tilpassing av visuell forståing | GPT-4o (2024-08-06) |
|
|
| Content Filtering | Sikkerheitsfilter for bilete-input/output | Azure AI Content Safety |
|
|
|
|
---
|
|
|
|
## Visual Grounding og Spatial Reasoning i Prompts
|
|
|
|
### Grunnleggjande image prompt-prinsipp
|
|
|
|
1. **Kontekstuell spesifisitet** — Gi modellen kontekst om kva biletet representerer
|
|
2. **Oppgåveorientering** — Fokuser på ei spesifikk oppgåve
|
|
3. **Handle refusals** — Reformuler ved nekting
|
|
4. **Bruk eksempel** — Vis ønska output-type
|
|
5. **Del opp komplekse oppgåver** — Steg-for-steg
|
|
6. **Definer output-format** — JSON, Markdown, tabell osv.
|
|
|
|
### Spatial reasoning-prompts
|
|
|
|
```python
|
|
from openai import AzureOpenAI
|
|
|
|
client = AzureOpenAI(
|
|
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
|
|
api_key=os.environ["AZURE_OPENAI_API_KEY"],
|
|
api_version="2024-10-21"
|
|
)
|
|
|
|
# Spatial reasoning: Posisjon og relasjonar i biletet
|
|
response = client.chat.completions.create(
|
|
model="gpt-4o",
|
|
messages=[
|
|
{
|
|
"role": "system",
|
|
"content": """Du er ein vegingeniør-assistent. Analyser
|
|
biletet av vegkrysset og beskriv:
|
|
1. Kva som er i NORD (øvst i biletet)
|
|
2. Kva som er i SØR (nedst)
|
|
3. Kva som er i ØST (høgre)
|
|
4. Kva som er i VEST (venstre)
|
|
5. Eventuelle trafikkproblem du observerer
|
|
Returner som strukturert JSON."""
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "Analyser dette vegkrysset for trafikkplanlegging:"
|
|
},
|
|
{
|
|
"type": "image_url",
|
|
"image_url": {
|
|
"url": "https://example.com/intersection.jpg",
|
|
"detail": "high"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
],
|
|
max_tokens=1000,
|
|
response_format={"type": "json_object"}
|
|
)
|
|
```
|
|
|
|
### Visual grounding med bounding box-referansar
|
|
|
|
```python
|
|
# Be modellen referere til spesifikke regionar
|
|
response = client.chat.completions.create(
|
|
model="gpt-4o",
|
|
messages=[
|
|
{
|
|
"role": "system",
|
|
"content": """Når du analyserer bilete, referer til
|
|
posisjonar med relative koordinatar:
|
|
- Øvste venstre = (0,0)
|
|
- Nedste høgre = (1,1)
|
|
Bruk format: [objekt] ved ca. (x, y)"""
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{"type": "text", "text": "Identifiser alle trafikkskilt "
|
|
"og deira posisjon i biletet."},
|
|
{"type": "image_url", "image_url": {"url": image_url}}
|
|
]
|
|
}
|
|
]
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## Few-shot Examples with Images
|
|
|
|
### Mønster: Klassifisering med bilete-eksempel
|
|
|
|
```python
|
|
def classify_with_examples(target_image_url: str,
|
|
examples: list[dict]) -> str:
|
|
"""
|
|
Klassifiser med few-shot bilete-eksempel.
|
|
|
|
examples = [
|
|
{"url": "...", "label": "HULLROT", "forklaring": "..."},
|
|
{"url": "...", "label": "SPREKK", "forklaring": "..."},
|
|
]
|
|
"""
|
|
messages = [
|
|
{
|
|
"role": "system",
|
|
"content": "Du er ein vegskade-klassifiseringsekspert. "
|
|
"Bruk dei gitte eksempla som referanse."
|
|
}
|
|
]
|
|
|
|
# Legg til eksempel-bilete som user/assistant-par
|
|
for ex in examples:
|
|
messages.append({
|
|
"role": "user",
|
|
"content": [
|
|
{"type": "text", "text": "Klassifiser denne vegskaden:"},
|
|
{"type": "image_url",
|
|
"image_url": {"url": ex["url"], "detail": "low"}}
|
|
]
|
|
})
|
|
messages.append({
|
|
"role": "assistant",
|
|
"content": f"Klassifisering: {ex['label']}\n"
|
|
f"Forklaring: {ex['forklaring']}"
|
|
})
|
|
|
|
# Legg til målbiletet
|
|
messages.append({
|
|
"role": "user",
|
|
"content": [
|
|
{"type": "text", "text": "Klassifiser denne vegskaden:"},
|
|
{"type": "image_url",
|
|
"image_url": {"url": target_image_url, "detail": "high"}}
|
|
]
|
|
})
|
|
|
|
response = client.chat.completions.create(
|
|
model="gpt-4o",
|
|
messages=messages,
|
|
max_tokens=500
|
|
)
|
|
|
|
return response.choices[0].message.content
|
|
```
|
|
|
|
### Token-budsjett for few-shot med bilete
|
|
|
|
| Detalj-nivå | Tokens per bilete | Kostnadsimplikasjon |
|
|
|-------------|-------------------|---------------------|
|
|
| `low` | 85 tokens (GPT-4o) | Optimal for eksempel-bilete |
|
|
| `high` (1024x1024) | ~765 tokens (GPT-4o) | Bruk for mål-biletet |
|
|
| `high` (2048x2048) | ~2805 tokens | Reduser til 1024 om mogleg |
|
|
| `auto` | Varierer | Standard — modellen vel |
|
|
|
|
**Best practice for few-shot:**
|
|
- Bruk `"detail": "low"` for eksempel-bilete (85 tokens kvar)
|
|
- Bruk `"detail": "high"` for mål-biletet (full analyse)
|
|
- Avgrens til 3-5 eksempel for å spare tokens
|
|
- Plasser biletet **før** tekst for single-image prompts
|
|
|
|
---
|
|
|
|
## Chain-of-Thought Reasoning with Visuals
|
|
|
|
### Visuell CoT-teknikk
|
|
|
|
```python
|
|
# Steg-for-steg visuelt resonnement
|
|
response = client.chat.completions.create(
|
|
model="gpt-4o",
|
|
messages=[
|
|
{
|
|
"role": "system",
|
|
"content": """Du er ein byggesak-ekspert for norsk
|
|
offentleg sektor. Analyser biletet steg for steg:
|
|
|
|
STEG 1: Beskriv kva du ser i biletet i detalj
|
|
STEG 2: Identifiser relevante byggtekniske element
|
|
STEG 3: Vurder samsvar med gjeldande forskrifter
|
|
STEG 4: Gi din konklusjon med grunngjeving
|
|
|
|
Vis resonneringskjeda tydeleg."""
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "Vurder om dette byggeprosjektet "
|
|
"ser ut til å følgje TEK17 krav "
|
|
"til universell utforming:"
|
|
},
|
|
{
|
|
"type": "image_url",
|
|
"image_url": {
|
|
"url": "https://example.com/building-entrance.jpg",
|
|
"detail": "high"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
],
|
|
max_tokens=2000
|
|
)
|
|
```
|
|
|
|
### Multi-image CoT-samanlikning
|
|
|
|
```python
|
|
# Samanlikn to bilete med resonnement
|
|
messages = [
|
|
{
|
|
"role": "system",
|
|
"content": """Samanlikn dei to bileta steg for steg:
|
|
1. Beskriv bilete A
|
|
2. Beskriv bilete B
|
|
3. Identifiser forskjellar
|
|
4. Gi vurdering basert på forskjellane"""
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{"type": "text",
|
|
"text": "Bilete A (før tiltak):"},
|
|
{"type": "image_url",
|
|
"image_url": {"url": before_url, "detail": "high"}},
|
|
{"type": "text",
|
|
"text": "Bilete B (etter tiltak):"},
|
|
{"type": "image_url",
|
|
"image_url": {"url": after_url, "detail": "high"}},
|
|
{"type": "text",
|
|
"text": "Vurder om vedlikehaldstiltaket er utført korrekt."}
|
|
]
|
|
}
|
|
]
|
|
```
|
|
|
|
### "Describe first"-teknikken
|
|
|
|
Når modellen nektar å utføre ei oppgåve, be den først beskrive biletet:
|
|
|
|
```python
|
|
# Steg 1: Be modellen beskrive biletet detaljert
|
|
describe_response = client.chat.completions.create(
|
|
model="gpt-4o",
|
|
messages=[{
|
|
"role": "user",
|
|
"content": [
|
|
{"type": "text",
|
|
"text": "Beskriv dette biletet i detalj, inkludert "
|
|
"alle synlege element, tekst, tal og merking."},
|
|
{"type": "image_url",
|
|
"image_url": {"url": image_url, "detail": "high"}}
|
|
]
|
|
}]
|
|
)
|
|
|
|
description = describe_response.choices[0].message.content
|
|
|
|
# Steg 2: Utfør analyse basert på skildringa
|
|
analysis = client.chat.completions.create(
|
|
model="gpt-4o",
|
|
messages=[
|
|
{"role": "system",
|
|
"content": "Analyser følgjande bildeskilding for "
|
|
"reguleringsplan-samsvar."},
|
|
{"role": "user",
|
|
"content": f"Bildeskilding:\n{description}\n\n"
|
|
"Vurder om det skildra bygget er i samsvar "
|
|
"med reguleringsplanen."}
|
|
]
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## System Messages for Multi-Modal Tasks
|
|
|
|
### Template-struktur for visuelle system messages
|
|
|
|
```python
|
|
VISUAL_SYSTEM_TEMPLATE = """
|
|
ROLLE: {rolle}
|
|
KONTEKST: {kontekst}
|
|
OPPGÅVE: {oppgåve}
|
|
|
|
ANALYSEINSTRUKSJONAR:
|
|
{steg_for_steg_instruksjonar}
|
|
|
|
OUTPUT-FORMAT:
|
|
{format_spesifikasjon}
|
|
|
|
AVGRENSINGAR:
|
|
- {avgrensing_1}
|
|
- {avgrensing_2}
|
|
- Om du er usikker, sei eksplisitt kva du er usikker på
|
|
- Ikkje gjett — be om tilleggsinformasjon om nødvendig
|
|
"""
|
|
|
|
# Eksempel: Vegskade-vurdering
|
|
system_message = VISUAL_SYSTEM_TEMPLATE.format(
|
|
rolle="Fagingeniør med 20 års erfaring frå norsk offentleg sektor",
|
|
kontekst="Årlege fagvise inspeksjonar i Noreg",
|
|
oppgåve="Vurder vegskade og anbefal vedlikehaldstiltak",
|
|
steg_for_steg_instruksjonar="""
|
|
1. Identifiser skadetypen (sprekk, hullrot, setning, kantskade)
|
|
2. Vurder alvorlegheit på skala 1-5
|
|
3. Estimer utbreiing i m2
|
|
4. Anbefal tiltak (lappearbeid, fresing, full omlegging)
|
|
5. Prioriter (akutt, innan 3 mnd, neste sesong)""",
|
|
format_spesifikasjon="""JSON med felt:
|
|
{
|
|
"skadetype": "string",
|
|
"alvorlegheit": 1-5,
|
|
"utbreiing_m2": number,
|
|
"tiltak": "string",
|
|
"prioritet": "akutt|3mnd|neste_sesong",
|
|
"grunngjeving": "string"
|
|
}""",
|
|
avgrensing_1="Ikkje anslå kostnad utan prisgrunnlag",
|
|
avgrensing_2="Merk alle vurderingar der confidence er låg"
|
|
)
|
|
```
|
|
|
|
### Rollebaserte system messages
|
|
|
|
| Rolle | System message-fokus | Typisk output |
|
|
|-------|---------------------|---------------|
|
|
| Byggesak-konsulent | TEK17-samsvar, reguleringsplan | Avviksliste med referanse |
|
|
| Vegingeniør | Skadeklassifisering, NVDB-kategori | Vedlikehaldsprioritering |
|
|
| Kulturminne-rådgjevar | Tilstandsvurdering, freding | Tilstandsrapport |
|
|
| Miljørådgjevar | Artsidentifisering, habitatvurdering | Konsekvensutgreiing |
|
|
|
|
---
|
|
|
|
## Image Tokenization og Kostnadsoptimalisering
|
|
|
|
### Token-forbruk per bilete
|
|
|
|
**GPT-4o token-kalkulering (high detail):**
|
|
|
|
1. Skaler biletet slik at lengste side er maks 2048px
|
|
2. Skaler så kortaste side er maks 768px
|
|
3. Del biletet i 512x512-tiles
|
|
4. Kvar tile = 170 tokens
|
|
5. Legg til 85 base tokens
|
|
|
|
```python
|
|
import math
|
|
|
|
def estimate_image_tokens(width: int, height: int,
|
|
detail: str = "high",
|
|
model: str = "gpt-4o") -> int:
|
|
"""Estimer token-forbruk for eit bilete."""
|
|
if detail == "low":
|
|
return 85 if model == "gpt-4o" else 2833
|
|
|
|
# High detail: Skaler ned
|
|
max_long = 2048
|
|
max_short = 768
|
|
|
|
# Steg 1: Skaler lengste side til 2048
|
|
ratio = min(max_long / max(width, height), 1.0)
|
|
w, h = int(width * ratio), int(height * ratio)
|
|
|
|
# Steg 2: Skaler kortaste side til 768
|
|
ratio2 = min(max_short / min(w, h), 1.0)
|
|
w, h = int(w * ratio2), int(h * ratio2)
|
|
|
|
# Steg 3: Tell tiles
|
|
tiles_x = math.ceil(w / 512)
|
|
tiles_y = math.ceil(h / 512)
|
|
total_tiles = tiles_x * tiles_y
|
|
|
|
# Steg 4: Kalkuler tokens
|
|
return 85 + (170 * total_tiles)
|
|
|
|
# Eksempel
|
|
tokens = estimate_image_tokens(4096, 3072, "high")
|
|
print(f"Estimerte tokens: {tokens}") # 85 + (170 * 6) = 1105
|
|
```
|
|
|
|
### Kostnadsoptimaliseringsstrategiar
|
|
|
|
| Strategi | Besparingsestimat | Avveging |
|
|
|----------|-------------------|----------|
|
|
| Bruk `detail: low` for eksempel-bilete | 80-95% per bilete | Lågare oppløysing |
|
|
| Resize til 1024x1024 før sending | 40-60% | Tap av findetaljar |
|
|
| Crop til relevant region | 60-80% | Krev forhandskjennskap |
|
|
| Cache analyseresultat | 100% på gjenbruk | Stale data-risiko |
|
|
| Batch liknande bilete | Redusert overhead | Meir kompleks logikk |
|
|
|
|
---
|
|
|
|
## Norsk offentleg sektor
|
|
|
|
### Bruksområde for multimodal prompt engineering
|
|
- **Byggesak**: Visuell vurdering av samsvar med reguleringsplanar
|
|
- **Vegforvaltning**: Automatisk skadeklassifisering frå dronefoto
|
|
- **Kulturarv**: Tilstandsvurdering av kulturminne frå bilete
|
|
- **Plan og kart**: Analyse av reguleringsplanar og kartutsnitt
|
|
- **Miljø**: Artsidentifisering og habitatvurdering
|
|
|
|
### Prompt-design for norsk kontekst
|
|
- Skriv system messages på norsk for domene-spesifikk terminologi
|
|
- Referer til norske standardar (TEK17, NVDB, NS-EN-standardar)
|
|
- Inkluder norske einskapar (NOK, m2, km/t)
|
|
- Bruk norske stadnamn og referansar
|
|
|
|
### Personvern i multimodale prompts
|
|
- Bilete av personar: Aldri be modellen identifisere personar
|
|
- Nummerplatar: Sladd før analyse om ikkje nødvendig
|
|
- Brev/dokument: Fjern personnummer frå bilete-input
|
|
- Azure OpenAI content filtering aktiv som standard
|
|
|
|
---
|
|
|
|
## Beslutningsrammeverk
|
|
|
|
| Scenario | Anbefaling | Grunngjeving |
|
|
|----------|------------|--------------|
|
|
| Enkel bildeklassifisering | Zero-shot med god system message | Raskast, lågast kostnad |
|
|
| Konsistent klassifisering | Few-shot med 3-5 eksempel-bilete | Betre konsistens, høgare kostnad |
|
|
| Kompleks vurdering | Chain-of-thought med steg-instruksjonar | Transparent resonnement |
|
|
| Kostnadsoptimalisering | `detail: low` + resize + caching | Drastisk token-reduksjon |
|
|
| Nekting/refusal-problem | "Describe first"-teknikk | Omgå overivrig filtering |
|
|
| Multi-bilete-samanlikning | Sekvensielle bilete med tydelege labels | Unngå forvirring |
|
|
| Produksjonssystem | Structured output (JSON) + validering | Påliteleg parsing |
|
|
|
|
---
|
|
|
|
## For Cosmo
|
|
|
|
- **Seks grunnprinsipp for image prompts**: Kontekstuell spesifisitet, oppgåveorientering, refusal-handtering, eksempelbruk, oppgåvedeling og output-formatering — følg Microsoft sin offisielle rettleiing for GPT-4o vision.
|
|
- **Few-shot med bilete brukar `detail: low` (85 tokens) for eksempel** og `detail: high` for mål-biletet — dette gir konsistent klassifisering utan å sprengje token-budsjettet.
|
|
- **Chain-of-thought med visuelt resonnement** gir transparente vurderingar — kritisk for offentleg sektor der avgjerder må grunngjevast, be modellen vise resonneringskjeda steg for steg.
|
|
- **Image tokenization avgjer kostnad**: Eit 4096x3072 bilete i `high detail` kostar ~1105 tokens med GPT-4o — resize til 1024x1024 reduserer til ~765 tokens, og `low detail` er flat 85 tokens.
|
|
- **System messages på norsk med domene-terminologi** gir betre resultat enn engelske generelle prompts — referer til norske standardar, einskapar og kontekst for presise fagvurderingar.
|