AnleitungExperte

RAG für Bilder: Vision models und visuelle Suche

19. März 2026
25 Min. Lesezeit
Ailog Team

Umfassender Leitfaden zur Integration von Bildern in Ihr RAG-System: Vision models, multimodal embeddings, Indexierung und visuelle Suche mit GPT-4V, Claude Vision und CLIP.

RAG für Bilder: Vision-Modelle und visuelle Suche

Die traditionellen RAG-Systeme beschränken sich auf Text. Dabei sind viele Unternehmensinformationen visuell: Produktfotos, Screenshots, Grafiken, technische Zeichnungen. Image RAG erlaubt es, in diesen visuellen Inhalten mit derselben Präzision wie bei einem textuellen RAG zu indexieren und zu suchen.

Warum Bilder in den RAG integrieren?

Visuelle Daten im Unternehmen

  • E-Commerce: 70% der Kaufentscheidungen werden durch Produktbilder beeinflusst
  • Technischer Support: Screenshots beschleunigen die Lösung von Tickets um 60%
  • Dokumentation: Eine Grafik ist oft mehr wert als eine Seite Text
  • Compliance: Baustellenfotos, Zustandsdokumentationen, visuelle Belege

Konkrete Anwendungsfälle

BrancheAnwendungBeispielanfrage
E-CommerceVisuelle Suche"Finde Kleider, die diesem Foto ähneln"
ImmobilienObjektanalyse"Zeig mir moderne Einbauküchen"
IT-SupportDiagnose"Was bedeutet diese Fehlermeldung?"
FertigungQualitätskontrolle"Weist dieses Teil einen Defekt auf?"

Architektur eines Image RAG

Gesamtübersicht

┌─────────────────────────────────────────────────────────────┐
│                    IMAGE RAG PIPELINE                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────┐    ┌──────────────┐    ┌──────────────────┐  │
│  │  Image   │───▶│   Vision     │───▶│   Embedding      │  │
│  │  Input   │    │   Model      │    │   (CLIP/SigLIP)  │  │
│  └──────────┘    └──────────────┘    └──────────────────┘  │
│       │                │                      │             │
│       │                ▼                      ▼             │
│       │         ┌──────────────┐    ┌──────────────────┐   │
│       │         │  Description │    │  Vector Store    │   │
│       │         │  textuelle   │    │  (Qdrant/Pine)   │   │
│       │         └──────────────┘    └──────────────────┘   │
│       │                │                      │             │
│       │                ▼                      ▼             │
│       │         ┌─────────────────────────────────┐        │
│       └────────▶│      Retrieval multimodal       │        │
│                 └─────────────────────────────────┘        │
│                                │                            │
│                                ▼                            │
│                 ┌─────────────────────────────────┐        │
│                 │      Génération (VLM/LLM)       │        │
│                 └─────────────────────────────────┘        │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Die zwei Ansätze

1. Description + RAG textuel

  • Das Vision-Model beschreibt das Bild in Text
  • Der Text wird klassisch indexiert
  • Einfacher, verliert jedoch visuelle Informationen

2. Native multimodale Embeddings

  • Das Bild wird direkt in einen Vektor konvertiert
  • Bewahrt die vollständige visuelle Information
  • Ermöglicht Bild-zu-Bild-Suche

Vision-Modelle für den RAG

Proprietäre Modelle

ModellMax. AuflösungKostenStärken
GPT-4V2048x2048$0.00765/Bild (low)Komplexes Reasoning, exzellentes OCR
Claude 3.5 Sonnet Vision8192x8192$0.003/BildDetaillierte Analyse, Sicherheit
Gemini 1.5 ProUnbegrenzt$0.001315/BildMulti-Bild, langer Kontext

Open-Source-Modelle

ModellParameterVRAMAnwendung
LLaVA 1.634B24GBAllgemeine Beschreibung
CogVLM219B16GBFeingranulares Verständnis
InternVL276B48GBSOTA-Performance
Qwen-VL-Max72B48GBMehrsprachig

Multimodale Embedding-Modelle

ModellDimensionSprachenOpen Source
CLIP (OpenAI)512/768Hauptsächlich ENJa
SigLIP384-1152MehrsprachigJa
Jina CLIP v2102489 SprachenJa
Cohere Embed v31024100+ SprachenNein

Praktische Implementierung

Schritt 1: Extraktion und Beschreibung der Bilder

DEVELOPERpython
import base64 from openai import OpenAI def describe_image_for_rag(image_path: str, context: str = "") -> dict: """ Erzeugt eine RAG-optimierte Beschreibung eines Bildes. """ client = OpenAI() # Das Bild in base64 kodieren with open(image_path, "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8") # Den MIME-Typ bestimmen mime_type = "image/jpeg" if image_path.endswith((".jpg", ".jpeg")) else "image/png" prompt = """Analysiere dieses Bild für ein RAG-System. Liefere: 1. **Allgemeine Beschreibung** (2-3 Sätze) 2. **Schlüsselelemente** (Aufzählung der wichtigen Objekte/Konzepte) 3. **Sichtbarer Text** (jeglicher lesbarer Text im Bild) 4. **Vorgeschlagene Metadaten** (Kategorie, relevante Tags) Sei umfassend, aber prägnant. Ziel ist es, die textuelle Suche auf diesem Bild zu ermöglichen.""" if context: prompt += f"\n\nZusätzlicher Kontext: {context}" response = client.chat.completions.create( model="gpt-4o", messages=[ { "role": "user", "content": [ {"type": "text", "text": prompt}, { "type": "image_url", "image_url": { "url": f"data:{mime_type};base64,{image_data}", "detail": "high" } } ] } ], max_tokens=1000 ) description = response.choices[0].message.content return { "image_path": image_path, "description": description, "model": "gpt-4o", "tokens_used": response.usage.total_tokens }

Schritt 2: Multimodale Embeddings mit CLIP

DEVELOPERpython
import torch from PIL import Image from transformers import CLIPProcessor, CLIPModel class MultimodalEmbedder: def __init__(self, model_name: str = "openai/clip-vit-large-patch14"): self.device = "cuda" if torch.cuda.is_available() else "cpu" self.model = CLIPModel.from_pretrained(model_name).to(self.device) self.processor = CLIPProcessor.from_pretrained(model_name) def embed_image(self, image_path: str) -> list[float]: """Erzeugt ein Embedding für ein Bild.""" image = Image.open(image_path).convert("RGB") inputs = self.processor(images=image, return_tensors="pt").to(self.device) with torch.no_grad(): embedding = self.model.get_image_features(**inputs) # Für Kosinusähnlichkeit normalisieren embedding = embedding / embedding.norm(dim=-1, keepdim=True) return embedding.cpu().squeeze().tolist() def embed_text(self, text: str) -> list[float]: """Erzeugt ein Embedding für Text (im selben Raum wie die Bilder).""" inputs = self.processor(text=[text], return_tensors="pt", padding=True).to(self.device) with torch.no_grad(): embedding = self.model.get_text_features(**inputs) embedding = embedding / embedding.norm(dim=-1, keepdim=True) return embedding.cpu().squeeze().tolist() def compute_similarity(self, image_path: str, text: str) -> float: """Berechnet die Ähnlichkeit Bild-zu-Text.""" img_emb = torch.tensor(self.embed_image(image_path)) txt_emb = torch.tensor(self.embed_text(text)) return (img_emb @ txt_emb).item()

Schritt 3: Indexierung in Qdrant

DEVELOPERpython
from qdrant_client import QdrantClient from qdrant_client.models import ( VectorParams, Distance, PointStruct, Filter, FieldCondition, MatchValue ) class ImageRAGIndex: def __init__(self, collection_name: str = "image_rag"): self.client = QdrantClient(url="http://localhost:6333") self.collection_name = collection_name self.embedder = MultimodalEmbedder() def create_collection(self, vector_size: int = 768): """Erstellt die Collection mit zwei Vektorräumen.""" self.client.recreate_collection( collection_name=self.collection_name, vectors_config={ # Visuelles Embedding (CLIP) "visual": VectorParams( size=vector_size, distance=Distance.COSINE ), # Textuelles Embedding (Beschreibung) "textual": VectorParams( size=1536, # Ada-002 oder ähnlich distance=Distance.COSINE ) } ) def index_image( self, image_id: str, image_path: str, description: str, text_embedding: list[float], metadata: dict = None ): """Indexiert ein Bild mit seinen beiden Embeddings.""" visual_embedding = self.embedder.embed_image(image_path) point = PointStruct( id=hash(image_id) % (2**63), vector={ "visual": visual_embedding, "textual": text_embedding }, payload={ "image_id": image_id, "image_path": image_path, "description": description, **(metadata or {}) } ) self.client.upsert( collection_name=self.collection_name, points=[point] ) def search_by_text(self, query: str, limit: int = 5) -> list[dict]: """Suche mittels textueller Anfrage.""" query_embedding = self.embedder.embed_text(query) results = self.client.search( collection_name=self.collection_name, query_vector=("visual", query_embedding), # CLIP text -> visual limit=limit ) return [ { "image_path": r.payload["image_path"], "description": r.payload["description"], "score": r.score } for r in results ] def search_by_image(self, image_path: str, limit: int = 5) -> list[dict]: """Suche nach ähnlichen Bildern.""" query_embedding = self.embedder.embed_image(image_path) results = self.client.search( collection_name=self.collection_name, query_vector=("visual", query_embedding), limit=limit ) return [ { "image_path": r.payload["image_path"], "description": r.payload["description"], "score": r.score } for r in results ]

Schritt 4: Generierung mit visuellem Kontext

DEVELOPERpython
def generate_with_images( query: str, retrieved_images: list[dict], client: OpenAI ) -> str: """ Erzeugt eine Antwort unter Verwendung der abgerufenen Bilder als Kontext. """ # Den multimodalen Inhalt vorbereiten content = [ { "type": "text", "text": f"""Du bist ein Assistent, der Fragen beantwortet, indem er die bereitgestellten Bilder als Informationsquelle nutzt. Frage des Benutzers: {query} Verfügbare Bilder:""" } ] # Jedes Bild mit seiner Beschreibung hinzufügen for i, img in enumerate(retrieved_images[:3], 1): # Max 3 Bilder with open(img["image_path"], "rb") as f: img_data = base64.b64encode(f.read()).decode("utf-8") content.append({ "type": "text", "text": f"\n**Bild {i}** (Score: {img['score']:.2f}):\n{img['description']}" }) content.append({ "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{img_data}", "detail": "low" # Tokens sparen } }) content.append({ "type": "text", "text": "\n\nBeantworte die Frage ausschließlich auf Grundlage dieser Bilder. Falls die Bilder keine Antwort ermöglichen, sage dies klar." }) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": content}], max_tokens=1000 ) return response.choices[0].message.content

Erweiterte Optimierungen

Chunking hochauflösender Bilder

Für sehr große Bilder (Pläne, Schaubilder) in Kacheln schneiden:

DEVELOPERpython
from PIL import Image def tile_large_image(image_path: str, tile_size: int = 512, overlap: int = 64): """Zerteilt ein großes Bild in überlappende Kacheln.""" img = Image.open(image_path) width, height = img.size tiles = [] for y in range(0, height - overlap, tile_size - overlap): for x in range(0, width - overlap, tile_size - overlap): box = (x, y, min(x + tile_size, width), min(y + tile_size, height)) tile = img.crop(box) tiles.append({ "tile": tile, "position": (x, y), "original_size": (width, height) }) return tiles

Hybride Suche Bild + Text

DEVELOPERpython
def hybrid_image_search( query: str, text_embedding: list[float], index: ImageRAGIndex, alpha: float = 0.7 # Gewicht visuell vs. textuell ) -> list[dict]: """Kombiniert visuelle und textuelle Suche.""" # Visuelle Suche (CLIP) visual_results = index.search_by_text(query, limit=20) # Textuelle Suche (auf den Beschreibungen) text_results = index.client.search( collection_name=index.collection_name, query_vector=("textual", text_embedding), limit=20 ) # Scores mit RRF zusammenführen combined_scores = {} for rank, r in enumerate(visual_results): img_id = r["image_path"] combined_scores[img_id] = combined_scores.get(img_id, 0) + alpha / (rank + 60) for rank, r in enumerate(text_results): img_id = r.payload["image_path"] combined_scores[img_id] = combined_scores.get(img_id, 0) + (1 - alpha) / (rank + 60) # Nach kombiniertem Score sortieren sorted_results = sorted(combined_scores.items(), key=lambda x: x[1], reverse=True) return [{"image_path": path, "score": score} for path, score in sorted_results[:5]]

Benchmarks und Kosten

Retrieval-Performance

MethodePrecision@5Recall@10Latenz
Nur Beschreibung0.720.8150ms
Nur CLIP0.780.8530ms
Hybrid0.840.9180ms

Kosten pro indexiertem Bild

SchrittGeschätzte KostenHinweise
Beschreibung GPT-4V$0,01-0,03Je nach Größe und Detailgrad
CLIP-Embedding$0 (lokal)GPU empfohlen
Qdrant-Speicherung~$0,0001Pro Vektor/Monat

Vergleich der Embedding-Modelle

ModellZero-Shot-GenauigkeitMehrsprachigGeschwindigkeit
CLIP ViT-L/1475.5%NeinSchnell
SigLIP So400m83.1%JaMittel
Jina CLIP v281.2%JaSchnell

Fallstricke und Lösungen

Problem 1: Bilder mit wenig visuellem Inhalt

Symptom: Screenshots mit viel Text werden von CLIP schlecht indexiert.

Lösung: Explizites OCR + textuelle Indexierung.

DEVELOPERpython
import pytesseract def extract_text_from_image(image_path: str) -> str: """Extrahiert Text aus einem Bild mittels OCR.""" img = Image.open(image_path) text = pytesseract.image_to_string(img, lang='fra+eng') return text.strip()

Problem 2: Visuelle Duplikate

Symptom: Mehrere nahezu identische Bilder verschmutzen die Ergebnisse.

Lösung: Deduplizierung per Ähnlichkeit.

DEVELOPERpython
def deduplicate_images(embeddings: list, threshold: float = 0.95): """Entfernt zu ähnliche Bilder.""" keep = [] for i, emb in enumerate(embeddings): is_duplicate = False for j in keep: similarity = cosine_similarity(emb, embeddings[j]) if similarity > threshold: is_duplicate = True break if not is_duplicate: keep.append(i) return keep

Problem 3: Widersprüchlicher visueller vs. textueller Kontext

Symptom: Die generierte Beschreibung widerspricht dem Bild.

Lösung: Kreuzvalidierung und Vertrauensscore.

Integration mit Ailog

Ailog unterstützt nativ die Indexierung von Bildern in euren Knowledge Bases:

  1. Upload: Bilder per Drag & Drop in die Oberfläche ziehen
  2. Automatische Analyse: Vision-Model zur Inhaltsextraktion
  3. Hybride Indexierung: Visuelle + textuelle Embeddings
  4. Vereinheitlichte Suche: Eine einzige Anfrage für Text und Bilder

Probieren Sie das Image RAG bei Ailog aus - Keine Konfiguration erforderlich.

FAQ

CLIP erzeugt multimodale Embeddings, die Bild-zu-Bild- und Text-zu-Bild-Suche direkt ermöglichen. GPT-4V analysiert und beschreibt Bilder in detailliertem Text. Praktisch kombiniert man beides: CLIP für schnelles retrieval und GPT-4V für tiefgehende Analyse und kontextuelle Antwortgenerierung.
Rechnet mit etwa 10–30 Dollar für 1000 Bilder mit GPT-4V (Beschreibung) plus den CLIP-Embeddings (lokal kostenlos). Die Hauptkosten entstehen durch die initiale Beschreibung. Nach der Indexierung kosten die Suchen nur noch die Embeddings der Anfrage und die Kosten für die Antwortgenerierung.
Ja, aber mit Einschränkungen. CLIP kann auf CPU laufen (langsamer), und man kann Cloud-APIs (OpenAI, Anthropic) für die Vision-Models nutzen. Für produktive Systeme mit vielen Bildern beschleunigt ein GPU die Initialindexierung erheblich und reduziert langfristig die Kosten.
Vision-Modelle wie GPT-4V haben ein exzellentes eingebautes OCR, aber für textlastige Dokumente kombiniert man die Ansätze: Text via dediziertem OCR (Tesseract, Azure Document Intelligence) extrahieren und separat indexieren. Das verbessert die textuelle Suche und erhält gleichzeitig den visuellen Kontext.
Absolut. Das ist sogar ein idealer Anwendungsfall. Indexieren Sie die Produktfotos mit ihren generierten Beschreibungen und ermöglichen Sie den Kunden die visuelle Suche ("finde ähnliche Kleider"). Für große Kataloge verwenden Sie Qdrant oder Pinecone mit für großangelegte Suchen optimierten Indizes.

Verwandte Guides

Tags

RAGmultimodalvisionimagesGPT-4VClaude VisionCLIPembeddings

Verwandte Artikel

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !