Zum Inhalt springen
CASOON

RAG mit Mistral: Dokumente, Embeddings und Suche

Wie man mit Mistral interne Wissenssysteme baut – Architektur, Grenzen, Praxis

13 Minuten
RAG mit Mistral: Dokumente, Embeddings und Suche
#Mistral #RAG #Embeddings #Vektordatenbank
SerieMistral & Vibe CLI
Teil 15 von 16

Wenn ein Sprachmodell Fragen zu internen Dokumenten beantworten soll – Handbüchern, Kundendaten, Projektdokumentation – reicht ein reines Chatbot-Setup nicht aus. Das Modell kennt diese Daten nicht, es hat sie nie gesehen. Ohne Kontext erfindet es Antworten oder gibt offen zu, nichts zu wissen.

Retrieval-Augmented Generation (RAG) löst genau dieses Problem: Relevante Dokumentausschnitte werden zur Laufzeit in den Prompt geladen. Das Modell antwortet auf Basis echter Quellen – nachvollziehbar, aktuell, kontrollierbar.

Dieser Artikel zeigt, wie eine RAG-Pipeline mit Mistral aufgebaut wird: von der Grundidee über eigene Python-Implementierung bis zu Unternehmensarchitektur, Grenzen und Datenschutz.

Was ist RAG? Kernbegriffe kompakt

RAG (Retrieval-Augmented Generation) kombiniert klassische Suche mit generativer KI: Dokumente werden vorab in Embeddings umgewandelt und in einer Vektordatenbank gespeichert. Bei einer Anfrage wird zunächst gesucht, dann generiert.

Chunking bezeichnet die Aufteilung von Dokumenten in kleinere Abschnitte (Chunks). Chunks sind die eigentliche Sucheinheit – sie sollten semantisch kohärent sein, typischerweise 256 bis 512 Tokens groß.

Embeddings sind numerische Vektoren, die den semantischen Inhalt eines Texts komprimiert darstellen. Ähnliche Texte liegen im Vektorraum nah beieinander. Mistral stellt dafür das Modell mistral-embed bereit.

Vektordatenbank speichert diese Embeddings und ermöglicht effiziente Nearest-Neighbor-Suche. Bekannte Optionen: FAISS (lokal, in-memory), Chroma (lokal, persistent), Weaviate und Pinecone (Cloud-fähig, Metadaten-Filter).

Retrieval bezeichnet den Suchschritt: Die Frage wird ebenfalls zu einem Embedding, dann werden die ähnlichsten Chunks in der Datenbank gesucht.

Prompt Injection ist eine Angriffsvariante, bei der Inhalte in indexierten Dokumenten absichtlich Anweisungen für das Modell einschmuggeln. Relevant sobald externe oder nicht kontrollierte Dokumente indexiert werden.

Die RAG-Architektur im Überblick

Eine vollständige RAG-Pipeline mit Mistral läuft in zwei Phasen ab: Indexierung (einmalig, bei Dokumentänderungen) und Retrieval (bei jeder Anfrage).

1
Indexierungsphase: Dokumente laden PDFs, Confluence-Seiten, Textdateien, Datenbankexporte – alles, was als Wissensquelle dienen soll. Dokumente werden in lesbare Texte umgewandelt.
2
Indexierungsphase: Chunking Texte werden in Abschnitte von 256–512 Tokens aufgeteilt. Optional: Metadaten (Quelle, Datum, Abteilung) werden pro Chunk gespeichert.
3
Indexierungsphase: Embeddings mit mistral-embed Jeder Chunk wird an die Mistral Embeddings API gesendet und als Vektor gespeichert. mistral-embed gibt 1024-dimensionale Vektoren zurück.
4
Indexierungsphase: Vektordatenbank Vektoren + Originaltext + Metadaten werden in FAISS, Chroma, Weaviate oder Pinecone gespeichert. Der Index ist danach abfragebereit.
5
Abfragephase: Retrieval Die Nutzerfrage wird ebenfalls zu einem Embedding. Die Vektordatenbank sucht die k ähnlichsten Chunks (Nearest-Neighbor-Suche).
6
Abfragephase: Prompt-Konstruktion und Antwort Die gefundenen Chunks werden als Kontext in den Prompt eingebaut. Mistral (z.B. mistral-large) antwortet auf Basis dieser Dokumente.

Der entscheidende Punkt: Das Sprachmodell generiert keine Antwort aus eigenem Wissen – es liest die relevanten Abschnitte im Prompt und formuliert darauf basierend eine Antwort.

Eigene RAG-Pipeline mit Python aufbauen

Das folgende Beispiel verwendet die Mistral Python SDK und FAISS als Vektordatenbank. FAISS ist ideal für lokale Entwicklung und mittelgroße Dokumentenmengen ohne Cloud-Abhängigkeit.

Installation:

pip install mistralai faiss-cpu numpy

Schritt 1: Dokumente laden und aufteilen

# Einfaches Chunking nach Zeichenanzahl
# Für Produktionseinsatz: langchain.text_splitter oder tiktoken verwenden

def chunk_text(text: str, chunk_size: int = 1000, overlap: int = 100) -> list[str]:
    chunks = []
    start = 0
    while start < len(text):
        end = start + chunk_size
        chunks.append(text[start:end])
        start = end - overlap  # Überlappung für Kontext-Kontinuität
    return chunks

# Beispiel: Textdatei laden
with open("handbuch.txt", "r", encoding="utf-8") as f:
    raw_text = f.read()

chunks = chunk_text(raw_text)
print(f"{len(chunks)} Chunks erstellt")

Für Produktionsumgebungen empfiehlt sich RecursiveCharacterTextSplitter aus LangChain, das Satzgrenzen respektiert. Für PDFs: pymupdf oder pdfplumber.

Schritt 2: Embeddings mit mistral-embed erstellen

import numpy as np
from mistralai import Mistral

client = Mistral(api_key="YOUR_API_KEY")

def get_embeddings(texts: list[str], batch_size: int = 50) -> np.ndarray:
    all_embeddings = []

    # API in Batches aufrufen (Rate-Limits beachten)
    for i in range(0, len(texts), batch_size):
        batch = texts[i : i + batch_size]
        response = client.embeddings.create(
            model="mistral-embed",
            inputs=batch,
        )
        batch_embeddings = [e.embedding for e in response.data]
        all_embeddings.extend(batch_embeddings)

    return np.array(all_embeddings, dtype="float32")

text_embeddings = get_embeddings(chunks)
print(f"Embedding-Dimension: {text_embeddings.shape[1]}")  # 1024 bei mistral-embed

Schritt 3: FAISS-Index aufbauen

import faiss

dimension = text_embeddings.shape[1]

# IndexFlatL2: exakte Suche, gut für Entwicklung und kleine Bestände
# Für große Bestände: IndexIVFFlat oder IndexHNSWFlat erwägen
index = faiss.IndexFlatL2(dimension)
index.add(text_embeddings)

print(f"Index enthält {index.ntotal} Vektoren")

# Optional: Index auf Disk speichern
faiss.write_index(index, "dokumente.index")

Schritt 4: Retrieval für eine Nutzerfrage

def retrieve(query: str, k: int = 3) -> list[str]:
    # Frage embedden
    response = client.embeddings.create(
        model="mistral-embed",
        inputs=[query],
    )
    query_embedding = np.array(
        [response.data[0].embedding], dtype="float32"
    )

    # Nearest Neighbors suchen
    distances, indices = index.search(query_embedding, k=k)

    return [chunks[i] for i in indices[0]]

context_chunks = retrieve("Wie wird die Software installiert?")

Schritt 5: Prompt konstruieren und Mistral antworten lassen

def ask(query: str) -> str:
    context_chunks = retrieve(query, k=3)
    context = "\n\n---\n\n".join(context_chunks)

    prompt = f"""Du bist ein hilfreicher Assistent. Beantworte die Frage ausschließlich
auf Basis der folgenden Dokumente. Wenn die Antwort nicht in den Dokumenten
enthalten ist, sag das explizit.

Dokumente:
{context}

Frage: {query}
Antwort:"""

    response = client.chat.complete(
        model="mistral-large-latest",
        messages=[{"role": "user", "content": prompt}],
    )
    return response.choices[0].message.content

print(ask("Wie wird die Software installiert?"))

Low-Code-Einstieg: LangChain und n8n

Wer keine eigene Pipeline bauen will, hat zwei etablierte Einstiegspunkte:

LangChain abstrahiert die gesamte RAG-Pipeline in wenige Zeilen. Die LangChain-Mistral-Integration unterstützt ChatMistralAI für Generierung und MistralAIEmbeddings für Embeddings. Dazu kommen fertige Retriever für FAISS, Chroma und Weaviate. Der Vorteil: sauber entkoppelte Retrieval- und Generierungsschritte, einfache Austauschbarkeit von Komponenten. Der Nachteil: Abstraktion versteckt, was tatsächlich passiert – schwieriger zu debuggen.

from langchain_mistralai import ChatMistralAI, MistralAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA

embeddings = MistralAIEmbeddings(model="mistral-embed")
vectorstore = FAISS.from_texts(chunks, embeddings)

llm = ChatMistralAI(model="mistral-large-latest")
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=vectorstore.as_retriever())

result = qa_chain.invoke({"query": "Wie wird die Software installiert?"})

n8n ermöglicht RAG-Agenten ohne Code: Pinecone als Vektordatenbank, Mistral für Embeddings und Chat – verbunden über visuelle Workflows. Geeignet für Agenturen, die schnell Proof-of-Concepts bauen, ohne Python-Stack aufzusetzen. Beide Tools (Pinecone, Mistral) bieten kostenfreie Tiers.

Unternehmensarchitektur: Datenquellen, Chunking, Stack

In der Praxis geht es selten um eine einzelne Textdatei. Die Architektur skaliert mit der Datenvielfalt.

Typische Datenquellen:

  • Intern: PDF-Handbücher, Confluence-Seiten, Jira-Tickets, SharePoint-Dokumente, Datenbankexporte
  • Extern: API-Feeds, öffentliche Dokumentationen, regulatorische Texte

Chunking-Strategien im Vergleich:

StrategieBeschreibungGeeignet für
Token-basiertFeste Größe (256–512 Tokens), optionale ÜberlappungAllgemeine Dokumente, einfache Implementierung
Satz-/ParagraphenbasiertTrennung an natürlichen GrenzenFließtext, Dokumentationen
HierarchischParagraph-Ebene + Dokument-MetadatenEnterprise-Suche mit Kontext-Filterung
SemantischChunk-Grenzen nach semantischer Kohärenz (z.B. über Embedding-Distanz)Qualitätsanspruchsvolle Systeme

Metadaten sind unterschätzt: Wer pro Chunk Quelle, Abteilung, Dokumentversion, Sprache und Zugriffsberechtigung speichert, kann später nach diesen Feldern filtern – bevor der Nearest-Neighbor-Schritt läuft. Weaviate und Pinecone unterstützen solche Metadaten-Filter nativ.

Mistral-Stack-Optionen im Überblick:

KomponenteCloud-VarianteSelf-Hosted-Variante
Embeddingsmistral-embed über Mistral APILokale Embedding-Modelle via Ollama
LLM für Antwortmistral-large-latest über APIMistral 7B / Mistral Nemo via Ollama
VektordatenbankPinecone, Weaviate CloudFAISS (in-memory), Chroma, Weaviate lokal
OrchestrierungLangChain, LlamaIndex, n8nDasselbe, lokal ausgeführt

Grenzen: Wann RAG nicht hilft

RAG ist kein Universalwerkzeug. Fünf Szenarien, in denen es reicht – und drei, in denen es nicht ausreicht.

RAG funktioniert gut für:

  • Fragen zu internen Dokumenten mit klaren Antworten
  • Zusammenfassungen aus bekannten Quellen
  • Suche in technischen Handbüchern oder Vertragssammlungen
  • Kundenservice-Bots mit definiertem Wissensbereich
  • Code-Assistenten mit Zugriff auf interne Codebases

RAG stößt an Grenzen bei:

Wissen, das nicht in den Dokumenten steckt. Wenn die Antwort in keinem indexierten Dokument vorkommt, kann Mistral nur raten oder ablehnen. RAG erzeugt keine Erkenntnisse – es sucht und formuliert.

Niedrige Retrieval-Qualität. Embeddings liefern Nearest Neighbors nach semantischer Ähnlichkeit, nicht nach fachlicher Korrektheit. Wenn ein Chunk thematisch ähnlich, aber inhaltlich falsch ist, landet er trotzdem oben – und das Modell antwortet auf Basis falscher Prämissen.

Aktualität und Versionsdrift. Ändern sich Dokumente, muss der Index neu aufgebaut werden. Veraltete Embeddings führen zu veralteten Antworten. In dynamischen Wissensbasen ist ein automatisierter Re-Index-Prozess Pflicht.

Entscheidungslogik und Berechnungen. Wenn eine Frage eine Berechnung, einen Regelabgleich oder eine Entscheidungstabelle erfordert, ist RAG das falsche Tool. Besser: klassische Geschäftslogik, regelbasierte Systeme oder strukturierte Datenabfragen.

Datenschutz: Self-Hosted RAG vs. Cloud

Für Unternehmen mit sensiblen Dokumenten ist die Frage, wo Daten und Embeddings liegen, entscheidend.

AspektCloud-RAGSelf-Hosted RAG
Embeddings-VerarbeitungDokumente werden an externe API gesendetLokal (Ollama + lokales Embedding-Modell)
VektordatenbankPinecone, Weaviate CloudFAISS, Chroma, Weaviate on-premise
DatenschutzAVV mit Mistral / Pinecone nötig; DSGVO prüfenDaten verlassen das Unternehmen nicht
WartungsaufwandGering (Managed Services)Hoch (Infrastruktur, Updates, Backups)
KostenNutzungsabhängig; bei großen Indexen teuerHardware/GPU + DevOps-Kapazität
PerformanceHoch (optimierte Cloud-Modelle)Abhängig von Hardware; Mistral 7B ist CPU-fähig
EmpfehlungProduktivdaten ohne besondere SchutzstufeHR, Finanzen, M&A, Patiente, Rechtsakten

Mischmodell ist oft der pragmatischste Ansatz: Öffentliche oder weniger sensible Dokumente laufen über die Cloud-Pipeline. Dokumente mit besonderem Schutzbedarf – HR-Akten, Finanzdaten, Kundendaten mit besonderer Vertraulichkeit – werden lokal indexiert und abgefragt.

Self-Hosted mit Ollama: Mistral 7B und Mistral Nemo laufen auf moderner Consumer-Hardware. Über Ollama ist die Einrichtung auf einem Mac oder Linux-Server in wenigen Minuten erledigt. Für Embeddings stehen lokale Modelle wie nomic-embed-text zur Verfügung – kein API-Call, kein Datentransfer.

# Mistral lokal starten
ollama pull mistral
ollama pull nomic-embed-text
ollama serve

LangChain, LlamaIndex und LlamaIndex unterstützen Ollama direkt als Provider – der Austausch von Cloud-API zu lokalem Modell ist in der Regel ein Einzeiler.

Einordnung: Wann RAG der richtige Ansatz ist

RAG ist heute die erste Wahl, wenn ein Sprachmodell auf kontrolliertes, aktuelles Wissen zugreifen soll, das nicht im Training enthalten ist. Die Architektur ist erprobt, die Werkzeuge sind ausgereift – von einfachem FAISS für lokale Entwicklung bis zu Weaviate mit Metadaten-Filterung für Enterprise-Deployments.

Die Entscheidung für Cloud oder Self-Hosted ist keine technische, sondern eine datenschutzrechtliche. Wer interne Dokumente mit mistral-embed verarbeitet, sendet diese Dokumente an Mistral – das erfordert einen Auftragsverarbeitungsvertrag und eine DSGVO-Prüfung. Wer das nicht will, setzt Ollama ein und bleibt lokal.

Die wichtigsten Qualitätshebel sind Chunking-Strategie und Retrieval-Qualität – nicht das Sprachmodell. Ein guter Retriever mit präzisen Chunks schlägt ein schlechter Retriever mit mistral-large jedes Mal. Darin investierte Zeit zahlt sich direkt in bessere Antworten aus.

Weiterführend: