> 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-fr/rag-et-bases-de-donnees-vectorielles/qdrant.md).

# Qdrant

> **Base de données vectorielle haute performance pour la recherche sémantique et les applications RAG — indexation accélérée par GPU**

Qdrant est une base de données vectorielle open source, prête pour la production, écrite en Rust. Elle offre une recherche rapide approximative des plus proches voisins (ANN) sur des milliards de vecteurs avec filtrage avancé, indexation des payloads et prise en charge multi-vecteur. C’est l’épine dorsale de nombreux pipelines RAG (Retrieval-Augmented Generation) en production et d’applications de recherche sémantique.

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

***

## Pourquoi Qdrant ?

| Fonctionnalité                   | Qdrant     | Pinecone                   | Weaviate | Chroma    |
| -------------------------------- | ---------- | -------------------------- | -------- | --------- |
| Code source ouvert               | ✅          | ❌                          | ✅        | ✅         |
| Performances de Rust             | ✅          | —                          | ❌ Go     | ❌ Python  |
| Filtrage au moment de la requête | ✅ Avancé   | ✅ Basique                  | ✅        | ✅ Basique |
| Multi-vecteur                    | ✅          | ❌                          | ✅        | ❌         |
| HNSW basé sur disque             | ✅          | ✅                          | ✅        | ❌         |
| Indexation des payloads          | ✅          | Limité                     | ✅        | Limité    |
| gRPC + REST                      | ✅ Les deux | ✅ REST                     | ✅        | REST      |
| Auto-hébergé                     | ✅          | ❌ Uniquement dans le cloud | ✅        | ✅         |

{% hint style="success" %}
**Qdrant est écrit en Rust** — offrant des performances de niveau C avec une sécurité mémoire. Les tests de benchmark montrent que Qdrant est systématiquement **1,5–3x plus rapide** que les alternatives basées sur Python comme Chroma dans les scénarios à forte charge.
{% endhint %}

***

## Cas d'utilisation principaux

* **RAG (Retrieval-Augmented Generation)** — trouver un contexte pertinent pour les prompts des LLM
* **Recherche sémantique** — rechercher par le sens, pas seulement par mots-clés
* **Systèmes de recommandation** — trouver des éléments similaires par similarité d'embedding
* **Détection de doublons** — identifier du contenu quasi dupliqué
* **Détection d'anomalies** — trouver des vecteurs éloignés des centres de cluster
* **Recherche de similarité d'images/de sons** — récupération multimodale

***

## Prérequis

* Compte Clore.ai avec location de GPU
* Connaissances de base des API REST ou de Python
* Votre modèle d'embeddings de votre choix (OpenAI, SentenceTransformers, etc.)

***

## Étape 1 — Louer un serveur sur Clore.ai

Qdrant est principalement limité par le CPU/la RAM pour le service, mais bénéficie du GPU lorsque :

* Génération d'embeddings en parallèle du service (modèle d'embeddings sur le même serveur)
* Opérations d'indexation par lots à grande échelle

1. Accédez à [clore.ai](https://clore.ai) → **Place de marché**
2. Pour **combinaison embeddings + service :** RTX 3090/4090 avec 32 Go+ de RAM
3. Pour **service uniquement :** serveur optimisé pour le CPU avec stockage NVMe rapide

{% hint style="info" %}
**Planification mémoire :**

* Chaque vecteur float32 de 1536 dimensions = 6 Ko
* 1 million de vecteurs = \~6 Go de RAM
* 10 millions de vecteurs = \~60 Go de RAM
* Activez le stockage sur disque pour les collections très volumineuses
  {% endhint %}

***

## Étape 2 — Déployer le conteneur Qdrant

**Image Docker :**

```
qdrant/qdrant:latest
```

**Ports :**

```
22
6333
6334
```

* **Port 6333 :** API REST (HTTP)
* **Port 6334 :** API gRPC (meilleures performances pour les opérations groupées)

**Variables d'environnement :**

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

**Volume/stockage persistant :** Monter `/qdrant/storage` pour la persistance des données. Sans cela, les données sont perdues au redémarrage du conteneur.

***

## Étape 3 — Vérifier que Qdrant est en cours d’exécution

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

# Vérifier que Qdrant est en cours d'exécution
curl http://localhost:6333/

# Réponse attendue :
# {"title":"qdrant - moteur de recherche vectorielle","version":"..."}

# Vérifier l'état
curl http://localhost:6333/healthz

# Vérifier les informations du cluster
curl http://localhost:6333/cluster
```

***

## Étape 4 — Installer le client Python

```bash
# Installer le client Python Qdrant et les outils d'embedding
pip install qdrant-client sentence-transformers openai numpy

# Vérifier la connexion
python3 << 'EOF'
from qdrant_client import QdrantClient

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

***

## Étape 5 — Créer une collection

Une collection est un groupe nommé de vecteurs avec une dimensionalité fixe.

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

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

# Créer une collection pour OpenAI text-embedding-3-small (1536 dims)
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(
        size=1536,           # Dimension du vecteur (à faire correspondre à votre modèle d'embedding)
        distance=Distance.COSINE,  # Options : COSINE, EUCLID, DOT
        on_disk=False        # Mettre à True pour les collections très volumineuses
    ),
    hnsw_config=HnswConfigDiff(
        m=16,                # Connectivité du graphe HNSW (plus élevé = meilleur rappel, plus de RAM)
        ef_construct=100,    # Profondeur de recherche à la construction (plus élevé = meilleure qualité, indexation plus lente)
        full_scan_threshold=10000  # Utiliser la force brute en dessous de ce nombre
    ),
    optimizers_config=OptimizersConfigDiff(
        indexing_threshold=20000  # Commencer l'indexation HNSW après ce nombre de vecteurs
    ),
    quantization_config=QuantizationConfig(
        scalar=ScalarQuantizationConfig(
            type=ScalarType.INT8,  # Compresser les vecteurs en INT8 (réduction de mémoire x4)
            quantile=0.99,
            always_ram=True        # Conserver l'index quantifié en RAM
        )
    )
)

print("Collection créée !")
print(client.get_collection("documents"))
```

### Collection pour SentenceTransformers (384 dimensions)

```python
client.create_collection(
    collection_name="embeddings_384",
    vectors_config=VectorParams(
        size=384,              # taille de sortie de all-MiniLM-L6-v2
        distance=Distance.COSINE
    )
)
```

***

## Étape 6 — Indexer des documents

### Avec les embeddings OpenAI

```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]]:
    """Générer des embeddings par lots."""
    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

# Exemples de documents
documents = [
    {
        "id": str(uuid.uuid4()),
        "text": "Qdrant est une base de données vectorielle construite en Rust pour des performances élevées.",
        "source": "documentation",
        "category": "database",
        "year": 2024
    },
    {
        "id": str(uuid.uuid4()),
        "text": "Les modèles de machine learning convertissent le texte en représentations vectorielles denses.",
        "source": "article",
        "category": "ml",
        "year": 2023
    },
    # Ajouter d'autres documents...
]

# Générer les embeddings
texts = [doc["text"] for doc in documents]
embeddings = get_embeddings(texts)

# Insérer dans Qdrant
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  # Attendre la fin de l'indexation
)

print(f"{len(points)} documents indexés !")
```

### Avec SentenceTransformers (local, accéléré par GPU)

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

# Charger le modèle d'embedding sur le GPU
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

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

documents = [
    {"text": "Comment configurer Qdrant sur un serveur GPU ?", "tag": "setup"},
    {"text": "Les bases de données vectorielles stockent des embeddings de haute dimension pour la recherche de similarité.", "tag": "concept"},
    {"text": "L'algorithme HNSW fournit une recherche approximative des plus proches voisins.", "tag": "algorithm"},
    # ... d'autres documents
]

# Encodage par lots accéléré par GPU
texts = [doc["text"] for doc in documents]
embeddings = model.encode(
    texts,
    batch_size=256,       # Grande taille de lot pour l'efficacité du GPU
    show_progress_bar=True,
    normalize_embeddings=True  # Normaliser pour la similarité cosinus
)

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

# Insertion par lots (plus efficace)
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"{min(i + BATCH_SIZE, len(points))}/{len(points)} indexés")
```

***

## Étape 7 — Rechercher et interroger

### Recherche sémantique de base

```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"):
    # Générer l'embedding de la requête
    query_vector = model.encode(query, normalize_embeddings=True).tolist()
    
    # Rechercher
    results = client.search(
        collection_name=collection,
        query_vector=query_vector,
        limit=limit,
        with_payload=True,
        with_vectors=False    # Ne pas renvoyer les vecteurs (économise la bande passante)
    )
    
    return results

# Tester la recherche
results = search("performance de base de données vectorielle")
for r in results:
    print(f"Score : {r.score:.4f} | {r.payload['text'][:100]}")
```

### Recherche filtrée (métadonnées + vecteur)

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

# Recherche avec filtres de métadonnées
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)  # Année >= 2023
            )
        ]
    ),
    limit=10,
    with_payload=True
)
```

### Recherche par lot / multi-requête

```python
from qdrant_client.models import SearchRequest

queries = [
    "comment installer une base de données vectorielle",
    "optimisation de l'inférence en machine learning",
    "architecture de pipeline RAG"
]

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

# Recherche par lot (un appel API pour toutes les requêtes)
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"\nRequête : {query}")
    for r in res:
        print(f"  {r.score:.3f}: {r.payload['text'][:80]}")
```

***

## Étape 8 — Construire un pipeline RAG

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

# Initialiser les clients
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:
    # Étape 1 : vectoriser la question
    query_vector = embedder.encode(question, normalize_embeddings=True).tolist()
    
    # Étape 2 : récupérer le contexte pertinent depuis Qdrant
    search_results = qdrant.search(
        collection_name="documents",
        query_vector=query_vector,
        limit=n_context,
        with_payload=True
    )
    
    # Étape 3 : construire la chaîne de contexte
    context = "\n\n".join([
        f"[Source : {r.payload.get('source', 'unknown')}]\n{r.payload['text']}"
        for r in search_results
        if r.score > 0.5  # Filtrer les résultats à faible confiance
    ])
    
    # Étape 4 : générer la réponse avec le LLM
    response = llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "Répondez aux questions en fonction du contexte fourni. Soyez concis et précis."
            },
            {
                "role": "user",
                "content": f"Contexte :\n{context}\n\nQuestion : {question}"
            }
        ],
        temperature=0.1
    )
    
    return response.choices[0].message.content

# Tester le pipeline RAG
answer = rag_query("Qu'est-ce que Qdrant et comment cela fonctionne-t-il ?")
print(answer)
```

***

## Étape 9 — Surveiller et gérer les collections

```python
# Statistiques de la collection
info = client.get_collection("documents")
print(f"Nombre de vecteurs : {info.vectors_count:,}")
print(f"Nombre de points : {info.points_count:,}")
print(f"Vecteurs indexés : {info.indexed_vectors_count:,}")
print(f"État : {info.status}")
print(f"Utilisation disque : {info.disk_data_size / 1024 / 1024:.1f} MB")

# Lister toutes les collections
collections = client.get_collections()
for c in collections.collections:
    print(f" - {c.name}")

# Supprimer des points par filtre
client.delete(
    collection_name="documents",
    points_selector=Filter(
        must=[FieldCondition(key="source", match=MatchValue(value="old_source"))]
    )
)

# Optimiser la collection (forcer la création de l'index)
client.update_collection(
    collection_name="documents",
    optimizer_config=OptimizersConfigDiff(indexing_threshold=0)  # Forcer l'indexation immédiate
)
```

***

## Dépannage

### Connexion refusée

```bash
# Vérifier que Qdrant est en cours d'exécution
docker ps | grep qdrant
# Ou vérifier le processus
ps aux | grep qdrant

# Vérifier que les ports sont ouverts
curl http://localhost:6333/
netstat -tlnp | grep 6333
```

### Performances de recherche lentes

```python
# Optimiser les paramètres HNSW pour un meilleur rappel
client.update_collection(
    collection_name="documents",
    hnsw_config=HnswConfigDiff(ef=128)  # Augmenter le ef au moment de la recherche (par défaut 100)
)

# Utiliser la quantification INT8 pour faire tenir plus de vecteurs en RAM
```

### Utilisation mémoire élevée

```python
# Activer le stockage sur disque pour les collections volumineuses
client.create_collection(
    collection_name="large_collection",
    vectors_config=VectorParams(
        size=1536,
        distance=Distance.COSINE,
        on_disk=True  # Stocker les vecteurs sur disque au lieu de la RAM
    )
)
```

***

## Référence rapide de l'API REST

```bash
# Lister les collections
curl http://localhost:6333/collections

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

# Compter les points
curl http://localhost:6333/collections/my_collection/points/count

# Rechercher
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
    }'

# Supprimer la collection
curl -X DELETE http://localhost:6333/collections/my_collection
```

***

## Estimation des coûts sur Clore.ai

| Configuration           | Serveur                | Coût mensuel | Capacité        |
| ----------------------- | ---------------------- | ------------ | --------------- |
| Petit RAG               | RTX 3090, 32 Go de RAM | \~60–80 $    | \~5 M vecteurs  |
| Recherche intermédiaire | RTX 4090, 64 Go de RAM | \~120–150 $  | \~15 M vecteurs |
| Grande échelle          | A100, 128 Go de RAM    | \~250–350 $  | \~30 M vecteurs |

***

## Ressources supplémentaires

* [Documentation Qdrant](https://qdrant.tech/documentation/)
* [GitHub Qdrant](https://github.com/qdrant/qdrant)
* [Client Python Qdrant](https://github.com/qdrant/qdrant-client)
* [Exemples Qdrant](https://github.com/qdrant/examples)
* [Benchmarks des bases de données vectorielles](https://qdrant.tech/benchmarks/)
* [Sentence Transformers](https://www.sbert.net/)

***

*Qdrant sur Clore.ai vous offre une base de données vectorielle auto-hébergée et haute performance, sans les coûts par requête de Pinecone ou de Weaviate Cloud. Parfait pour les pipelines RAG traitant des millions de documents.*

***

## Recommandations GPU Clore.ai

| Cas d’utilisation                   | GPU recommandé   | Coût estimé sur Clore.ai |
| ----------------------------------- | ---------------- | ------------------------ |
| Développement/Test                  | RTX 3090 (24 Go) | 0,07–0,21 $/gpu/h        |
| Recherche vectorielle en production | RTX 3090 (24 Go) | 0,07–0,21 $/gpu/h        |
| Embeddings à haut débit             | RTX 4090 (24 Go) | 0,14–0,42 $/gpu/h        |

> 💡 Tous les exemples de ce guide peuvent être déployés sur [Clore.ai](https://clore.ai/marketplace) des serveurs GPU. Parcourez les GPU disponibles et louez à l'heure — sans engagement, accès root complet.


---

# 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-fr/rag-et-bases-de-donnees-vectorielles/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.
