> 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-es/rag-y-bases-de-datos-vectoriales/qdrant.md).

# Qdrant

> **Base de datos vectorial de alto rendimiento para búsqueda semántica y aplicaciones RAG — indexación acelerada por GPU**

Qdrant es una base de datos vectorial de código abierto y lista para producción escrita en Rust. Ofrece búsqueda rápida de vecinos más cercanos aproximados (ANN) a través de miles de millones de vectores con filtrado avanzado, indexación de payload y soporte multivector. Es la base de muchos flujos de trabajo RAG (Generación Aumentada por Recuperación) en producción y aplicaciones de búsqueda semántica.

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

***

## ¿Por qué Qdrant?

| Función                        | Qdrant     | Pinecone          | Weaviate | Chroma   |
| ------------------------------ | ---------- | ----------------- | -------- | -------- |
| Código abierto                 | ✅          | ❌                 | ✅        | ✅        |
| Rendimiento de Rust            | ✅          | —                 | ❌ Go     | ❌ Python |
| Filtrado en tiempo de consulta | ✅ Avanzado | ✅ Básico          | ✅        | ✅ Básico |
| Multivector                    | ✅          | ❌                 | ✅        | ❌        |
| HNSW basado en disco           | ✅          | ✅                 | ✅        | ❌        |
| Indexación de payload          | ✅          | Limitado          | ✅        | Limitado |
| gRPC + REST                    | ✅ Ambos    | ✅ REST            | ✅        | REST     |
| Autoalojado                    | ✅          | ❌ Solo en la nube | ✅        | ✅        |

{% hint style="success" %}
**Qdrant está escrito en Rust** — ofreciendo rendimiento de nivel C con seguridad de memoria. Las pruebas comparativas muestran que Qdrant es consistentemente **1,5–3 veces más rápido** que alternativas basadas en Python como Chroma para escenarios de alta carga.
{% endhint %}

***

## Casos de uso clave

* **RAG (Generación Aumentada por Recuperación)** — encontrar contexto relevante para prompts de LLM
* **Búsqueda semántica** — buscar por significado, no solo por palabras clave
* **Sistemas de recomendación** — encontrar elementos similares mediante similitud de embeddings
* **Detección de duplicados** — identificar contenido casi duplicado
* **Detección de anomalías** — encontrar vectores alejados de los centros de los clústeres
* **Búsqueda de similitud de imágenes/audio** — recuperación multimodal

***

## Requisitos previos

* Cuenta de Clore.ai con alquiler de GPU
* Familiaridad básica con APIs REST o Python
* Tu modelo de embeddings de elección (OpenAI, SentenceTransformers, etc.)

***

## Paso 1 — Alquilar un servidor en Clore.ai

Qdrant depende principalmente de CPU/RAM para servir, pero se beneficia de GPU cuando:

* Generar embeddings junto con el servicio (modelo de embeddings en el mismo servidor)
* Operaciones de indexación por lotes a gran escala

1. Ve a [clore.ai](https://clore.ai) → **Marketplace**
2. Para **combinación embeddings + servicio:** RTX 3090/4090 con 32 GB+ de RAM
3. Para **solo servicio:** servidor optimizado para CPU con almacenamiento NVMe rápido

{% hint style="info" %}
**Planificación de memoria:**

* Cada vector float32 con 1536 dimensiones = 6 KB
* 1 millón de vectores = \~6 GB de RAM
* 10 millones de vectores = \~60 GB de RAM
* Habilita el almacenamiento en disco para colecciones muy grandes
  {% endhint %}

***

## Paso 2 — Implementar el contenedor de Qdrant

**Imagen de Docker:**

```
qdrant/qdrant:latest
```

**Puertos:**

```
22
6333
6334
```

* **Puerto 6333:** API REST (HTTP)
* **Puerto 6334:** API gRPC (mayor rendimiento para operaciones en lote)

**Variables de entorno:**

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

**Volumen/Almacenamiento persistente:** Montar `/qdrant/storage` para la persistencia de datos. Sin esto, los datos se pierden al reiniciar el contenedor.

***

## Paso 3 — Verificar que Qdrant se está ejecutando

```bash
ssh root@<ip-del-servidor> -p <puerto-ssh>

# Verificar que Qdrant se está ejecutando
curl http://localhost:6333/

# Respuesta esperada:
# {"title":"qdrant - motor de búsqueda vectorial","version":"..."}

# Comprobar el estado
curl http://localhost:6333/healthz

# Ver información del clúster
curl http://localhost:6333/cluster
```

***

## Paso 4 — Instalar el cliente de Python

```bash
# Instalar el cliente Python de Qdrant y herramientas de embeddings
pip install qdrant-client sentence-transformers openai numpy

# Verificar conexión
python3 << 'EOF'
from qdrant_client import QdrantClient

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

***

## Paso 5 — Crear una colección

Una colección es un grupo nombrado de vectores con una dimensionalidad fija.

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

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

# Crear colección para OpenAI text-embedding-3-small (1536 dimensiones)
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(
        size=1536,           # Dimensión del vector (debe coincidir con tu modelo de embeddings)
        distance=Distance.COSINE,  # Opciones: COSINE, EUCLID, DOT
        on_disk=False        # Establece True para colecciones muy grandes
    ),
    hnsw_config=HnswConfigDiff(
        m=16,                # Conectividad del grafo HNSW (más alto = mejor recall, más RAM)
        ef_construct=100,    # Profundidad de búsqueda en la construcción (más alto = mejor calidad, indexación más lenta)
        full_scan_threshold=10000  # Usar fuerza bruta por debajo de este número
    ),
    optimizers_config=OptimizersConfigDiff(
        indexing_threshold=20000  # Empezar la indexación HNSW después de esta cantidad de vectores
    ),
    quantization_config=QuantizationConfig(
        scalar=ScalarQuantizationConfig(
            type=ScalarType.INT8,  # Comprimir vectores a INT8 (reducción de memoria de 4x)
            quantile=0.99,
            always_ram=True        # Mantener el índice cuantizado en RAM
        )
    )
)

¡Colección creada!
print(client.get_collection("documents"))
```

### Colección para SentenceTransformers (384 dimensiones)

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

***

## Paso 6 — Indexar documentos

### Con 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]]:
    """Generar embeddings por lotes."""
    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

# Documentos de ejemplo
documents = [
    {
        "id": str(uuid.uuid4()),
        "text": "Qdrant es una base de datos vectorial construida en Rust para alto rendimiento.",
        "source": "documentación",
        "category": "base de datos",
        "year": 2024
    },
    {
        "id": str(uuid.uuid4()),
        "text": "Los modelos de aprendizaje automático convierten texto en representaciones vectoriales densas.",
        "source": "artículo",
        "category": "ml",
        "year": 2023
    },
    # Añadir más documentos...
]

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

# Hacer upsert en 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  # Esperar a que se complete la indexación
)

print(f"¡{len(points)} documentos indexados!")
```

### Con SentenceTransformers (local, acelerado por GPU)

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

# Cargar el modelo de embeddings en la GPU
model = SentenceTransformer("all-MiniLM-L6-v2", device="cuda")

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

documents = [
    {"text": "¿Cómo configuro Qdrant en un servidor GPU?", "tag": "configuración"},
    {"text": "Las bases de datos vectoriales almacenan embeddings de alta dimensión para búsqueda por similitud.", "tag": "concepto"},
    {"text": "El algoritmo HNSW proporciona búsqueda aproximada de vecinos más cercanos.", "tag": "algoritmo"},
    # ... más documentos
]

# Codificación por lotes acelerada por GPU
texts = [doc["text"] for doc in documents]
embeddings = model.encode(
    texts,
    batch_size=256,       # Tamaño de lote grande para eficiencia de GPU
    show_progress_bar=True,
    normalize_embeddings=True  # Normalizar para similitud coseno
)

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

# Upsert por lotes (más eficiente)
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"Indexados {min(i + BATCH_SIZE, len(points))}/{len(points)}")
```

***

## Paso 7 — Buscar y consultar

### Búsqueda semántica básica

```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"):
    # Generar embedding de la consulta
    query_vector = model.encode(query, normalize_embeddings=True).tolist()
    
    # Buscar
    results = client.search(
        collection_name=collection,
        query_vector=query_vector,
        limit=limit,
        with_payload=True,
        with_vectors=False    # No devolver vectores (ahorra ancho de banda)
    )
    
    return results

# Probar búsqueda
results = search("rendimiento de base de datos vectorial")
for r in results:
    print(f"Puntuación: {r.score:.4f} | {r.payload['text'][:100]}")
```

### Búsqueda filtrada (metadatos + vector)

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

# Buscar con filtros de metadatos
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)  # Año >= 2023
            )
        ]
    ),
    limit=10,
    with_payload=True
)
```

### Búsqueda por lotes/multiconsulta

```python
from qdrant_client.models import SearchRequest

queries = [
    "how to install vector database",
    "machine learning inference optimization",
    "RAG pipeline architecture"
]

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

# Búsqueda por lotes (una llamada a la API para todas las consultas)
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"\nConsulta: {query}")
    for r in res:
        print(f"  {r.score:.3f}: {r.payload['text'][:80]}")
```

***

## Paso 8 — Crear una tubería RAG

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

# Inicializar clientes
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:
    # Paso 1: Convertir la pregunta en embedding
    query_vector = embedder.encode(question, normalize_embeddings=True).tolist()
    
    # Paso 2: Recuperar contexto relevante de Qdrant
    search_results = qdrant.search(
        collection_name="documents",
        query_vector=query_vector,
        limit=n_context,
        with_payload=True
    )
    
    # Paso 3: Construir la cadena de contexto
    context = "\n\n".join([
        f"[Fuente: {r.payload.get('source', 'unknown')}]\n{r.payload['text']}"
        for r in search_results
        if r.score > 0.5  # Filtrar resultados con baja confianza
    ])
    
    # Paso 4: Generar respuesta con el LLM
    response = llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": "Responde a las preguntas basándote en el contexto proporcionado. Sé conciso y preciso."
            },
            {
                "role": "user",
                "content": f"Contexto:\n{context}\n\nPregunta: {question}"
            }
        ],
        temperature=0.1
    )
    
    return response.choices[0].message.content

# Probar la tubería RAG
answer = rag_query("¿Qué es Qdrant y cómo funciona?")
print(answer)
```

***

## Paso 9 — Supervisar y gestionar colecciones

```python
# Estadísticas de la colección
info = client.get_collection("documents")
print(f"Cantidad de vectores: {info.vectors_count:,}")
print(f"Cantidad de puntos: {info.points_count:,}")
print(f"Vectores indexados: {info.indexed_vectors_count:,}")
print(f"Estado: {info.status}")
print(f"Uso de disco: {info.disk_data_size / 1024 / 1024:.1f} MB")

# Listar todas las colecciones
collections = client.get_collections()
for c in collections.collections:
    print(f" - {c.name}")

# Eliminar puntos por filtro
client.delete(
    collection_name="documents",
    points_selector=Filter(
        must=[FieldCondition(key="source", match=MatchValue(value="old_source"))]
    )
)

# Optimizar colección (forzar la construcción del índice)
client.update_collection(
    collection_name="documents",
    optimizer_config=OptimizersConfigDiff(indexing_threshold=0)  # Forzar indexación inmediata
)
```

***

## Solución de problemas

### Conexión rechazada

```bash
# Verificar que Qdrant se está ejecutando
docker ps | grep qdrant
# O comprobar el proceso
ps aux | grep qdrant

# Comprobar que los puertos están abiertos
curl http://localhost:6333/
netstat -tlnp | grep 6333
```

### Rendimiento de búsqueda lento

```python
# Optimizar los parámetros de HNSW para mejor recall
client.update_collection(
    collection_name="documents",
    hnsw_config=HnswConfigDiff(ef=128)  # Aumentar ef en tiempo de búsqueda (predeterminado 100)
)

# Usar cuantización INT8 para meter más vectores en RAM
```

### Uso elevado de memoria

```python
# Habilitar almacenamiento en disco para colecciones grandes
client.create_collection(
    collection_name="large_collection",
    vectors_config=VectorParams(
        size=1536,
        distance=Distance.COSINE,
        on_disk=True  # Almacenar vectores en disco en lugar de RAM
    )
)
```

***

## Referencia rápida de la API REST

```bash
# Listar colecciones
curl http://localhost:6333/collections

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

# Contar puntos
curl http://localhost:6333/collections/my_collection/points/count

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

# Eliminar colección
curl -X DELETE http://localhost:6333/collections/my_collection
```

***

## Estimación de costos en Clore.ai

| Configuración  | Servidor           | Costo mensual | Capacidad      |
| -------------- | ------------------ | ------------- | -------------- |
| RAG pequeño    | RTX 3090, 32GB RAM | \~$60–80      | \~5M vectores  |
| Búsqueda media | RTX 4090, 64GB RAM | \~$120–150    | \~15M vectores |
| A gran escala  | A100, 128GB RAM    | \~$250–350    | \~30M vectores |

***

## Recursos adicionales

* [Documentación de Qdrant](https://qdrant.tech/documentation/)
* [GitHub de Qdrant](https://github.com/qdrant/qdrant)
* [Cliente Python de Qdrant](https://github.com/qdrant/qdrant-client)
* [Ejemplos de Qdrant](https://github.com/qdrant/examples)
* [Puntos de referencia de bases de datos vectoriales](https://qdrant.tech/benchmarks/)
* [Sentence Transformers](https://www.sbert.net/)

***

*Qdrant en Clore.ai te ofrece una base de datos vectorial de alto rendimiento y autohospedada, sin los costos por consulta de Pinecone o Weaviate Cloud. Perfecta para canalizaciones de RAG que procesan millones de documentos.*

***

## Recomendaciones de GPU para Clore.ai

| Caso de uso                      | GPU recomendada | Costo estimado en Clore.ai |
| -------------------------------- | --------------- | -------------------------- |
| Desarrollo/Pruebas               | RTX 3090 (24GB) | $0.07–0.21/gpu/hr          |
| Búsqueda vectorial en producción | RTX 3090 (24GB) | $0.07–0.21/gpu/hr          |
| Embeddings de alto rendimiento   | RTX 4090 (24GB) | $0.14–0.42/gpu/hr          |

> 💡 Todos los ejemplos de esta guía pueden desplegarse en [Clore.ai](https://clore.ai/marketplace) servidores GPU. Explora las GPUs disponibles y alquila por hora: sin compromisos, acceso root completo.


---

# 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-es/rag-y-bases-de-datos-vectoriales/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.
