> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-de/rag-and-vektordatenbanken/qdrant.md).

# Qdrant

> **Hochleistungsfähige Vektordatenbank für semantische Suche und RAG-Anwendungen — GPU-beschleunigte Indexierung**

Qdrant ist eine quelloffene, produktionsreife Vektordatenbank, geschrieben in Rust. Sie liefert schnelle, approximative Suche nach den nächsten Nachbarn (ANN) über Milliarden von Vektoren hinweg mit fortschrittlichem Filtern, Payload-Indexierung und Unterstützung für Multi-Vektoren. Sie ist das Rückgrat vieler Produktions-Pipelines für RAG (Retrieval-Augmented Generation) und semantischer Suchanwendungen.

**GitHub:** [qdrant/qdrant](https://github.com/qdrant/qdrant) — 22K+ ⭐

***

## Warum Qdrant?

| Funktion                  | Qdrant      | Pinecone      | Weaviate | Chroma        |
| ------------------------- | ----------- | ------------- | -------- | ------------- |
| Open Source               | ✅           | ❌             | ✅        | ✅             |
| Rust-Performance          | ✅           | —             | ❌ Go     | ❌ Python      |
| Filtern zur Abfragezeit   | ✅ Erweitert | ✅ Grundlegend | ✅        | ✅ Grundlegend |
| Mehrvektor                | ✅           | ❌             | ✅        | ❌             |
| HNSW auf Festplattenbasis | ✅           | ✅             | ✅        | ❌             |
| Payload-Indexierung       | ✅           | Begrenzt      | ✅        | Begrenzt      |
| gRPC + REST               | ✅ Beides    | ✅ REST        | ✅        | REST          |
| Selbst gehostet           | ✅           | ❌ Nur Cloud   | ✅        | ✅             |

{% hint style="success" %}
**Qdrant ist in Rust geschrieben** — und liefert C-Niveau-Performance bei Speichersicherheit. Benchmark-Tests zeigen, dass Qdrant durchgehend **1,5–3x schneller** als Python-basierte Alternativen wie Chroma in Hochlastszenarien.
{% endhint %}

***

## Wichtige Anwendungsfälle

* **RAG (Retrieval-Augmented Generation)** — relevanten Kontext für LLM-Prompts finden
* **Semantische Suche** — nach Bedeutung suchen, nicht nur nach Stichwörtern
* **Empfehlungssysteme** — ähnliche Elemente anhand der Embedding-Ähnlichkeit finden
* **Duplikaterkennung** — nahezu doppelte Inhalte identifizieren
* **Anomalieerkennung** — Vektoren finden, die weit von Clusterzentren entfernt sind
* **Bild-/Audio-Ähnlichkeitssuche** — multimodales Retrieval

***

## Voraussetzungen

* Clore.ai-Konto mit GPU-Miete
* Grundlegende Vertrautheit mit REST-APIs oder Python
* Dein Embedding-Modell deiner Wahl (OpenAI, SentenceTransformers usw.)

***

## Schritt 1 — Einen Server auf Clore.ai mieten

Qdrant ist für das Bereitstellen hauptsächlich durch CPU/RAM begrenzt, profitiert aber von GPU, wenn:

* Embeddings zusammen mit dem Serving generiert werden (Embedding-Modell auf demselben Server)
* Batch-Indexierungsoperationen im großen Maßstab

1. Gehe zu [clore.ai](https://clore.ai) → **Marktplatz**
2. Für **Kombination aus Embeddings + Serving:** RTX 3090/4090 mit 32 GB+ RAM
3. Für **nur Serving:** CPU-optimierter Server mit schnellem NVMe-Speicher

{% hint style="info" %}
**Speicherplanung:**

* Jeder float32-Vektor mit 1536 Dimensionen = 6 KB
* 1 Million Vektoren = \~6 GB RAM
* 10 Millionen Vektoren = \~60 GB RAM
* Aktiviere On-Disk-Speicher für sehr große Collections
  {% endhint %}

***

## Schritt 2 — Qdrant-Container bereitstellen

**Docker-Image:**

```
qdrant/qdrant:latest
```

**Ports:**

```
22
6333
6334
```

* **Port 6333:** REST-API (HTTP)
* **Port 6334:** gRPC-API (höhere Leistung für Massenoperationen)

**Umgebungsvariablen:**

```
QDRANT__SERVICE__HTTP_PORT=6333
QDRANT__SERVICE__GRPC_PORT=6334
QDRANT__LOG_LEVEL=INFO
QDRANT__STORAGE__STORAGE_PATH=/qdrant/storage
```

**Volume/Persistenter Speicher:** Einbinden `/qdrant/storage` für die Datenpersistenz. Ohne dies gehen die Daten beim Neustart des Containers verloren.

***

## Schritt 3 — Überprüfen, ob Qdrant läuft

```bash
ssh root@<server-ip> -p <ssh-port>

# Prüfen, ob Qdrant läuft
curl http://localhost:6333/

# Erwartete Antwort:
# {"title":"qdrant - Vektorsuchmaschine","version":"..."}

# Status prüfen
curl http://localhost:6333/healthz

# Cluster-Info prüfen
curl http://localhost:6333/cluster
```

***

## Schritt 4 — Python-Client installieren

```bash
# Qdrant-Python-Client und Embedding-Tools installieren
pip install qdrant-client sentence-transformers openai numpy

# Verbindung überprüfen
python3 << 'EOF'
from qdrant_client import QdrantClient

client = QdrantClient("localhost", port=6333)
print(f"Qdrant verbunden: {client.get_collections()}")
EOF
```

***

## Schritt 5 — Eine Collection erstellen

Eine Collection ist eine benannte Gruppe von Vektoren mit fester Dimensionalität.

```python
from qdrant_client import QdrantClient
from qdrant_client.models import (
    Distance,
    VectorParams,
    HnswConfigDiff,
    OptimizersConfigDiff,
    QuantizationConfig,
    ScalarQuantizationConfig,
    ScalarType
)

client = QdrantClient("localhost", port=6333)

# Collection für OpenAI text-embedding-3-small erstellen (1536 Dimensionen)
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(
        size=1536,           # Vektordimension (muss zu deinem Embedding-Modell passen)
        distance=Distance.COSINE,  # Optionen: COSINE, EUCLID, DOT
        on_disk=False        # Auf True setzen für sehr große Collections
    ),
    hnsw_config=HnswConfigDiff(
        m=16,                # HNSW-Graph-Konnektivität (höher = besserer Recall, mehr RAM)
        ef_construct=100,    # Tiefe der Suche zur Build-Zeit (höher = bessere Qualität, langsamere Indexierung)
        full_scan_threshold=10000  # Brute-Force unterhalb dieser Anzahl verwenden
    ),
    optimizers_config=OptimizersConfigDiff(
        indexing_threshold=20000  # HNSW-Indexierung nach so vielen Vektoren starten
    ),
    quantization_config=QuantizationConfig(
        scalar=ScalarQuantizationConfig(
            type=ScalarType.INT8,  # Vektoren auf INT8 komprimieren (4-fache Speicherreduktion)
            quantile=0.99,
            always_ram=True        # Quantisierten Index im RAM halten
        )
    )
)

print("Collection erstellt!")
print(client.get_collection("documents"))
```

### Collection für SentenceTransformers (384 Dimensionen)

```python
client.create_collection(
    collection_name="embeddings_384",
    vectors_config=VectorParams(
        size=384,              # Ausgabengröße von all-MiniLM-L6-v2
        distance=Distance.COSINE
    )
)
```

***

## Schritt 6 — Dokumente indexieren

### Mit OpenAI-Embeddings

```python
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct
from openai import OpenAI
import uuid

client = QdrantClient("localhost", port=6333)
openai_client = OpenAI(api_key="your-openai-api-key")

def get_embeddings(texts: list[str], batch_size: int = 100) -> list[list[float]]:
    """Embeddings in Batches generieren."""
    all_embeddings = []
    for i in range(0, len(texts), batch_size):
        batch = texts[i:i + batch_size]
        response = openai_client.embeddings.create(
            model="text-embedding-3-small",
            input=batch
        )
        all_embeddings.extend([e.embedding for e in response.data])
    return all_embeddings

# Beispieldokumente
documents = [
    {
        "id": str(uuid.uuid4()),
        "text": "Qdrant ist eine Vektordatenbank, die in Rust für hohe Leistung entwickelt wurde.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "id": str(uuid.uuid4()),
        "text": "Maschinelle Lernmodelle wandeln Text in dichte Vektorrepräsentationen um.",
        "source": "article",
        "category": "ml",
        "year": 2023
    },
    # Weitere Dokumente hinzufügen...
]

# Embeddings generieren
texts = [doc["text"] for doc in documents]
embeddings = get_embeddings(texts)

# In Qdrant einfügen
points = [
    PointStruct(
        id=str(uuid.uuid4()),
        vector=embedding,
        payload={
            "text": doc["text"],
            "source": doc["source"],
            "category": doc["category"],
            "year": doc["year"]
        }
    )
    for doc, embedding in zip(documents, embeddings)
]

client.upsert(
    collection_name="documents",
    points=points,
    wait=True  # Auf Abschluss der Indexierung warten
)

print(f"{len(points)} Dokumente indexiert!")
```

### Mit SentenceTransformers (lokal, GPU-beschleunigt)

```python
from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct
import torch
import uuid

# Embedding-Modell auf der GPU laden
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

client = QdrantClient("localhost", port=6333)

documents = [
    {"text": "Wie richte ich Qdrant auf einem GPU-Server ein?", "tag": "setup"},
    {"text": "Vektordatenbanken speichern hochdimensionale Embeddings für die Ähnlichkeitssuche.", "tag": "concept"},
    {"text": "Der HNSW-Algorithmus ermöglicht eine approximative Suche nach den nächsten Nachbarn.", "tag": "algorithm"},
    # ... weitere Dokumente
]

# GPU-beschleunigte Batch-Codierung
texts = [doc["text"] for doc in documents]
embeddings = model.encode(
    texts,
    batch_size=256,       # Große Batch-Größe für GPU-Effizienz
    show_progress_bar=True,
    normalize_embeddings=True  # Für Kosinus-Ähnlichkeit normalisieren
)

# In Qdrant indexieren
points = [
    PointStruct(
        id=str(uuid.uuid4()),
        vector=embedding.tolist(),
        payload=doc
    )
    for doc, embedding in zip(documents, embeddings)
]

# Batch-Upsert (effizienter)
BATCH_SIZE = 1000
for i in range(0, len(points), BATCH_SIZE):
    batch = points[i:i + BATCH_SIZE]
    client.upsert(collection_name="embeddings_384", points=batch)
    print(f"Indexed {min(i + BATCH_SIZE, len(points))}/{len(points)}")
```

***

## Schritt 7 — Suchen und Abfragen

### Einfache semantische Suche

```python
from qdrant_client import QdrantClient
from sentence_transformers import SentenceTransformer

client = QdrantClient("localhost", port=6333)
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

def search(query: str, limit: int = 5, collection: str = "embeddings_384"):
    # Abfrage-Embedding generieren
    query_vector = model.encode(query, normalize_embeddings=True).tolist()
    
    # Suchen
    results = client.search(
        collection_name=collection,
        query_vector=query_vector,
        limit=limit,
        with_payload=True,
        with_vectors=False    # Keine Vektoren zurückgeben (spart Bandbreite)
    )
    
    return results

# Suche testen
results = search("Leistung von Vektordatenbanken")
for r in results:
    print(f"Score: {r.score:.4f} | {r.payload['text'][:100]}")
```

### Gefilterte Suche (Metadaten + Vektor)

```python
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range

# Mit Metadatenfiltern suchen
results = client.search(
    collection_name="documents",
    query_vector=query_vector,
    query_filter=Filter(
        must=[
            FieldCondition(
                key="category",
                match=MatchValue(value="database")
            ),
            FieldCondition(
                key="year",
                range=Range(gte=2023)  # Jahr >= 2023
            )
        ]
    ),
    limit=10,
    with_payload=True
)
```

### Batch-/Multi-Abfrage-Suche

```python
from qdrant_client.models import SearchRequest

queries = [
    "wie man eine Vektordatenbank installiert",
    "Optimierung der Inferenz im maschinellen Lernen",
    "RAG-Pipeline-Architektur"
]

query_vectors = model.encode(queries, normalize_embeddings=True)

# Batch-Suche (ein API-Aufruf für alle Abfragen)
results = client.search_batch(
    collection_name="embeddings_384",
    requests=[
        SearchRequest(
            vector=vec.tolist(),
            limit=5,
            with_payload=True
        )
        for vec in query_vectors
    ]
)

for query, res in zip(queries, results):
    print(f"\nAbfrage: {query}")
    for r in res:
        print(f"  {r.score:.3f}: {r.payload['text'][:80]}")
```

***

## Schritt 8 — Eine RAG-Pipeline aufbauen

```python
from qdrant_client import QdrantClient
from sentence_transformers import SentenceTransformer
from openai import OpenAI

# Clients initialisieren
qdrant = QdrantClient("localhost", port=6333)
embedder = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")
llm = OpenAI(api_key="your-openai-key")

def rag_query(question: str, n_context: int = 5) -> str:
    # Schritt 1: Die Frage einbetten
    query_vector = embedder.encode(question, normalize_embeddings=True).tolist()
    
    # Schritt 2: Relevanten Kontext aus Qdrant abrufen
    search_results = qdrant.search(
        collection_name="documents",
        query_vector=query_vector,
        limit=n_context,
        with_payload=True
    )
    
    # Schritt 3: Kontext-String erstellen
    context = "\n\n".join([
        f"[Quelle: {r.payload.get('source', 'unknown')}]\n{r.payload['text']}"
        for r in search_results
        if r.score > 0.5  # Ergebnisse mit geringer Sicherheit filtern
    ])
    
    # Schritt 4: Antwort mit dem LLM generieren
    response = llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "Beantworte Fragen auf Basis des bereitgestellten Kontexts. Sei prägnant und präzise."
            },
            {
                "role": "user",
                "content": f"Kontext:\n{context}\n\nFrage: {question}"
            }
        ],
        temperature=0.1
    )
    
    return response.choices[0].message.content

# RAG-Pipeline testen
answer = rag_query("Was ist Qdrant und wie funktioniert es?")
print(answer)
```

***

## Schritt 9 — Collections überwachen und verwalten

```python
# Collection-Statistiken
info = client.get_collection("documents")
print(f"Vektoranzahl: {info.vectors_count:,}")
print(f"Punktanzahl: {info.points_count:,}")
print(f"Indexierte Vektoren: {info.indexed_vectors_count:,}")
print(f"Status: {info.status}")
print(f"Festplattennutzung: {info.disk_data_size / 1024 / 1024:.1f} MB")

# Alle Collections auflisten
collections = client.get_collections()
for c in collections.collections:
    print(f" - {c.name}")

# Punkte nach Filter löschen
client.delete(
    collection_name="documents",
    points_selector=Filter(
        must=[FieldCondition(key="source", match=MatchValue(value="old_source"))]
    )
)

# Collection optimieren (Indexaufbau erzwingen)
client.update_collection(
    collection_name="documents",
    optimizer_config=OptimizersConfigDiff(indexing_threshold=0)  # Sofortige Indexierung erzwingen
)
```

***

## Fehlerbehebung

### Verbindung verweigert

```bash
# Prüfen, ob Qdrant läuft
docker ps | grep qdrant
# Oder den Prozess prüfen
ps aux | grep qdrant

# Prüfen, ob die Ports offen sind
curl http://localhost:6333/
netstat -tlnp | grep 6333
```

### Langsame Suchleistung

```python
# HNSW-Parameter für besseren Recall optimieren
client.update_collection(
    collection_name="documents",
    hnsw_config=HnswConfigDiff(ef=128)  # ef zur Suchzeit erhöhen (Standard 100)
)

# INT8-Quantisierung verwenden, um mehr Vektoren in den RAM zu bekommen
```

### Hohe Speicherauslastung

```python
# On-Disk-Speicher für große Collections aktivieren
client.create_collection(
    collection_name="large_collection",
    vectors_config=VectorParams(
        size=1536,
        distance=Distance.COSINE,
        on_disk=True  # Vektoren auf der Festplatte statt im RAM speichern
    )
)
```

***

## Kurzübersicht der REST-API

```bash
# Collections auflisten
curl http://localhost:6333/collections

# Collection erstellen
curl -X PUT http://localhost:6333/collections/my_collection \\
    -H "Content-Type: application/json" \\
    -d '{"vectors": {"size": 384, "distance": "Cosine"}}'

# Punkte zählen
curl http://localhost:6333/collections/my_collection/points/count

# Suchen
curl -X POST http://localhost:6333/collections/my_collection/points/search \\
    -H "Content-Type: application/json" \\
    -d '{
        "vector": [0.1, 0.2, ...],
        "limit": 5,
        "with_payload": true
    }'

# Sammlung löschen
curl -X DELETE http://localhost:6333/collections/my_collection
```

***

## Kostenschätzung auf Clore.ai

| Einrichtung    | Server              | Monatliche Kosten | Kapazität          |
| -------------- | ------------------- | ----------------- | ------------------ |
| Kleines RAG    | RTX 3090, 32 GB RAM | \~60–80 $         | \~5 Mio. Vektoren  |
| Mittlere Suche | RTX 4090, 64 GB RAM | \~120–150 $       | \~15 Mio. Vektoren |
| Großer Maßstab | A100, 128 GB RAM    | \~250–350 $       | \~30 Mio. Vektoren |

***

## Zusätzliche Ressourcen

* [Qdrant-Dokumentation](https://qdrant.tech/documentation/)
* [Qdrant GitHub](https://github.com/qdrant/qdrant)
* [Qdrant Python-Client](https://github.com/qdrant/qdrant-client)
* [Qdrant-Beispiele](https://github.com/qdrant/examples)
* [Benchmarks für Vektordatenbanken](https://qdrant.tech/benchmarks/)
* [Sentence Transformers](https://www.sbert.net/)

***

*Qdrant auf Clore.ai bietet Ihnen eine selbst gehostete, leistungsstarke Vektordatenbank ohne die pro Abfrage anfallenden Kosten von Pinecone oder Weaviate Cloud. Perfekt für RAG-Pipelines, die Millionen von Dokumenten verarbeiten.*

***

## GPU-Empfehlungen für Clore.ai

| Anwendungsfall                   | Empfohlene GPU   | Geschätzte Kosten bei Clore.ai |
| -------------------------------- | ---------------- | ------------------------------ |
| Entwicklung/Testen               | RTX 3090 (24 GB) | 0,07–0,21 $/GPU/Stunde         |
| Produktionsrecherche in Vektoren | RTX 3090 (24 GB) | 0,07–0,21 $/GPU/Stunde         |
| Embedding mit hohem Durchsatz    | RTX 4090 (24 GB) | 0,14–0,42 $/GPU/Stunde         |

> 💡 Alle Beispiele in diesem Leitfaden können bereitgestellt werden auf [Clore.ai](https://clore.ai/marketplace) GPU-Servern. Durchsuchen Sie verfügbare GPUs und mieten Sie stundenweise — keine Verpflichtungen, voller Root-Zugriff.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-de/rag-and-vektordatenbanken/qdrant.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
