Qdrant векторная БД для AI-агентов: полный гайд
🔍

Qdrant: векторная база данных для AI-агентов

Qdrant — написанная на Rust векторная БД с фильтрацией по payload, гибридным поиском и квантованием. Идеальный бэкенд для RAG-агентов с миллионами векторов и миллисекундной latency.

intermediate ⏱ 15 мин
API Layer REST API gRPC API Python/JS Client Qdrant Engine (Rust) HNSW Index Payload Filter Quantization Sparse Vectors Replication Snapshots Storage Backend Memmap RocksDB WAL Journal Vector Search → Payload Filter → Score → Top-K Qdrant Architecture — Rust-powered Vector Database with HNSW

# 1. Почему Qdrant — лучший выбор для AI-агентов

Qdrant — это векторная база данных, написанная на Rust, что даёт ей производительность на порядок выше Python-решений вроде Chroma. Она поддерживает payload filtering (фильтрацию по метаданным ДО векторного поиска), что критично для multi-tenant AI-агентов, где у каждого клиента свои документы. В отличие от Pinecone, Qdrant можно развернуть on-premise без привязки к облаку.

Ключевые фичи: бинарное квантование векторов (сжатие в 32 раза), разреженные векторы для гибридного поиска (BM25 + dense), шардирование для горизонтального масштабирования, и нативная поддержка репликации. Qdrant — выбор по умолчанию для RAG-агентов в энтерпрайзе, где важны суверенитет данных и низкая latency.

# Запуск Qdrant через Docker
docker run -d --name qdrant \
  -p 6333:6333 -p 6334:6334 \
  -v $(pwd)/qdrant_storage:/qdrant/storage \
  qdrant/qdrant:latest

# Проверка health
curl http://localhost:6333/healthz

# Вывод: {"title":"healthz","version":"1.11.0"}

# 2. Создание коллекции и загрузка векторов

В Qdrant данные организованы в коллекции (аналог таблиц в SQL). Каждая коллекция имеет конфигурацию: размерность векторов, метрику расстояния (Cosine, Euclid, Dot), и настройки HNSW-индекса. При создании коллекции укажите тип квантования: scalar (без сжатия), binary (32x сжатие, небольшая потеря точности), или product (компромисс).

Payload — это метаданные точки (JSON). В отличие от других векторных БД, Qdrant индексирует payload-поля, позволяя делать быструю предварительную фильтрацию. Это даёт выигрыш в скорости когда у вас миллионы точек, но запросы ограничены tenant_id или категорией документа.

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

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

# Создаём коллекцию для документов AI-агента
client.create_collection(
    collection_name="agent_knowledge",
    vectors_config=VectorParams(
        size=1536,
        distance=Distance.COSINE
    ),
    hnsw_config={
        "m": 16,             # connections per layer
        "ef_construct": 200,  # build-time search depth
    },
    quantization_config={
        "scalar": {
            "type": "int8",     # сжатие в 4 раза
            "always_ram": True
        }
    }
)

# Загружаем эмбеддинги с метаданными
points = [
    PointStruct(
        id=1,
        vector=embedding_1,  # 1536-мерный вектор
        payload={
            "source": "docs/api-reference.md",
            "tenant": "acme-corp",
            "chunk_id": 42,
            "created_at": "2026-06-15T10:00:00Z"
        }
    ),
    # ... ещё точки
]

client.upsert(
    collection_name="agent_knowledge",
    points=points
)

print(f"Points: {client.count('agent_knowledge').count}")

# 3. Поиск: семантический, фильтрованный и гибридный

Qdrant поддерживает три режима поиска. Семантический (dense) — по векторному сходству, классика RAG. Фильтрованный — сначала фильтр по payload, потом поиск среди отфильтрованных. Гибридный — комбинация dense и sparse (BM25) векторов с настраиваемыми весами. Для AI-агентов гибридный поиск даёт наилучшее качество retrieval, особенно на смешанных данных с техническими терминами.

Используйте search_groups для группировки результатов по полю payload — например, чтобы вернуть не более 3 чанков из одного документа. Это предотвращает ситуацию, когда весь top-K занят чанками из единственного длинного документа.

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

# 1. Семантический поиск
results = client.search(
    collection_name="agent_knowledge",
    query_vector=query_embedding,
    limit=5,
    with_payload=True
)

# 2. Поиск с фильтром по tenant_id
results = client.search(
    collection_name="agent_knowledge",
    query_vector=query_embedding,
    query_filter=Filter(
        must=[
            FieldCondition(
                key="tenant",
                match=MatchValue(value="acme-corp")
            ),
            FieldCondition(
                key="chunk_id",
                range=Range(gte=10, lte=100)
            )
        ]
    ),
    limit=5
)

# 3. Гибридный поиск (dense + sparse)
results = client.search(
    collection_name="agent_knowledge",
    query_vector=query_embedding,
    query_sparse_vector=sparse_vector,  # BM25 sparse
    limit=5,
    with_payload=True
)

for hit in results:
    print(f"Score: {hit.score:.3f}, Source: {hit.payload['source']}")

# 4. Продвинутая фильтрация и поиск по группам

Qdrant поддерживает сложные фильтры: вложенные условия (must, should, must_not), операции с массивами, полнотекстовый поиск по payload-полям, и гео-фильтры. Для AI-агента это позволяет делать запросы вроде «найди документы, созданные за последнюю неделю, в категории API и не относящиеся к deprecated-эндпоинтам».

Search groups решают проблему доминирования одного документа в результатах. Вы группируете результаты по полю (например, source или document_id) и указываете group_size — максимальное количество результатов из одной группы. Это гарантирует разнообразие источников в контексте LLM.

from qdrant_client.models import Filter, FieldCondition, MatchText, DatetimeRange
from datetime import datetime, timedelta

# Сложный фильтр: must (AND) + should (OR) + must_not (NOT)
last_week = datetime.now() - timedelta(days=7)
advanced_filter = Filter(
    must=[
        FieldCondition(key="tenant", match=MatchValue(value="acme-corp")),
        FieldCondition(key="created_at", range=DatetimeRange(gte=last_week.isoformat()))
    ],
    should=[
        FieldCondition(key="category", match=MatchValue(value="api")),
        FieldCondition(key="category", match=MatchValue(value="sdk"))
    ],
    must_not=[
        FieldCondition(key="tags", match=MatchText(text="deprecated"))
    ]
)

# Поиск с группировкой по источнику
results = client.search_groups(
    collection_name="agent_knowledge",
    query_vector=query_embedding,
    group_by="source",
    group_size=2,         # макс 2 чанка из одного документа
    limit=5,               # 5 групп (разных документов)
    query_filter=advanced_filter,
    with_payload=True
)

for group in results.groups:
    print(f"Source: {group.id}")
    for hit in group.hits:
        print(f"  Score: {hit.score:.3f}")

# 5. Интеграция Qdrant с LangChain и LlamaIndex

Qdrant нативно интегрирован с LangChain и LlamaIndex как векторное хранилище. Вы можете использовать QdrantVectorStore в LangChain или QdrantVectorStore в LlamaIndex с одной строкой конфигурации. Это позволяет строить RAG-пайплайны, где Qdrant отвечает за хранение и поиск, а LangChain/LlamaIndex — за оркестрацию и LLM-вызовы.

Для AI-агентов с миллионами документов используйте Qdrant в режиме сервера (отдельный контейнер), а не in-memory режим. Подключите LangChain через async-клиент Qdrant для неблокирующего поиска — это критично когда агент выполняет несколько retrieval-запросов параллельно.

# LangChain + Qdrant интеграция
from langchain_qdrant import QdrantVectorStore
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# Подключаем Qdrant как векторное хранилище
vectorstore = QdrantVectorStore.from_existing_collection(
    embedding=embeddings,
    collection_name="agent_knowledge",
    url="http://localhost:6333",
    content_payload_key="text",
)

# Создаём retriever с фильтром
retriever = vectorstore.as_retriever(
    search_kwargs={
        "k": 5,
        "filter": {"must": [{"key": "tenant", "match": {"value": "acme"}}]}
    }
)

from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o", temperature=0),
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True
)

result = qa_chain.invoke({"query": "Как работает search_groups в Qdrant?"})
print(result["result"])

# 6. Продакшен: репликация, бэкапы и мониторинг

Для продакшена разверните Qdrant в кластерном режиме с репликацией. Минимальная конфигурация: 3 ноды, replication_factor=2. Это даёт отказоустойчивость: при падении одной ноды данные доступны на репликах. Qdrant использует Raft-консенсус для метаданных коллекций и асинхронную репликацию для данных.

Настройте регулярные снапшоты через API для бэкапов. Qdrant поддерживает инкрементальные снапшоты, которые можно заливать в S3-совместимое хранилище. Мониторинг — через встроенный /metrics эндпоинт для Prometheus: отслеживайте количество точек, latency поиска, размер коллекций и использование памяти.

# docker-compose.yaml для Qdrant в продакшене
version: "3.8"
services:
  qdrant:
    image: qdrant/qdrant:v1.11.0
    ports:
      - "6333:6333"  # REST API
      - "6334:6334"  # gRPC API
      - "6335:6335"  # Cluster (internal)
    volumes:
      - qdrant_data:/qdrant/storage
      - ./config/production.yaml:/qdrant/config/production.yaml
    command: ["--config-path", "/qdrant/config/production.yaml"]
    environment:
      QDRANT__SERVICE__GRPC_PORT: "6334"
      QDRANT__LOG_LEVEL: "INFO"
    deploy:
      resources:
        limits:
          memory: 8G
        reservations:
          memory: 4G
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:6333/healthz"]
      interval: 30s
      timeout: 5s
      retries: 3

volumes:
  qdrant_data:
    driver: local

📊 Итог: Qdrant как фундамент RAG-агентов

Qdrant — это производительность Rust в сочетании с богатым API для фильтрации и гибридного поиска. Используйте его когда у вас: миллионы документов, multi-tenant архитектура, требования к миллисекундной latency и необходимость on-premise развёртывания. Ключевые практики: включайте бинарное квантование для экономии памяти, используйте search_groups для разнообразия контекста, настройте гибридный поиск для production-качества retrieval. Qdrant отлично работает с LangChain, LlamaIndex и Embedchain — это ваш основной векторный бэкенд для серьёзных AI-агентов.