Когда вы собираете поиск по своим документам или RAG-систему, рано или поздно упираетесь в вопрос: где хранить векторы. Держать их в памяти Python-процесса можно ровно до первого перезапуска, а отдавать корпоративную базу знаний в облако хочется не всегда. Qdrant — векторная база с открытым кодом (Apache 2.0), которая ставится одной командой Docker и спокойно живёт на обычном VPS. Разберём весь путь: от выбора машины до боевой конфигурации с ключом, фильтрами, квантизацией и бэкапами.
Что такое Qdrant и когда он нужен
Qdrant написан на Rust и решает одну задачу: хранить векторы (числовые представления текста, картинок, аудио) с произвольными метаданными и быстро находить среди них ближайшие к запросу. «Ближайшие» — значит похожие по смыслу: на этом строятся семантический поиск, рекомендации и подстановка контекста в промпт.
Критерий простой. Пара тысяч фрагментов и один процесс, который их читает, — хватит перебора в numpy. Десятки тысяч фрагментов, несколько сервисов, фильтры по метаданным (только документы этого клиента, только за последний год) и требование пережить деплой — пора ставить отдельную базу.
Qdrant в этом ряду выделяется тем, что его удобно держать у себя: один бинарник без внешних зависимостей — ни отдельного кластера, ни JVM, ни управляющей базы. Плюс встроенная веб-панель, где видно коллекции и можно руками выполнить запрос.
Сколько ресурсов заложить
Основной расход — память под векторы: число векторов × размерность × 4 байта (тип float32 по умолчанию). Сверху индекс HNSW, который связывает векторы в граф: примерно m × 2 × 4 байта × 1,2 на вектор, где m — число связей, по умолчанию 16, то есть около 154 байт.
Пример: миллион фрагментов, эмбеддинги размерностью 1536 (типичный размер у моделей OpenAI и Gemini) — это ≈ 6,1 ГБ на векторы плюс ≈ 0,15 ГБ на индекс. Документация советует закладывать ещё около 20% на кеш файловой системы, журнал записи и временные сегменты. Итого машина с 8 ГБ памяти — и это без запаса на всё остальное.
Пугает это только на первый взгляд: миллион фрагментов — очень много, база знаний среднего бизнеса редко переваливает за сотню тысяч. К тому же есть два рычага: квантизация (о ней ниже) и «холодный» режим, когда векторы лежат на диске в memory-mapped файлах. Для старта хватает VPS с 2 vCPU и 4 ГБ памяти; диск — обязательно SSD или NVMe.
Запуск в Docker
Самый короткий путь — официальный образ:
docker pull qdrant/qdrant
docker run -p 6333:6333 -p 6334:6334 \
-v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
qdrant/qdrant
Порт 6333 — REST API и веб-панель, 6334 — gRPC (быстрее на больших пакетах, клиентские библиотеки умеют оба). Ключевая строка — том: без -v данные исчезнут вместе с контейнером, каталог qdrant_storage и есть ваша база. После запуска откройте http://localhost:6333/dashboard — там список коллекций и консоль запросов.
Docker Compose и автозапуск
На сервере одноразовая команда не годится — нужен файл, который переживёт перезагрузку:
services:
qdrant:
image: qdrant/qdrant:v1.18.2
restart: unless-stopped
ports:
- "127.0.0.1:6333:6333"
- "127.0.0.1:6334:6334"
volumes:
- ./qdrant_storage:/qdrant/storage
environment:
QDRANT__SERVICE__API_KEY: ${QDRANT_API_KEY}
Два принципиальных отличия от команды выше. Версия зафиксирована явно (актуальна 1.18.2, июнь 2026) — тег latest на проде однажды подложит мажорное обновление в неподходящий момент. И порты привязаны к 127.0.0.1: база доступна только с самого сервера. Если приложение живёт в той же docker-сети, публиковать порты наружу не нужно вовсе.
Закрываем доступ: API-ключ и TLS
Этот раздел чаще всего пропускают, а потом находят свою базу в чужих руках. По умолчанию Qdrant не защищён ничем: кто дотянулся до порта, тот читает и удаляет коллекции. Открытых инстансов с торчащим наружу 6333 в интернете находится неприятно много.
Минимум — ключ через переменную окружения QDRANT__SERVICE__API_KEY (как в compose-файле выше) или в конфиге:
service:
api_key: ваш_секретный_ключ
read_only_api_key: ключ_только_на_чтение
enable_tls: true
tls:
cert: ./tls/cert.pem
key: ./tls/key.pem
Отдельный ключ на чтение полезен: сервису, который только ищет, право удалять коллекции не нужно. И не игнорируйте TLS — ключ, летящий по открытому HTTP, видно на любом промежуточном узле. Практичная схема для одного сервера: не выставлять порты наружу вовсе и ходить в базу изнутри docker-сети, а если доступ снаружи нужен — ставить перед Qdrant nginx с сертификатом. Об общих правилах работы с внутренними данными в ИИ-контуре — в заметке «Как не слить данные через ИИ».
Первая коллекция и первые векторы
Дальше работаем через официальный Python-клиент (pip install qdrant-client). Коллекция — аналог таблицы: фиксированная размерность векторов и метрика близости.
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
client = QdrantClient(url="http://localhost:6333", api_key="ваш_секретный_ключ")
client.create_collection(
collection_name="docs",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)
Размерность обязана совпадать с той, что выдаёт ваша модель эмбеддингов: поменяли модель — создавайте новую коллекцию. Метрика COSINE — стандартный выбор для текста, DOT — если векторы уже нормализованы, EUCLID нужен редко.
Запись называется upsert: точка с существующим id перезаписывается, с новым — добавляется. Вместе с вектором кладём payload — произвольный JSON, по которому потом можно фильтровать и который вернётся с результатом.
client.upsert(
collection_name="docs",
wait=True,
points=[
PointStruct(
id=1,
vector=embedding, # список из 1536 чисел от вашей модели
payload={"text": "текст фрагмента", "doc": "instrukciya.pdf", "year": 2026},
)
],
)
Сами эмбеддинги вы получаете отдельно: через API провайдера (Gemini, OpenAI) или локальной моделью — например, через Ollama на своём сервере. Связка «Ollama для эмбеддингов плюс Qdrant для хранения» даёт полностью автономный контур: данные не покидают вашу инфраструктуру.
Поиск выглядит так:
result = client.query_points(
collection_name="docs",
query=query_embedding,
limit=5,
with_payload=True,
).points
Нюанс, на котором спотыкаются все: вектор запроса должен быть получен той же моделью, что и векторы в базе. Смешали две модели — выдача будет выглядеть правдоподобно и при этом не иметь смысла.
Фильтры по метаданным
Главное преимущество нормальной векторной базы перед самописным перебором — фильтрация. Условия комбинируются блоками: must (все, логическое И), should (хотя бы одно, ИЛИ), must_not (ни одного). Внутри — match для точного совпадения, range для чисел и дат (gt, gte, lt, lte), полнотекстовый text, гео-условия.
{
"filter": {
"must": [
{ "key": "doc", "match": { "value": "instrukciya.pdf" } },
{ "key": "year", "range": { "gte": 2025 } }
],
"must_not": [
{ "key": "status", "match": { "value": "archived" } }
]
}
}
Важная деталь: по полям, которые участвуют в фильтрах, нужно строить индекс — client.create_payload_index(). Без него условие проверяется перебором, и на большой коллекции «быстрый» поиск внезапно начинает занимать секунды. Особенно критично, когда каждый запрос ограничен идентификатором клиента.
Квантизация: как ужать память
Если расчёт по формуле выше вас не обрадовал, квантизация — главный рычаг: векторы хранятся в сжатом виде, а точность добирается перепроверкой кандидатов.
- Скалярная (с версии 1.1) — float32 превращается в 8-битное целое, сжатие в 4 раза, потеря точности обычно меньше 1%. Самый безопасный вариант «включил и забыл».
- TurboQuant (появился в 1.18) — четыре режима: 4 бита (сжатие в 8 раз), 2 бита (16), 1,5 бита (24), 1 бит (32). Запрос при этом остаётся в полной точности, поэтому качество держится на уровне скалярной при вдвое большем сжатии.
- Бинарная (с 1.5) — самая быстрая по CPU, но требует высокой размерности и «центрированного» распределения; на маленьких эмбеддингах качество проседает.
- Продуктовая (с 1.2) — до 64 раз, но заметно медленнее. Берут, когда память дороже скорости.
Начинайте со скалярной, а если памяти всё равно не хватает — пробуйте 4-битный TurboQuant и обязательно замерьте качество поиска на своих запросах до и после. Универсального ответа тут нет: на одних данных сжатие в 16 раз проходит незаметно, на других ломает выдачу.
Бэкапы
Самый простой путь — остановить контейнер и скопировать каталог qdrant_storage: работает всегда, но требует простоя. Штатный способ без остановки — снапшоты: POST /collections/docs/snapshots снимает коллекцию, POST /snapshots — всю базу. Файлы кладутся внутрь тома, так что забирать их наружу всё равно придётся — например, ночным заданием cron. И проверьте восстановление хотя бы один раз на тестовом инстансе: бэкап, который никогда не разворачивали, бэкапом не является.
Когда всё-таки взять облако
Свой сервер — не догма. У Qdrant есть управляемое облако с бессрочным бесплатным тарифом: один узел, 0,5 vCPU, 1 ГБ памяти и 4 ГБ диска. Для прототипа и демо этого хватает, а администрировать не нужно вовсе.
Считать стоит по трём пунктам. Данные: если в базе персональные данные клиентов, требования к их размещению часто закрывают вопрос сами. Отказоустойчивость: реплики и автобэкапы в облаке уже есть, на своём сервере это ваша работа. Время: обновления, мониторинг и разбор ночных инцидентов — реальная нагрузка, её надо честно заложить в цену «бесплатного» хостинга. Разумный компромисс — держать своё, пока это один узел без жёстких требований к доступности.
Итог
Минимальный рабочий вариант: VPS с 4 ГБ памяти и NVMe, docker compose с зафиксированной версией, порты на 127.0.0.1, API-ключ в переменной окружения, коллекция с косинусной метрикой, индексы по фильтруемым полям и ночной снапшот в отдельное хранилище. Разворачивается за вечер и спокойно тянет базу знаний на десятки тысяч документов.
Дальше настройка идёт от боли: не хватает памяти — включайте квантизацию, медленно ищет с фильтрами — проверьте индексы payload, растёт нагрузка на запись — переходите на gRPC вместо REST. Начинать с тонкой настройки не нужно: сначала пусть заработает, потом измеряйте.
Частые вопросы
Считайте по формуле: число векторов × размерность × 4 байта плюс около 154 байт на вектор под индекс HNSW и ещё ~20% запаса. Для миллиона фрагментов с эмбеддингами размерностью 1536 это примерно 7,5 ГБ. Для старта на десятки тысяч документов достаточно VPS с 2 vCPU и 4 ГБ памяти.
Нет. Свежий инстанс принимает любые запросы: кто дотянулся до порта 6333, тот может читать и удалять коллекции. Обязательно задайте API-ключ через переменную QDRANT__SERVICE__API_KEY, привяжите порты к 127.0.0.1 и включите TLS, если база доступна снаружи.
Обычная база ищет по точному совпадению или диапазону значений, Qdrant — по близости векторов, то есть по смысловому сходству. При этом он умеет и то, и другое одновременно: фильтр по метаданным (клиент, дата, статус) применяется вместе с векторным поиском в одном запросе.
Для прототипа — да: бесплатный тариф Qdrant Cloud даёт один узел с 0,5 vCPU, 1 ГБ памяти и 4 ГБ диска бессрочно. Свой сервер выбирают, когда данные нельзя выносить наружу или когда объём перерастает бесплатные лимиты, но тогда обновления, мониторинг и бэкапы становятся вашей задачей.
Источники
- 1.Qdrant — Local Quickstarthttps://qdrant.tech/documentation/quickstart/
- 2.Qdrant — Capacity Planninghttps://qdrant.tech/documentation/capacity-planning/
- 3.Qdrant — Securityhttps://qdrant.tech/documentation/guides/security/
- 4.Qdrant — Quantizationhttps://qdrant.tech/documentation/guides/quantization/
- 5.Qdrant — Filteringhttps://qdrant.tech/documentation/concepts/filtering/
- 6.Qdrant — Pricinghttps://qdrant.tech/pricing/
- 7.Qdrant — Releases on GitHubhttps://github.com/qdrant/qdrant/releases



