Wer 2026 eine eigene RAG-Anwendung baut, stößt fast zwangsläufig auf zwei Namen: LlamaIndex und Qdrant. Das eine ist das Datenframework, das Dokumente in eine für Sprachmodelle nutzbare Form bringt. Das andere ist die Vektor-Datenbank, die diese Daten speichert und in Millisekunden durchsucht. Am 21. September 2026 hat das Team hinter LlamaIndex Version 0.14.25 veröffentlicht, nur wenige Tage bevor ein Commit Unterstützung für Claude Sonnet 5.5 nachreichte. Qdrant zog mit Version 1.19.1 nach. Beide Projekte bewegen sich schnell, und genau das macht den Einstieg für Entwickler unübersichtlich, die zum ersten Mal eine produktionsreife Pipeline aufsetzen wollen.
Dieses Tutorial führt Schritt für Schritt durch den kompletten Aufbau: von der lokalen Python-Umgebung über den Qdrant-Container bis zur fertigen Chat-Engine mit Metadatenfiltern und Persistenz. Am Ende steht ein lauffähiges Projekt, das eigene Dokumente durchsuchbar macht, ganz ohne Cloud-Abhängigkeit, falls gewünscht. Die Codebeispiele stammen direkt aus den aktuellen APIs von LlamaIndex 0.14.25 und qdrant-client, sodass sie auch in einigen Monaten noch funktionieren sollten, solange keine Breaking Changes dazwischenkommen.
Der Anwendungsfall klingt zunächst technisch, betrifft aber sehr praktische Probleme: ein Support-Team, das durch Hunderte PDF-Handbücher sucht, eine Kanzlei, die Verträge nach Klauseln durchsuchbar machen will, oder ein Entwicklerteam, das interne Wikis in einen Chatbot verwandeln möchte. In allen drei Fällen ersetzt die Kombination aus LlamaIndex und Qdrant eine mühsame manuelle Suche durch eine Frage in natürlicher Sprache. Der Aufbau bleibt dabei überschaubar, sofern die einzelnen Schritte sauber nacheinander abgearbeitet werden, statt Codeschnipsel aus verschiedenen Versionsständen zu mischen.
Was ist LlamaIndex und warum lohnt sich der Umstieg 2026?
LlamaIndex, früher als GPT Index bekannt, ist ein Open-Source-Framework, das Rohdaten wie PDFs, Webseiten oder Datenbankeinträge in eine Struktur überführt, mit der große Sprachmodelle arbeiten können. Das Projekt liegt im Repository run-llama/llama_index auf GitHub und zählte am 30. September 2026 rund 52.400 Sterne und 8.300 Forks. Damit gehört es zu den etabliertesten Werkzeugen für Retrieval Augmented Generation, kurz RAG, neben LangChain und dessen Ableger LangGraph.
Der Kern von LlamaIndex besteht aus drei Bausteinen: Readern, die Dokumente einlesen, Indizes, die Embeddings organisieren, und Query Engines, die Anfragen gegen diese Indizes ausführen. Version 0.14.25 bringt vor allem Sicherheitskorrekturen in mehreren Agent- und Callback-Paketen mit, während ein Commit vom 29. September 2026 bereits Anthropics Claude Sonnet 5.5 als LLM-Backend anbindet. Wer also nicht nur mit OpenAI-Modellen arbeiten will, ist mit der aktuellen Version gut bedient.
Wichtig für die Einordnung: LlamaIndex selbst speichert keine Vektoren dauerhaft. Ohne eine externe Datenbank landen Embeddings nur im Arbeitsspeicher des laufenden Python-Prozesses und sind nach Programmende verloren. Für Experimente mit einer Handvoll Dokumenten reicht das aus, für alles, was über einen einmaligen Testlauf hinausgeht, braucht es einen persistenten Vektorspeicher wie Qdrant, Pinecone oder Weaviate. Dieses Tutorial nutzt bewusst Qdrant, weil es sich lokal ohne Cloud-Abhängigkeit betreiben lässt und unter einer Open-Source-Lizenz steht.
Anders als generische RAG-Tutorials, die oft nur In-Memory-Indizes zeigen, konzentriert sich dieser Artikel auf eine Kombination, die auch bei mehreren Millionen Vektoren stabil bleibt: LlamaIndex als Orchestrierungsschicht, Qdrant als persistenter Speicher.
Zum Ökosystem gehört außerdem LlamaHub, eine Sammlung fertiger Reader für Datenquellen wie Notion, Slack, Google Drive oder SQL-Datenbanken. Wer über reine Textdateien hinausgehen will, muss diese Reader also nicht selbst schreiben, sondern bindet sie über eine einzige Zeile Code ein. Zusätzlich bringt das Framework fertige Agenten-Workflows mit, die Funktionsaufrufe, Websuche und mehrstufiges Schlussfolgern kombinieren, was in diesem Tutorial aber bewusst außen vor bleibt, um den Fokus auf einer soliden RAG-Grundlage zu halten.
Qdrant als Vektor-Datenbank: Die Rolle in der RAG-Pipeline
Qdrant ist eine in Rust geschriebene Open-Source-Vektor-Datenbank und läuft entweder lokal per Docker, selbst gehostet auf einem eigenen Server oder als verwalteter Cloud-Dienst. Die Server-Version 1.19.1 erschien am 4. September 2026, der dazugehörige Python-Client qdrant-client zog am 16. September 2026 mit derselben Versionsnummer nach. Das Standard-Setup exponiert Port 6333 für die HTTP-API und Port 6334 für gRPC.
Im Vergleich zu einem reinen In-Memory-Index von LlamaIndex bringt Qdrant drei Vorteile. Die Daten überleben einen Neustart, weil sie auf Platte persistiert werden. Filterung nach Metadaten läuft direkt in der Datenbank statt im Anwendungscode. Und die Skalierung auf mehrere Millionen Vektoren gelingt über Sharding und Replikation, ohne dass der Python-Prozess selbst mehr Arbeitsspeicher braucht. Die offiziellen Qdrant-Release-Notes zur Version 1.19.1 nennen zusätzlich verbesserte Filterlogik, was direkt in die Metadatenfilter-Beispiele weiter unten einfließt.
Ein oft übersehener Punkt ist die Wahl der Distanzmetrik, mit der Qdrant die Ähnlichkeit zweier Vektoren berechnet. Cosine-Similarity eignet sich für die meisten Text-Embeddings, weil sie die Richtung der Vektoren vergleicht statt ihrer absoluten Länge. Dot-Product und euklidischer Abstand stehen ebenfalls zur Verfügung, sind aber nur bei bestimmten Embedding-Modellen die bessere Wahl. LlamaIndex setzt beim Anlegen einer neuen Collection standardmäßig eine passende Metrik, wer jedoch ein exotischeres Embedding-Modell einsetzt, sollte in dessen Dokumentation nachsehen, welche Metrik empfohlen wird.
Typische Anwendungsfälle für LlamaIndex mit Qdrant
Bevor es an die Installation geht, lohnt sich ein Blick auf konkrete Szenarien, in denen sich der Aufwand auszahlt. Ein Support-Team mit mehreren Hundert PDF-Handbüchern spart durch eine solche Pipeline im Schnitt spürbar Zeit, weil Mitarbeitende Fragen in natürlicher Sprache stellen können, statt Stichwörter in einer Volltextsuche durchzuprobieren. Die Antwort verweist zusätzlich auf die Quelle, sodass sich Aussagen im Zweifel im Originaldokument nachprüfen lassen.
In Kanzleien und Rechtsabteilungen übernimmt dieselbe Architektur die Suche nach Klauseln in Vertragswerken. Metadatenfilter nach Vertragstyp, Datum oder Mandant, wie in Schritt 10 beschrieben, machen aus einer reinen Ähnlichkeitssuche ein präzises Werkzeug, das nur innerhalb der relevanten Dokumentkategorie sucht. Entwicklerteams wiederum verwandeln interne Wikis und Architekturdokumentation in einen durchsuchbaren Assistenten, der neuen Kolleginnen und Kollegen beim Einarbeiten hilft, ohne dass jemand ständig Fragen im Chat beantworten muss.
Auch im E-Commerce lässt sich das Muster übertragen: Produktbeschreibungen, Bewertungen und technische Datenblätter landen in Qdrant, während LlamaIndex Kundenanfragen wie “Welches Modell eignet sich für kleine Wohnungen?” gegen diese Daten abgleicht. In allen Fällen bleibt der Kern identisch, nur die Dokumentquellen, Metadatenfelder und Prompt-Formulierungen unterscheiden sich je nach Branche.
Voraussetzungen: Software, Versionen und Zugangsdaten
Bevor der erste Befehl läuft, sollten folgende Komponenten bereitstehen. LlamaIndex 0.14.25 verlangt laut PyPI-Metadaten explizit Python 3.10 oder neuer, aber unter Python 4.0. Der qdrant-client-Python-Wrapper ist genügsamer und funktioniert bereits ab Python 3.8, in der Praxis lohnt es sich aber, direkt auf 3.10 oder neuer zu setzen, damit beide Pakete konfliktfrei zusammenarbeiten.
| Komponente | Mindestversion | Zweck |
|---|---|---|
| Python | 3.10 | Laufzeitumgebung für LlamaIndex 0.14.25 |
| Docker | 24.x oder neuer | Betrieb des Qdrant-Containers |
| llama-index | 0.14.25 | Framework für Dokumentenverarbeitung und RAG |
| qdrant-client | 1.19.1 | Python-Anbindung an die Qdrant-API |
| Qdrant Server | 1.19.1 | Vektor-Datenbank für Embeddings |
| OpenAI-API-Key (optional) | – | Embeddings und LLM-Antworten, alternativ lokal via Ollama |
Hardware-Empfehlung für den lokalen Betrieb
Für Testzwecke mit ein paar Hundert Dokumenten reichen 8 GB Arbeitsspeicher und zwei CPU-Kerne. Wer lokale Embedding-Modelle über Hugging Face laufen lässt statt eine API zu nutzen, sollte mindestens 16 GB RAM einplanen, da das Embedding-Modell zusätzlich zu Qdrant und Python im Speicher liegt. Eine GPU beschleunigt das Einbetten deutlich, ist für den Einstieg aber kein Muss.
Speicherplatz auf der Festplatte wird oft unterschätzt. Jeder Vektor belegt je nach Embedding-Dimension mehrere Kilobyte, bei 100.000 Dokumenten mit mehreren Chunks pro Dokument kommen so schnell einige Gigabyte zusammen. Eine stabile Internetverbindung ist nur nötig, sofern Embeddings oder Textgenerierung über eine externe API laufen. Beim vollständig lokalen Betrieb mit Ollama und Hugging-Face-Modellen läuft die gesamte Pipeline offline, was gerade für Unternehmen mit strengen Datenschutzvorgaben relevant ist.
Schritt 1: Python-Umgebung und virtuelles Environment vorbereiten
Ein sauberes virtuelles Environment verhindert Versionskonflikte mit anderen Projekten auf demselben Rechner. Zuerst wird ein neuer Projektordner angelegt, danach folgt die Umgebung selbst.
mkdir llamaindex-qdrant-projekt
cd llamaindex-qdrant-projekt
python3 --version
python3 -m venv venv
source venv/bin/activate
# Unter Windows: venv\Scripts\activate
Der Befehl python3 –version sollte 3.10 oder höher ausgeben. Erscheint eine ältere Version, hilft ein Wechsel über pyenv oder die Installation eines aktuellen Python-Pakets von der offiziellen Downloadseite über den jeweiligen Paketmanager des Betriebssystems.
Schritt 2: Qdrant lokal per Docker starten
Qdrant lässt sich ohne Installation zusätzlicher Abhängigkeiten direkt als Container starten. Wichtig ist ein gemountetes Volume, sonst gehen alle Daten beim nächsten Container-Neustart verloren.
docker pull qdrant/qdrant:v1.19.1
docker run -d --name qdrant-rag \
-p 6333:6333 -p 6334:6334 \
-v $(pwd)/qdrant_storage:/qdrant/storage:z \
qdrant/qdrant:v1.19.1
Nach wenigen Sekunden lässt sich der Status per Browser unter http://localhost:6333/dashboard prüfen. Erscheint dort das Qdrant-Dashboard, läuft die Datenbank korrekt und wartet auf Verbindungen.
Schritt 3: LlamaIndex und Qdrant-Pakete installieren
LlamaIndex ist modular aufgebaut. Das Kernpaket allein reicht nicht aus, denn die Qdrant-Anbindung liegt in einem separaten Integrationspaket. Wer das übersieht, landet schnell bei einem ImportError, siehe dazu den Abschnitt zur Fehlerbehebung weiter unten.
pip install llama-index==0.14.25
pip install llama-index-vector-stores-qdrant
pip install qdrant-client==1.19.1
pip install python-dotenv
Alternativ lässt sich alles in einer requirements.txt bündeln, was spätere Deployments deutlich vereinfacht. Feste Versionsnummern statt loser Angaben verhindern außerdem, dass ein automatisches Update mitten in der Entwicklung unerwartet API-Signaturen verändert, ein Problem, das bei schnell iterierenden Open-Source-Projekten wie LlamaIndex regelmäßig vorkommt.
llama-index==0.14.25
llama-index-vector-stores-qdrant
qdrant-client==1.19.1
python-dotenv
Schritt 4: API-Schlüssel und Umgebungsvariablen setzen
Standardmäßig nutzt LlamaIndex OpenAI-Modelle für Embeddings und Textgenerierung. Wer das beibehalten will, legt eine .env-Datei an und trägt dort den API-Key ein, statt ihn im Quellcode zu hinterlegen.
echo "OPENAI_API_KEY=sk-dein-schluessel-hier" > .env
Im Python-Code wird die Datei über python-dotenv geladen. Wer stattdessen komplett offline arbeiten möchte, kann diesen Schritt überspringen und im Abschnitt zu den Profi-Tipps nachlesen, wie sich Ollama als lokaler Ersatz einrichten lässt.
from dotenv import load_dotenv
load_dotenv()
Schritt 5: Dokumente laden und in Chunks aufteilen
Für dieses Beispiel liegen ein paar Textdateien und PDFs im Ordner daten. Der SimpleDirectoryReader von LlamaIndex erkennt gängige Formate automatisch und liest sie ein.
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader("./daten").load_data()
print(f"{len(documents)} Dokumente geladen")
Die Chunk-Größe steuert, wie fein die Dokumente später zerlegt werden. Ein zu kleiner Wert zerschneidet Sätze mitten im Kontext, ein zu großer Wert verwässert die Relevanz einzelner Treffer. Für Fließtext hat sich ein Wert zwischen 512 und 1024 Tokens bewährt, konfigurierbar über den globalen Settings-Mechanismus.
Bei PDF-Dateien mit Tabellen oder mehrspaltigem Layout liefert der Standard-Reader nicht immer sauberen Fließtext, weil die Extraktion auf der reinen Textreihenfolge im PDF basiert. In solchen Fällen hilft ein spezialisierter Reader aus der offiziellen LlamaIndex-Dokumentation, etwa für strukturierte PDFs oder Excel-Tabellen, statt den generischen SimpleDirectoryReader zu erzwingen. Für Markdown- und Textdateien funktioniert der Standardweg dagegen zuverlässig ohne Zusatzaufwand.
from llama_index.core import Settings
Settings.chunk_size = 512
Settings.chunk_overlap = 50
Schritt 6: Qdrant-Vektorspeicher und Storage Context aufbauen
Jetzt kommt die Verbindung zur Datenbank ins Spiel. Der QdrantClient verbindet sich mit dem laufenden Container, der QdrantVectorStore wird an diesen Client gekoppelt und in einen StorageContext eingebettet.
import qdrant_client
from llama_index.vector_stores.qdrant import QdrantVectorStore
from llama_index.core import StorageContext
client = qdrant_client.QdrantClient(host="localhost", port=6333)
vector_store = QdrantVectorStore(
client=client,
collection_name="dokumente_v1"
)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
Details zu allen verfügbaren Parametern von QdrantVectorStore liefert die offizielle Qdrant-Integrationsdokumentation für LlamaIndex. Der Name der Collection ist frei wählbar, sollte aber sprechend und versioniert sein. Ändert sich später das Embedding-Modell, empfiehlt sich eine neue Collection statt der Wiederverwendung der alten, siehe dazu die Stolpersteine weiter unten.
Schritt 7: Index erstellen und Embeddings schreiben
Mit Dokumenten, Vektorspeicher und Storage Context lässt sich der eigentliche Index in einer Zeile erzeugen. LlamaIndex übernimmt dabei automatisch das Aufteilen in Chunks, das Erzeugen der Embeddings und das Schreiben in Qdrant.
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context
)
Bei größeren Dokumentenmengen dauert dieser Schritt spürbar länger, weil jede Anfrage an die Embedding-API einzeln abgerechnet und verarbeitet wird. Für mehrere Tausend Dokumente lohnt sich Batch-Verarbeitung, dazu mehr im Abschnitt zu den Profi-Tipps. Im Hintergrund legt LlamaIndex beim ersten Aufruf automatisch eine neue Qdrant-Collection mit passender Vektordimension an, sofern noch keine Collection unter diesem Namen existiert. Existiert bereits eine Collection mit abweichender Dimension, meldet Qdrant einen Fehler, statt die Daten stillschweigend zu überschreiben.
Schritt 8: Query Engine aufbauen und erste Abfrage senden
Sobald der Index steht, liefert die Query Engine Antworten auf natürlichsprachliche Fragen. LlamaIndex sucht die relevantesten Chunks in Qdrant, reicht sie als Kontext an das Sprachmodell weiter und formuliert daraus eine Antwort.
query_engine = index.as_query_engine(similarity_top_k=3)
response = query_engine.query(
"Welche Themen behandeln die geladenen Dokumente?"
)
print(response)
similarity_top_k legt fest, wie viele Chunks pro Anfrage berücksichtigt werden. Ein höherer Wert liefert mehr Kontext, kostet aber auch mehr Tokens pro Anfrage an das Sprachmodell. Für die meisten Anwendungsfälle mit klar formulierten Fragen reichen drei bis fünf Chunks aus, bei sehr breiten Fragen über mehrere Dokumente hinweg kann ein Wert von acht bis zehn sinnvoller sein.
Schritt 9: Chat Engine mit Gesprächsverlauf einrichten
Eine reine Query Engine vergisst nach jeder Anfrage den Kontext. Für einen Chatbot, der sich an vorherige Fragen erinnert, bietet LlamaIndex die Chat Engine mit eingebautem Gesprächsspeicher.
chat_engine = index.as_chat_engine(chat_mode="context")
antwort1 = chat_engine.chat("Worum geht es in den Dokumenten?")
print(antwort1)
antwort2 = chat_engine.chat("Kannst du das genauer erklären?")
print(antwort2)
Der Modus context sorgt dafür, dass bei jeder neuen Nachricht erneut in Qdrant gesucht wird, kombiniert mit dem bisherigen Gesprächsverlauf. Das verhindert, dass die Chat Engine bei langen Unterhaltungen den Bezug zu den Quelldokumenten verliert. Bei sehr langen Sitzungen wächst der Gesprächsverlauf mit jeder Nachricht weiter, weshalb sich für Produktionsanwendungen ein Limit für die Anzahl gespeicherter Nachrichten empfiehlt, um die Tokenkosten pro Anfrage nicht unnötig in die Höhe zu treiben.
Schritt 10: Metadatenfilter und Hybrid-Suche
Reine Vektorsuche liefert semantisch ähnliche Treffer, ignoriert aber strukturierte Kriterien wie Datum, Kategorie oder Autor. Genau hier zahlt sich Qdrant als eigenständige Datenbank aus, denn Metadatenfilter laufen direkt in der Datenbank statt nachträglich im Python-Code.
from llama_index.core.vector_stores import (
MetadataFilters,
ExactMatchFilter,
)
filters = MetadataFilters(
filters=[ExactMatchFilter(key="kategorie", value="handbuch")]
)
query_engine = index.as_query_engine(
filters=filters,
similarity_top_k=3
)
response = query_engine.query("Wie wird das Gerät zurückgesetzt?")
print(response)
Damit die Filterung funktioniert, müssen die Metadaten beim Einlesen der Dokumente gesetzt werden, zum Beispiel über den metadata-Parameter im Document-Objekt. Qdrants Filterlogik prüft diese Felder direkt beim Suchvorgang und schließt nicht passende Punkte vor der eigentlichen Ähnlichkeitssuche aus, was bei großen Collections spürbar Zeit spart.
Neben dem exakten Abgleich unterstützt Qdrant auch Bereichsfilter, etwa für Datumsangaben oder numerische Werte wie einen Preis oder eine Versionsnummer. Damit lässt sich zum Beispiel eine Suche auf Dokumente der letzten sechs Monate eingrenzen, ohne dass ältere, möglicherweise veraltete Inhalte in der Antwort auftauchen. Für eine noch feinere Steuerung lassen sich mehrere Filterbedingungen mit logischem Und oder Oder verknüpfen.
Schritt 11: Index persistieren und nach Neustart laden
Weil Qdrant die Vektoren serverseitig speichert, muss der Index beim nächsten Programmstart nicht neu berechnet werden. Es genügt, sich erneut mit derselben Collection zu verbinden.
from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.qdrant import QdrantVectorStore
import qdrant_client
client = qdrant_client.QdrantClient(host="localhost", port=6333)
vector_store = QdrantVectorStore(
client=client,
collection_name="dokumente_v1"
)
index = VectorStoreIndex.from_vector_store(vector_store)
query_engine = index.as_query_engine()
Dieser Ansatz spart bei jedem Neustart die komplette Embedding-Berechnung und damit auch API-Kosten, falls ein kostenpflichtiger Embedding-Dienst zum Einsatz kommt. Neue Dokumente lassen sich jederzeit über index.insert() nachträglich hinzufügen, ohne den bestehenden Index neu aufzubauen.
Schritt 12: Produktionsbetrieb, Monitoring und Skalierung
Der letzte Schritt bringt das Projekt von der lokalen Testumgebung in einen belastbaren Betrieb. Drei Punkte verdienen besondere Aufmerksamkeit: Beobachtbarkeit, Ressourcenplanung und Ausfallsicherheit.
Monitoring einrichten
Qdrant bringt unter /dashboard eine eingebaute Oberfläche mit, die Collection-Größe, Speichernutzung und Suchlatenzen anzeigt. Für den produktiven Einsatz lohnt sich zusätzlich ein Export der Qdrant-Metriken über den integrierten Prometheus-Endpunkt, damit sich Latenzspitzen in einem bestehenden Monitoring-Stack wie Grafana nachvollziehen lassen. Auf der Anwendungsseite lohnt es sich, jede Anfrage an die Query Engine zu protokollieren, inklusive der verwendeten Chunk-IDs. So lässt sich im Nachhinein nachvollziehen, welche Dokumente tatsächlich zu einer Antwort beigetragen haben, was besonders bei Rückfragen von Nutzenden zur Genauigkeit einer Antwort hilfreich ist.
Skalierung planen
Bei wachsenden Datenmengen lässt sich Qdrant über Sharding auf mehrere Knoten verteilen. Für die meisten mittelständischen Anwendungsfälle reicht allerdings eine vertikale Skalierung, also mehr Arbeitsspeicher und CPU-Kerne auf einer einzigen Instanz, bevor eine Cluster-Architektur nötig wird. Wer den Betrieb nicht selbst verwalten will, kann auf Qdrant Cloud ausweichen und spart sich damit Patch-Management und Backups.
Für Hochverfügbarkeit unterstützt Qdrant außerdem Replikation, bei der dieselben Daten auf mehreren Knoten vorgehalten werden. Fällt ein Knoten aus, übernehmen die verbleibenden Replikate die Anfragen, ohne dass die Anwendung selbst eine Umschaltlogik implementieren muss. Für die meisten Projekte mit einer überschaubaren Nutzerzahl ist das zunächst kein dringendes Thema, gewinnt aber an Bedeutung, sobald die RAG-Pipeline zu einem festen Bestandteil eines Kundenprodukts wird.
Datenschutz und DSGVO: Worauf Unternehmen in Deutschland achten müssen
Sobald personenbezogene Daten in Dokumenten stecken, etwa Kundenanfragen, Verträge oder interne Personalunterlagen, greift die DSGVO auch beim Aufbau einer RAG-Pipeline. Zwei Stellen im beschriebenen Setup verdienen deshalb besondere Aufmerksamkeit: die Embedding-API und der Ort, an dem Qdrant läuft.
Wo landen die Daten wirklich?
Wird OpenAI für Embeddings genutzt, verlassen die Rohtexte kurzzeitig das eigene Netzwerk und werden beim Anbieter verarbeitet. Für viele Anwendungsfälle mit öffentlichen oder unkritischen Dokumenten ist das unproblematisch, bei personenbezogenen oder vertraulichen Inhalten lohnt sich aber ein Blick in die Auftragsverarbeitungsvereinbarung des jeweiligen Anbieters, bevor produktive Daten eingebettet werden. Die in diesem Tutorial gezeigte lokale Alternative über Hugging-Face-Embeddings und ein per Ollama betriebenes Sprachmodell umgeht dieses Problem vollständig, weil dann keine Daten das eigene System verlassen. Für IT-Abteilungen, die eine Pipeline für den produktiven Einsatz freigeben müssen, ist diese Unterscheidung oft der entscheidende Punkt in der Sicherheitsprüfung, noch vor Fragen zu Performance oder Kosten.
Für Qdrant selbst gilt: Ein lokal per Docker betriebener Container speichert alle Vektoren und zugehörigen Metadaten ausschließlich auf der eigenen Festplatte. Wer stattdessen Qdrant Cloud nutzt, sollte in den Einstellungen gezielt eine Region innerhalb der EU wählen, um Datenübermittlungen in Drittstaaten zu vermeiden. Für Behörden und Unternehmen mit hohen Compliance-Anforderungen bleibt der selbst gehostete Betrieb auf eigener oder deutscher Cloud-Infrastruktur die konservativere Wahl.
Ein weiterer Aspekt betrifft Aufbewahrungsfristen. Wird ein Dokument im Quellsystem gelöscht, etwa weil ein Vertrag abgelaufen ist oder eine Person das Unternehmen verlassen hat, bleiben die zugehörigen Vektoren in Qdrant bestehen, bis sie aktiv entfernt werden. Für eine rechtskonforme Pipeline empfiehlt sich deshalb ein Löschprozess, der bei jeder Entfernung eines Quelldokuments auch die zugehörigen Punkte in der Qdrant-Collection über deren Dokument-ID löscht, statt Löschungen nur auf Dateisystemebene vorzunehmen.
Alternative Embedding-Modelle im Vergleich
Die Wahl des Embedding-Modells beeinflusst sowohl die Suchqualität als auch die Kosten und die Frage, ob Daten das eigene System verlassen. LlamaIndex erlaubt den Austausch über die globale Settings-Konfiguration, ohne dass sich am restlichen Code etwas ändert.
| Modell | Anbieter | Vektordimension | Läuft lokal |
|---|---|---|---|
| text-embedding-3-small | OpenAI | 1536 | Nein, API-basiert |
| all-MiniLM-L6-v2 | Sentence-Transformers | 384 | Ja, über Hugging Face |
| bge-large-en-v1.5 | BAAI | 1024 | Ja, über Hugging Face |
| nomic-embed-text | Nomic AI | 768 | Ja, über Ollama |
Ein Wechsel des Embedding-Modells verändert fast immer die Vektordimension. Genau deshalb taucht dieser Punkt auch in den Stolpersteinen weiter unten auf: Wird eine bestehende Qdrant-Collection mit einem neuen Modell weiterbefüllt, das eine andere Dimension liefert, meldet die Datenbank einen Dimensionskonflikt. Der sichere Weg führt über eine neue, klar benannte Collection, sobald ein anderes Embedding-Modell zum Einsatz kommt.
Das komplette Projekt im Überblick
Alle bisherigen Schritte lassen sich in zwei Dateien bündeln: ein Ingest-Skript, das Dokumente einliest und in Qdrant schreibt, und ein Query-Skript, das bei jedem Start nur noch Anfragen stellt.
# ingest.py
from dotenv import load_dotenv
load_dotenv()
import qdrant_client
from llama_index.core import (
SimpleDirectoryReader,
VectorStoreIndex,
StorageContext,
Settings,
)
from llama_index.vector_stores.qdrant import QdrantVectorStore
Settings.chunk_size = 512
Settings.chunk_overlap = 50
client = qdrant_client.QdrantClient(host="localhost", port=6333)
vector_store = QdrantVectorStore(client=client, collection_name="dokumente_v1")
storage_context = StorageContext.from_defaults(vector_store=vector_store)
documents = SimpleDirectoryReader("./daten").load_data()
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
print(f"{len(documents)} Dokumente indexiert in Collection 'dokumente_v1'")
# query.py
from dotenv import load_dotenv
load_dotenv()
import qdrant_client
from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.qdrant import QdrantVectorStore
client = qdrant_client.QdrantClient(host="localhost", port=6333)
vector_store = QdrantVectorStore(client=client, collection_name="dokumente_v1")
index = VectorStoreIndex.from_vector_store(vector_store)
chat_engine = index.as_chat_engine(chat_mode="context")
while True:
frage = input("Frage (oder 'exit'): ")
if frage.lower() == "exit":
break
antwort = chat_engine.chat(frage)
print(antwort)
Die Ordnerstruktur sieht am Ende so aus: llamaindex-qdrant-projekt mit den Unterordnern daten und qdrant_storage sowie den Dateien .env, ingest.py, query.py und requirements.txt. Der Befehl python ingest.py läuft einmalig, python query.py startet danach beliebig oft die interaktive Chat-Schleife.
Wer das Projekt unter Versionskontrolle stellt, sollte unbedingt eine .gitignore-Datei mit den Einträgen venv, .env und qdrant_storage anlegen. Damit landen weder der API-Key noch die lokal gespeicherten Vektordaten versehentlich in einem öffentlichen Repository, was direkt an den zuvor genannten Stolperstein zum hartcodierten API-Key anknüpft. Für ein Team-Setup lässt sich der Qdrant-Container zusätzlich über eine docker-compose.yml neben weiteren Diensten wie einer Weboberfläche oder einem Backend-Server verwalten, sodass ein einziger Befehl die komplette Umgebung hochfährt.
Fünf häufige Stolpersteine beim Einstieg
Die meisten Probleme beim Einstieg entstehen nicht durch komplizierten Code, sondern durch kleine Inkonsistenzen zwischen Ingest- und Query-Seite oder durch übersehene Konfigurationsdetails. Die folgende Liste sammelt die Fehler, die in Foren und Issue-Trackern rund um LlamaIndex und Qdrant am häufigsten auftauchen.
- Falsche Python-Version: LlamaIndex 0.14.25 verlangt mindestens Python 3.10. Unter älteren Versionen bricht die Installation mit einer Abhängigkeitswarnung ab.
- Collection-Namen wiederverwenden: Wird dieselbe Collection nach einem Wechsel des Embedding-Modells weiterverwendet, mischen sich Vektoren unterschiedlicher Dimension in einer Sammlung.
- Chunk-Größe falsch gewählt: Zu kleine Chunks zerreißen Kontext, zu große verwässern die Relevanz einzelner Treffer bei der Ähnlichkeitssuche.
- API-Key im Quellcode hartcodiert: Landet der Schlüssel versehentlich in einem Git-Repository, ist er faktisch öffentlich, sobald das Repository gepusht wird.
- Fehlendes Docker-Volume: Ohne gemountetes Verzeichnis verliert der Qdrant-Container beim nächsten Neustart sämtliche gespeicherten Vektoren.
- Kein Reranking bei großen Datenmengen: Reine Vektorsuche ohne zusätzliches Reranking liefert bei mehreren Zehntausend Chunks oft ungenaue Top-Treffer.
- Blockierende Ingestion: Wer Tausende Dokumente ohne Batching einliest, riskiert Timeouts und unnötig hohe Kosten bei API-basierten Embeddings.
Die meisten dieser Fehler lassen sich vermeiden, indem Ingest- und Query-Skript dieselbe Konfiguration für Chunk-Größe, Embedding-Modell und Collection-Namen referenzieren, statt Werte an mehreren Stellen im Code zu duplizieren. Eine zentrale Konfigurationsdatei oder gemeinsame Settings-Instanz, wie in den Codebeispielen oben verwendet, reduziert dieses Risiko erheblich.
Fehlerbehebung: Die häufigsten Probleme und Lösungen
Selbst bei sorgfältigem Vorgehen tauchen im Betrieb gelegentlich Fehlermeldungen auf, die auf den ersten Blick kryptisch wirken. Die folgende Tabelle ordnet die häufigsten Fehlerbilder ihrer wahrscheinlichsten Ursache zu und nennt jeweils den schnellsten Weg zur Lösung, ohne den kompletten Aufbau neu starten zu müssen.
| Fehler | Ursache | Lösung |
|---|---|---|
| ConnectionRefusedError beim Verbinden | Qdrant-Container läuft nicht oder falscher Port | Mit docker ps prüfen, ob der Container aktiv ist, Ports 6333/6334 kontrollieren |
| ImportError: llama_index.vector_stores.qdrant fehlt | Integrationspaket nicht separat installiert | pip install llama-index-vector-stores-qdrant nachholen |
| openai.AuthenticationError | Fehlender oder ungültiger API-Key | .env-Datei prüfen und load_dotenv() vor jedem API-Aufruf sicherstellen |
| ValueError: Vector dimension mismatch | Embedding-Modell zwischen Ingest und Abfrage unterscheidet sich | Gleiches Embedding-Modell für Ingest und Query fest in Settings hinterlegen |
| Collection existiert bereits mit falscher Dimension | Alte Collection aus einem früheren Testlauf | Collection über das Qdrant-Dashboard löschen und Index neu aufbauen |
| Sehr langsame Antwortzeiten | Zu hoher similarity_top_k-Wert oder fehlender Metadatenindex | top_k reduzieren und Payload-Index für häufig gefilterte Felder anlegen |
| Leere oder generische Antworten | Chunk-Größe unpassend oder Dokumente nicht korrekt geparst | Chunk-Größe anpassen und geladene Dokumente vor dem Indexieren manuell prüfen |
| Hoher Speicherverbrauch bei der Ingestion | Alle Dokumente werden gleichzeitig geladen und eingebettet | Batch-Ingestion in Gruppen von 50 bis 100 Dokumenten durchführen |
| SSL-Zertifikatsfehler bei Qdrant Cloud | Fehlendes https-Flag im QdrantClient | QdrantClient mit url und https=True statt host/port aufrufen |
| Rate-Limit-Fehler der Embedding-API | Zu viele parallele Anfragen ohne Drosselung | Batching aktivieren und Retry-Logik mit exponentiellem Backoff einbauen |
Kosten realistisch einschätzen: Was treibt die Rechnung nach oben?
Die Software selbst kostet nichts, denn sowohl LlamaIndex als auch Qdrant sind Open Source. Kosten entstehen an zwei anderen Stellen: bei der Embedding-Berechnung und bei der Texterzeugung durch das Sprachmodell, sofern beides über eine externe API läuft. Beide Anbieter rechnen üblicherweise nach verbrauchten Tokens ab, weshalb die tatsächliche Rechnung stark von der Dokumentenmenge, der gewählten Chunk-Größe und der Zahl der gestellten Fragen abhängt. Wer die genauen Preise für ein bestimmtes Modell prüfen will, findet die aktuellen Tarife direkt auf der Preisseite des jeweiligen Anbieters, da sich diese Werte im Lauf der Zeit ändern.
Der Betrieb von Qdrant selbst verursacht beim lokalen Docker-Setup keine laufenden Kosten außer Strom und Hardware-Abschreibung. Bei Qdrant Cloud richtet sich der Preis nach Speichervolumen und Rechenleistung der gebuchten Instanz. Für Teams, die zunächst experimentieren wollen, ist der lokale Docker-Betrieb aus Kostensicht der naheliegende Startpunkt, ein Umzug in die Cloud lässt sich später jederzeit nachholen, da der Code bis auf die Verbindungsdaten unverändert bleibt.
Die größte Stellschraube bleibt in der Praxis die Häufigkeit der Neu-Indexierung. Wird bei jeder kleinen Dokumentänderung der gesamte Bestand neu eingebettet, steigen die Kosten proportional zur Gesamtgröße der Sammlung statt nur zur Größe der Änderung. Der in Schritt 11 beschriebene Ansatz, nur veränderte Dokumente erneut zu verarbeiten, wirkt sich deshalb nicht nur auf die Laufzeit aus, sondern direkt auf die monatliche Rechnung bei API-basierten Embeddings.
Profi-Tipps für den produktiven Einsatz
Wer über das reine Tutorial hinaus produktiv mit LlamaIndex und Qdrant arbeiten will, profitiert von ein paar zusätzlichen Kniffen. Hybrid-Suche kombiniert dichte Vektor-Embeddings mit klassischer Keyword-Suche und verbessert die Trefferqualität besonders bei Fachbegriffen und Eigennamen, die rein semantische Suche gelegentlich übersieht. Qdrant unterstützt das über Sparse Vectors, die sich zusammen mit den regulären Embeddings in derselben Collection speichern lassen.
Für Teams mit begrenztem API-Budget lohnt sich ein Wechsel zu lokalen Embedding-Modellen über Hugging Face, kombiniert mit einem lokal laufenden LLM über Ollama. Das eliminiert externe API-Kosten vollständig, verlangt im Gegenzug aber mehr Rechenleistung auf der eigenen Hardware. Ein Reranking-Schritt mit einem Cross-Encoder-Modell nach der ersten Vektorsuche verbessert außerdem die Präzision der Top-Treffer, bevor sie an das Sprachmodell weitergereicht werden. Schließlich zahlt sich Batch-Ingestion bei großen Dokumentenmengen aus. Statt jedes Dokument einzeln einzubetten, verarbeitet man Gruppen von 50 bis 100 Dokumenten parallel und reduziert damit sowohl Latenz als auch Fehleranfälligkeit bei Netzwerkproblemen.
Ein weiterer Punkt betrifft das Aktualisieren bestehender Dokumente. Ändert sich eine Quelldatei, sollte nicht der komplette Index neu aufgebaut werden. LlamaIndex bietet dafür RefreshRef-Mechanismen, die einzelne Dokumente anhand ihrer ID erkennen und nur die veränderten Chunks neu einbetten. Das spart bei großen, sich regelmäßig ändernden Wissensdatenbanken erheblich Zeit und API-Kosten gegenüber einem kompletten Neuaufbau bei jeder kleinen Änderung.
LlamaIndex vs. LangChain: Welches Framework passt wann?
Beide Frameworks lösen ähnliche Probleme, setzen aber unterschiedliche Schwerpunkte. LangChain, das die Redaktion in einem separaten Tutorial bereits behandelt hat, bringt mit rund 146.000 GitHub-Sternen eine deutlich breitere Ökosystem-Anbindung mit und eignet sich besonders für komplexe Multi-Agenten-Workflows, wie sie auch in der LangGraph-Anleitung beschrieben werden. LlamaIndex mit seinen 52.400 Sternen ist dagegen stärker auf Datenverarbeitung und Retrieval spezialisiert und bietet dafür schlankere Abstraktionen rund um Indizes und Query Engines.
| Kriterium | LlamaIndex | LangChain |
|---|---|---|
| GitHub-Sterne (Stand 30.09.2026) | ca. 52.400 | ca. 146.000 |
| Schwerpunkt | Datenverarbeitung und Retrieval | Breite Orchestrierung und Agenten |
| Einstiegskurve | Flach für reine RAG-Anwendungen | Steiler, mehr Konzepte gleichzeitig |
| Qdrant-Integration | Direkt über llama-index-vector-stores-qdrant | Über langchain-qdrant Paket |
| Typischer Einsatz | Dokumenten-Chatbots, Wissenssuche | Komplexe Agenten-Pipelines, Tool-Ketten |
Für reine Frage-Antwort-Systeme über eigene Dokumente, wie in diesem Tutorial gezeigt, ist LlamaIndex meist der schnellere Weg zum Ergebnis. Sobald ein Projekt mehrere Werkzeuge, externe APIs und mehrstufige Entscheidungslogik verknüpfen muss, gewinnt LangChain durch seine breitere Toolchain an Vorteil. Wer bereits einen MCP-Server betreibt, kann diesen unabhängig vom gewählten Framework als zusätzliche Werkzeugquelle einbinden. Und wer stattdessen komplett auf ein generisches RAG-Setup ohne Framework setzen will, findet in der RAG-Pipeline-Anleitung der Redaktion einen Vergleichspunkt ohne LlamaIndex oder LangChain.
In der Praxis schließen sich beide Ansätze nicht aus. Manche Teams nutzen LlamaIndex ausschließlich für die Retrieval-Schicht, also das Laden, Indexieren und Durchsuchen von Dokumenten, und reichen die gefundenen Chunks anschließend an eine in LangChain gebaute Agenten-Logik weiter, die zusätzlich auf externe Tools wie Kalender, E-Mail-Versand oder interne APIs zugreift. Wer noch unsicher ist, sollte mit dem in diesem Tutorial gezeigten LlamaIndex-Setup starten und erst bei tatsächlichem Bedarf an komplexerer Orchestrierung zu LangChain oder LangGraph wechseln, statt von Beginn an die aufwendigere Lösung zu wählen.
Wer die zwölf Schritte dieses Tutorials der Reihe nach durchgeht, hat am Ende mehr als nur ein Testskript: eine wiederverwendbare Grundlage, die sich um zusätzliche Datenquellen, Metadatenfelder oder ein zweites Sprachmodell erweitern lässt, ohne die grundlegende Architektur zu verändern. Der größte Hebel für bessere Ergebnisse liegt dabei selten im Code selbst, sondern in der Qualität der eingelesenen Dokumente und einer sinnvoll gewählten Chunk-Größe. Beides lässt sich iterativ verbessern, sobald die Pipeline einmal läuft und erste echte Fragen gegen sie gestellt werden.
Häufig gestellte Fragen
Ist LlamaIndex kostenlos?
Ja, das Framework selbst steht unter einer Open-Source-Lizenz auf GitHub und kostet nichts. Kosten entstehen ausschließlich durch die verwendeten Embedding- und LLM-APIs, sofern nicht auf lokale Modelle über Ollama oder Hugging Face ausgewichen wird. Auch Qdrant lässt sich vollständig kostenfrei selbst hosten, lediglich der verwaltete Cloud-Dienst Qdrant Cloud verlangt eine Gebühr für Speicher und Rechenleistung.
Brauche ich zwingend einen OpenAI-API-Key?
Nein. LlamaIndex nutzt OpenAI standardmäßig, lässt sich aber problemlos auf andere Anbieter oder komplett lokale Modelle umstellen. Für den kompletten Offline-Betrieb eignen sich lokale Embeddings über Hugging Face in Kombination mit einem über Ollama betriebenen Sprachmodell, wie in der Ollama-Anleitung der Redaktion beschrieben.
Kann ich Qdrant ohne Docker nutzen?
Ja. Qdrant lässt sich als eigenständige Binary kompilieren oder als verwalteter Cloud-Dienst über Qdrant Cloud buchen. Docker bleibt aber für lokale Entwicklung und Tests der einfachste Weg, weil kein manuelles Kompilieren nötig ist.
Was ist der Unterschied zwischen LlamaIndex und LangChain?
LlamaIndex konzentriert sich stärker auf Datenverarbeitung und Retrieval, LangChain deckt ein breiteres Spektrum an Orchestrierungs- und Agenten-Funktionen ab. Beide lassen sich sogar kombinieren, etwa LlamaIndex als Retrieval-Schicht innerhalb einer größeren LangChain-Pipeline.
Wie viele Dokumente verkraftet Qdrant?
Qdrant ist für Sammlungen mit mehreren Millionen Vektoren ausgelegt und skaliert über Sharding auf mehrere Knoten. Für die meisten Projekte mit einigen Tausend bis Hunderttausend Dokumenten reicht eine einzelne Instanz mit ausreichend Arbeitsspeicher völlig aus. Wächst die Sammlung deutlich darüber hinaus, lässt sich die Collection ohne Codeänderung auf mehrere Shards verteilen, solange der Client weiterhin dieselbe Collection anspricht.
Läuft das Ganze auch komplett offline?
Ja, sofern sowohl Embeddings als auch das Sprachmodell lokal laufen. Qdrant selbst läuft ohnehin lokal im Docker-Container, sodass nur die Modellwahl über offline oder cloudbasiert entscheidet.
Wie sicher sind meine Daten in Qdrant?
Beim lokalen Betrieb per Docker verlassen die Daten den eigenen Rechner oder Server nicht. Bei Nutzung von Qdrant Cloud gelten die Sicherheitsmaßnahmen des jeweiligen Anbieters, weshalb sich für sensible Daten ein Blick in dessen Dokumentation zu Verschlüsselung und Zugriffskontrolle lohnt. Zusätzlich lässt sich der Zugriff auf eine selbst gehostete Qdrant-Instanz über einen API-Key und eine Firewall-Regel absichern, damit die Datenbank nicht offen im Netz erreichbar ist.
Welche Python-Version brauche ich mindestens?
LlamaIndex 0.14.25 setzt laut den offiziellen PyPI-Metadaten mindestens Python 3.10 voraus, bei einer Obergrenze unter Python 4.0. Der qdrant-client kommt bereits mit Python 3.8 zurecht, in der Praxis empfiehlt sich aber eine einheitliche Umgebung ab Version 3.10.




