похожих объектов в высокоразмерном пространстве. В контексте искусственного интеллекта она чаще всего
хранит embedding’и: числовые представления текстов, изображений, аудио, товаров, пользователей,
документов или фрагментов знаний.
Если совсем коротко:
SQL — библиотекарь ищет книгу по точному номеру полки, ID, дате или категории.
Vector DB — библиотекарь ищет книги, «похожие по смыслу» на ваш запрос.
Для архитектора важнейшая мысль такая:
Векторная база данных — это не просто хранилище
float[]. Это highly optimized engine
для nearest-neighbor search в высокоразмерном пространстве: индексы, ANN-поиск,
масштабирование, фильтрация, hybrid search, ingestion, репликация, GPU-ускорение и управление памятью.
Содержание
- Что такое векторная база данных
- Что такое embedding и как выглядит вектор
- Чем Vector DB отличается от SQL и NoSQL
- Cosine similarity, Euclidean distance, dot product
- Как работает поиск в векторной базе
- Почему нужен ANN, а не полный перебор
- Индексы: HNSW, IVF, Product Quantization
- Проблема масштаба, скорости и float’ов
- Сколько памяти нужно для векторов
- Где хранить векторную базу: RAM, SSD, NVMe, HDD, GPU
- Квантование и сжатие: int8, binary, PQ
- GPU для ускорения поиска
- Distributed architecture и шардинг
- Как выглядит AI/RAG pipeline
- Hybrid search: BM25 + vector search
- Почему embedding model критична
- FAISS, Milvus, NVIDIA RAPIDS/cuVS и другие инструменты
- Реальные масштабы и история: 2015–2026
- Когда нужны специализированные vector DB
- Примеры кода
- Краткое резюме
1. Что такое векторная база данных
Векторная база данных хранит объекты не только как строки, JSON или документы, а как
векторы чисел. Эти векторы обычно имеют сотни или тысячи измерений:
384измерения — часто у компактных sentence-transformer моделей;768измерений — типичный размер для многих BERT/E5/BGE-подобных моделей;1024,1536,3072— распространенные размеры для более крупных embedding-моделей;512или768— часто встречается в image embeddings, например CLIP-подобных моделях.
Каждый объект в базе выглядит примерно так:
{
"id": 12345,
"text": "Как подключить оплату в интернет-магазине?",
"embedding": [0.012, -0.184, 0.093, ..., 0.027],
"metadata": {
"source": "docs/payment.md",
"lang": "ru",
"created_at": "2026-01-15",
"category": "payments"
}
}Основная операция в такой базе:
«Найди мне
kобъектов, чьи векторы ближе всего к вектору моего запроса».
Это называется:
- nearest neighbor search — поиск ближайших соседей;
- kNN — k-nearest neighbors, точный поиск k ближайших;
- ANN — approximate nearest neighbors, приближенный, но гораздо более быстрый поиск.
2. Что такое embedding и как выглядит вектор
Embedding — это числовое представление объекта, полученное нейросетевой моделью.
Модель берет текст, картинку, аудио или другой объект и превращает его в массив чисел.
Например, у нас есть три текста:
A: «Как сбросить пароль?»B: «Я забыл пароль, что делать?»C: «Как приготовить пасту карбонара?»
Упрощенно embedding’и могут выглядеть так:
A = [0.82, 0.10, 0.05, 0.01]
B = [0.79, 0.12, 0.07, 0.02]
C = [0.03, 0.11, 0.88, 0.20]Здесь A и B близки друг к другу: оба про восстановление пароля.
C далеко: он про готовку.
В реальности вектор будет не из 4 чисел, а, например, из 768 или 1536 чисел:
[
-0.018127, 0.004512, 0.032881, -0.010904,
0.067338, -0.044210, 0.015003, ...
]Важный момент:
Векторная база сама по себе не «понимает смысл». Смысл создает embedding model.
База только эффективно хранит векторы и быстро ищет ближайшие.
3. Чем Vector DB отличается от SQL и NoSQL
Если вы знаете SQL и NoSQL, полезно сравнить подходы напрямую.
| Тип БД | Что хранит | Как ищет | Типичный вопрос |
|---|---|---|---|
| SQL | Строки, таблицы, связи | Индексы B-tree, hash, joins, filters | «Найди заказ пользователя с ID = 42» |
| NoSQL | Документы, key-value, колонки, графы | По ключу, JSON-полям, secondary indexes | «Дай документ по ключу» или «найди события по user_id» |
| Vector DB | Векторы + metadata + исходные объекты/ссылки | Similarity search, ANN-индексы, hybrid search | «Найди документы, похожие по смыслу на этот запрос» |
Можно хранить массивы чисел и в PostgreSQL, MongoDB или Elasticsearch. Но Vector DB ≠ просто
хранилище float[]. Главная ценность:
- индексы, оптимизированные под поиск ближайших векторов;
- ANN — approximate nearest neighbor search;
- низкая latency на миллионах и миллиардах объектов;
- масштабирование по нодам;
- фильтрация по metadata вместе с vector search;
- hybrid search: keyword + semantic;
- GPU acceleration и/или оптимизация под RAM/SSD;
- real-time ingestion: добавление новых векторов без полной перестройки всей системы.
4. Cosine similarity, Euclidean distance, dot product
Векторная база должна понять, какие векторы «близки». Для этого используются разные метрики.
4.1. Dot product / скалярное произведение
Dot product двух векторов:
A · B = A1 * B1 + A2 * B2 + ... + An * BnПример:
A = [1, 2, 3]
B = [4, 5, 6]
A · B = 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32Чем больше dot product, тем более похожими считаются векторы. Но есть нюанс:
dot product чувствителен к длине вектора. Длинные векторы могут получать больший score не только из-за
направления, но и из-за масштаба.
4.2. Cosine similarity / косинусная близость
Cosine similarity измеряет угол между векторами:
cosine(A, B) = (A · B) / (||A|| * ||B||)Где ||A|| — длина вектора.
Значения:
1.0— векторы направлены одинаково;0.0— векторы перпендикулярны;-1.0— векторы направлены противоположно.
Пример:
A = [1, 0]
B = [0.8, 0.2]
A · B = 1*0.8 + 0*0.2 = 0.8
||A|| = sqrt(1^2 + 0^2) = 1
||B|| = sqrt(0.8^2 + 0.2^2) = sqrt(0.68) ≈ 0.8246
cosine(A, B) = 0.8 / (1 * 0.8246) ≈ 0.970В semantic search косинусная близость используется очень часто.
На практике векторы часто заранее нормализуют до длины 1. Тогда:
cosine(A, B) = A · BТо есть для normalized vectors косинусный поиск можно выполнять через dot product.
4.3. Euclidean distance / евклидово расстояние
Euclidean distance — обычное геометрическое расстояние:
distance(A, B) = sqrt((A1 - B1)^2 + (A2 - B2)^2 + ... + (An - Bn)^2)Пример:
A = [1, 2]
B = [4, 6]
distance(A, B) = sqrt((1-4)^2 + (2-6)^2)
= sqrt(9 + 16)
= 5В отличие от cosine similarity, здесь меньше — лучше.
4.4. Какую метрику выбирать
| Метрика | Когда часто используется | Что означает |
|---|---|---|
| Cosine similarity | Тексты, semantic search, RAG | Похожесть направления векторов |
| Dot product / inner product | Рекомендации, normalized embeddings, ranking | Сходство с учетом направления и длины |
| Euclidean / L2 | Изображения, некоторые ML-задачи, clustering | Геометрическое расстояние между точками |
Универсального ответа нет: метрика должна соответствовать тому, как обучалась embedding-модель.
Если документация модели говорит использовать cosine — используйте cosine. Если модель обучалась под dot product —
используйте dot product.
5. Как работает поиск в векторной базе
Типичный процесс:
- Берем исходные документы, товары, картинки или сообщения.
- Разбиваем их на фрагменты, если нужно. Например, документ на chunks по 300–1000 токенов.
- Прогоняем каждый объект через embedding model.
- Получаем вектор фиксированной размерности.
- Сохраняем вектор в Vector DB вместе с ID и metadata.
- Строим индекс для быстрого поиска.
- При запросе пользователя также строим embedding запроса.
- Ищем ближайшие векторы.
- Возвращаем исходные документы, фрагменты или ID.
- Опционально rerank’им результаты более дорогой моделью.
Упрощенно:
Пользовательский запрос
↓
Embedding model
↓
query_vector = [0.01, -0.04, 0.19, ...]
↓
Vector DB similarity search
↓
Top-5 похожих документов
↓
LLM / приложение / recommender6. Почему нужен ANN, а не полный перебор
Представим, что у нас есть:
- 100 миллионов документов;
- каждый embedding имеет 1536 измерений;
- каждое число хранится как
float32, то есть 4 байта.
Один вектор:
1536 * 4 байта = 6144 байта ≈ 6 КБ100 миллионов векторов:
100 000 000 * 6144 байта = 614 400 000 000 байт ≈ 614.4 ГБОдин точный поиск по всем векторам означает, что нужно прочитать сотни гигабайт и сделать огромное количество
операций.
Для dot product:
100 000 000 векторов * 1536 умножений ≈ 153.6 млрд умножений
100 000 000 векторов * 1536 сложений ≈ 153.6 млрд сложенийЕсли считать multiply-add как две операции, это примерно:
≈ 307 млрд floating-point операцийТеоретически современный CPU или GPU может выполнять много FLOPS, но на практике поиск часто упирается не только
в вычисления, а в пропускную способность памяти. Чтобы сделать brute-force scan по 614 ГБ,
эти 614 ГБ нужно реально прочитать.
Пример грубой оценки по памяти:
| Среда | Типичная пропускная способность | Время чтения 614 ГБ при идеальном последовательном чтении |
|---|---|---|
| HDD | 100–250 МБ/с | десятки минут |
| SATA SSD | 400–550 МБ/с | около 19–26 минут |
| NVMe SSD PCIe 4.0 | 3–7 ГБ/с | примерно 1.5–3.5 минуты |
| DRAM | 50–300+ ГБ/с | примерно 2–12 секунд |
| GPU HBM | 1–4+ ТБ/с у high-end GPU | доли секунды в идеальном случае |
Это очень грубые цифры: реальные системы имеют overhead на индексы, random access, сеть, фильтры,
сериализацию, конкурентные запросы и reranking. Но идея понятна:
полный перебор плохо масштабируется.
Поэтому используется ANN — Approximate Nearest Neighbor.
ANN не всегда гарантирует идеальный top-k, зато позволяет находить очень хорошие результаты на порядки быстрее.
В ANN обычно настраивается баланс:
- recall — насколько часто мы находим те же результаты, что и точный поиск;
- latency — задержка одного запроса;
- throughput — сколько запросов в секунду выдерживает система;
- memory usage — сколько RAM/VRAM/SSD нужно;
- build time — как долго строится индекс;
- update cost — насколько легко добавлять и удалять векторы.
7. Как они устроены внутри: структуры индексации
Внутри векторной базы есть несколько ключевых слоев:
- Vector storage — хранение самих embedding’ов.
- Metadata storage — хранение ID, JSON-полей, ссылок на документы.
- Index — структура для ускорения similarity search.
- Query planner — решает, как совместить vector search и metadata filters.
- Execution engine — выполняет поиск, reranking, merge результатов с шардов.
- Replication/sharding layer — распределение данных по нодам.
- WAL/compaction/segments — механизмы надежной записи и обслуживания данных.
7.1. Flat index / полный перебор
Самый простой вариант — хранить все векторы массивом и при запросе считать расстояние до каждого.
Плюсы:
- точный результат;
- простая реализация;
- хорошо работает на маленьких объемах;
- на GPU может быть очень быстрым для средних объемов.
Минусы:
- плохо масштабируется на сотни миллионов и миллиарды;
- требует чтения большого объема памяти;
- дорогой по latency при больших данных.
7.2. HNSW — Hierarchical Navigable Small World
HNSW — один из самых популярных ANN-индексов для in-memory поиска.
Оригинальная работа по HNSW была опубликована в 2016 году:
Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs,
Malkov, Yashunin.
Идея: строится граф, где вершины — векторы, а ребра соединяют похожие векторы. Поиск похож на навигацию:
мы стартуем с некоторой точки и постепенно переходим к соседям, которые ближе к query vector.
HNSW имеет несколько уровней:
- верхние уровни — разреженные, помогают быстро «перепрыгивать» по пространству;
- нижний уровень — плотный, содержит много связей для точного уточнения;
- поиск идет сверху вниз, постепенно приближаясь к нужной области.
Важные параметры:
| Параметр | Что означает | Типичные значения |
|---|---|---|
M | Сколько соседей хранить для каждой вершины | 16, 32, иногда 48 или 64 |
efConstruction | Сколько кандидатов рассматривать при построении индекса | 100–400+ |
efSearch | Сколько кандидатов рассматривать при поиске | 32–512+ |
Чем больше M, efConstruction и efSearch, тем выше recall,
но больше память, дольше построение и выше latency.
HNSW обычно хорош, когда:
- данные помещаются в RAM;
- нужна низкая latency;
- объем — от сотен тысяч до десятков/сотен миллионов векторов, если есть достаточно памяти;
- нужны хорошие результаты без сильной компрессии.
7.3. IVF — Inverted File Index
IVF расшифровывается как Inverted File Index.
Идея похожа на разбиение пространства на кластеры.
Процесс:
- Берем обучающую выборку векторов.
- Кластеризуем их, например с помощью k-means.
- Получаем
nlistцентроидов — центры кластеров. - Каждый вектор кладем в ближайший кластер/inverted list.
- При поиске сначала находим ближайшие к query кластеры.
- Сканируем только эти списки, а не всю базу.
Важные параметры:
| Параметр | Что означает |
|---|---|
nlist | Количество кластеров/inverted lists |
nprobe | Сколько ближайших кластеров проверять при запросе |
Пример:
- 100 млн векторов;
nlist = 65 536кластеров;- в среднем около 1526 векторов на кластер;
nprobe = 32означает, что мы сканируем примерно 32 * 1526 ≈ 48 832 кандидата,
а не все 100 млн.
Это уже радикально быстрее полного перебора, но качество зависит от кластеризации и nprobe.
7.4. Product Quantization — PQ
Product Quantization — метод сжатия векторов. Он особенно важен для очень больших баз,
где хранить все векторы в float32 слишком дорого.
Упрощенно:
- Вектор размерности
dделится наmпод-векторов. - Для каждого подпространства обучается маленький codebook, например 256 центроидов.
- Каждый под-вектор заменяется ID ближайшего центроида.
- Если codebook имеет 256 центроидов, ID помещается в 1 байт.
Пример:
- исходный вектор:
1536float32; - размер:
1536 * 4 = 6144байта; - делим на
m = 96под-векторов; - каждый под-вектор кодируем 1 байтом;
- итоговый PQ-код:
96байт.
Сжатие:
6144 байта / 96 байт = 64xНа практике добавляются ID, служебные структуры, codebooks и индексы, но выигрыш все равно может быть огромным.
7.5. IVF + PQ
Часто IVF и PQ используются вместе:
- IVF уменьшает количество кандидатов;
- PQ уменьшает размер хранения и ускоряет сканирование кандидатов;
- после грубого поиска можно rerank’ить top-N по исходным float-векторам, если они сохранены отдельно.
Это распространенная стратегия для сотен миллионов и миллиардов векторов.
7.6. DiskANN и SSD-ориентированные индексы
Отдельный класс решений — индексы, которые проектируются с учетом SSD/NVMe.
Один известный пример — DiskANN от Microsoft Research. Идея в том, чтобы держать часть структуры
в памяти, а основные данные читать с SSD так, чтобы минимизировать случайные чтения и эффективно использовать NVMe.
Это важно, когда:
- векторов слишком много для RAM;
- нужно работать с миллиардными масштабами;
- стоимость RAM становится неприемлемой;
- latency должна быть ниже, чем при наивном чтении с диска.
8. Проблема масштаба, скорости и float’ов
Главная техническая проблема vector search — это сочетание трех факторов:
- Много объектов: миллионы, сотни миллионов, миллиарды.
- Высокая размерность: 384, 768, 1536, 3072+ измерений.
- Float storage: каждый
float32занимает 4 байта.
Посмотрим на размер одного вектора:
| Размерность | float32 | float16 / bfloat16 | int8 | binary |
|---|---|---|---|---|
| 384 | 1536 байт | 768 байт | 384 байта | 48 байт |
| 768 | 3072 байта | 1536 байт | 768 байт | 96 байт |
| 1536 | 6144 байта | 3072 байта | 1536 байт | 192 байта |
| 3072 | 12288 байт | 6144 байта | 3072 байта | 384 байта |
Но хранение вектора — это только часть стоимости. Еще нужны:
- ID объекта;
- metadata;
- индекс;
- служебные структуры;
- WAL/segments/compaction data;
- реплики;
- возможная копия исходных float-векторов для reranking;
- кэш.
Поэтому реальная система почти всегда требует больше места, чем «просто размер embedding’ов».
9. Сколько памяти нужно для скольких векторов
Ниже — расчеты без индексов, только массивы embedding’ов.
Для простоты считаем 1 ГБ как 1 000 000 000 байт.
9.1. Только векторы, без индексов и metadata
| Количество векторов | 384 dim float32 | 768 dim float32 | 1536 dim float32 | 3072 dim float32 |
|---|---|---|---|---|
| 1 млн | 1.54 ГБ | 3.07 ГБ | 6.14 ГБ | 12.29 ГБ |
| 10 млн | 15.36 ГБ | 30.72 ГБ | 61.44 ГБ | 122.88 ГБ |
| 100 млн | 153.6 ГБ | 307.2 ГБ | 614.4 ГБ | 1.23 ТБ |
| 1 млрд | 1.54 ТБ | 3.07 ТБ | 6.14 ТБ | 12.29 ТБ |
9.2. Сравнение float32, float16, int8 и binary для 1536 dim
| Количество векторов | float32 | float16 | int8 | binary |
|---|---|---|---|---|
| 1 млн | 6.14 ГБ | 3.07 ГБ | 1.54 ГБ | 0.19 ГБ |
| 10 млн | 61.44 ГБ | 30.72 ГБ | 15.36 ГБ | 1.92 ГБ |
| 100 млн | 614.4 ГБ | 307.2 ГБ | 153.6 ГБ | 19.2 ГБ |
| 1 млрд | 6.14 ТБ | 3.07 ТБ | 1.54 ТБ | 192 ГБ |
Binary выглядит фантастически компактно, но это не бесплатная магия:
качество поиска может заметно ухудшиться, если модель не обучалась/не адаптировалась под binary embeddings.
9.3. Сколько добавляют индексы
Точные цифры зависят от реализации, параметров, типа ID, аллокатора, хранения metadata и режима репликации.
Но полезно иметь ориентиры.
| Тип индекса | Память сверх векторов | Комментарий |
|---|---|---|
| Flat | минимальная | Почти только сами векторы + ID. Поиск точный, но дорогой. |
| HNSW | примерно десятки-сотни байт на вектор, иногда больше | Граф связей. При M=16 только neighbor IDs могут занимать порядка 128+ байт на вектор, но реальный overhead выше. |
| IVF Flat | центроиды + списки ID + сами векторы | Центроиды обычно занимают немного по сравнению с данными. |
| IVF PQ | PQ-коды + ID + codebooks | Может уменьшить хранение векторов в десятки раз, но с потерей точности. |
| DiskANN-like | часть графа/кэша в RAM, основное на SSD | Оптимизировано под миллиардные масштабы и NVMe. |
9.4. Пример оценки HNSW
Допустим:
- 100 млн векторов;
- 1536 dim;
- float32;
- сырые векторы: 614.4 ГБ;
- HNSW
M=16; - ID соседа — 4 байта.
В HNSW на нижнем уровне часто хранится больше связей, чем M, например порядка 2M,
плюс дополнительные уровни. Очень грубо можно ожидать:
32 neighbor IDs * 4 байта = 128 байт на вектор только на нижний уровеньДля 100 млн:
100 000 000 * 128 байт = 12.8 ГБС дополнительными уровнями, служебными структурами, выравниванием памяти и реализационным overhead это может быть
заметно больше: например 20–50+ ГБ сверх самих векторов. Если M=32, overhead увеличивается.
Важный вывод:
Для больших dense embeddings основную память часто занимают сами float-векторы.
Но для небольших размерностей, сильного сжатия или большихMиндекс тоже становится очень заметной частью стоимости.
9.5. Пример оценки IVF-PQ
Допустим:
- 100 млн векторов;
- 1536 dim float32 — 614.4 ГБ в сыром виде;
- PQ:
m = 96, 8 бит на subvector; - PQ-код одного вектора — 96 байт;
- ID — 8 байт.
Тогда:
PQ codes: 100 000 000 * 96 байт = 9.6 ГБ
IDs: 100 000 000 * 8 байт = 0.8 ГБ
Итого только codes + IDs ≈ 10.4 ГБДобавятся codebooks, IVF lists, metadata, служебные структуры.
Но даже если итог будет 15–30 ГБ, это все равно на порядок меньше, чем 614.4 ГБ.
Цена — потеря точности. Часто делают так:
- IVF-PQ быстро находит top-100 или top-1000 кандидатов.
- Затем кандидаты rerank’ятся по исходным float-векторам или более точной модели.
10. Где хранить векторные базы: RAM, SSD, NVMe, HDD, GPU
Выбор хранения критичен, потому что vector search очень чувствителен к bandwidth и latency.
10.1. HDD
HDD плохо подходит для низколатентного vector search.
- Последовательное чтение: примерно 100–250 МБ/с.
- Random access latency: миллисекунды.
- IOPS: на порядки ниже SSD.
HDD можно использовать:
- для архивов;
- для cold storage;
- для бэкапов;
- для нечасто используемых сегментов;
- если latency не важна.
Для интерактивного semantic search HDD обычно плохой выбор.
10.2. SATA SSD
SATA SSD лучше HDD, но ограничен интерфейсом:
- около 400–550 МБ/с последовательного чтения;
- значительно лучше random access, чем HDD;
- но для больших vector scans все еще медленно.
SATA SSD может быть нормален для:
- небольших проектов;
- хранения сегментов;
- metadata;
- бэкапов;
- индексов, которые большую часть горячих данных держат в RAM.
10.3. NVMe SSD
NVMe SSD — стандартный выбор для серьезных систем, где весь индекс не помещается в RAM
или где нужно быстро загружать сегменты.
- PCIe 3.0 NVMe: часто 2–3.5 ГБ/с.
- PCIe 4.0 NVMe: часто 5–7 ГБ/с.
- PCIe 5.0 NVMe: может достигать 10–14 ГБ/с в consumer/enterprise устройствах.
- Enterprise NVMe важны не только bandwidth, но и latency, endurance, sustained performance, IOPS.
NVMe особенно важен для:
- DiskANN-подобных индексов;
- больших сегментированных хранилищ;
- быстрой загрузки индексов после рестарта;
- spillover, когда RAM недостаточно;
- кластеров с большими объемами embedding’ов.
10.4. RAM
Оперативная память — лучший вариант для low-latency HNSW и многих production-сценариев.
- Пропускная способность: десятки-сотни ГБ/с.
- Latency: наносекунды-десятки наносекунд.
- Минус: дорого по сравнению с SSD.
Если вам нужен поиск за миллисекунды по миллионам или десяткам миллионов векторов, часто приходится держать
горячий индекс в RAM.
10.5. GPU VRAM
GPU хорош для массовых матричных операций, brute-force search, построения индексов,
batch-запросов и некоторых ANN-алгоритмов.
- GPU HBM bandwidth у high-end карт может быть 1–4+ ТБ/с.
- VRAM дорогая и ограниченная: 24 ГБ, 48 ГБ, 80 ГБ, 96+ ГБ в зависимости от карты.
- Передача CPU ↔ GPU через PCIe/NVLink тоже имеет стоимость.
GPU особенно полезен:
- для больших batch-запросов;
- для brute-force exact search по средним объемам;
- для IVF/PQ в FAISS GPU;
- для ускоренного построения индексов;
- для workloads, где данные помещаются в VRAM или эффективно шардуются по нескольким GPU.
10.6. Сравнение уровней хранения
| Уровень | Скорость | Latency | Цена за ГБ | Подходит для |
|---|---|---|---|---|
| HDD | низкая | плохая | низкая | архив, бэкапы, cold storage |
| SATA SSD | средняя | хорошая | средняя | малые/средние проекты, metadata, сегменты |
| NVMe SSD | высокая | очень хорошая | средняя/выше средней | production-хранилище, DiskANN, большие индексы |
| RAM | очень высокая | отличная | высокая | low-latency HNSW, hot index |
| GPU VRAM | экстремально высокая | отличная внутри GPU | очень высокая | GPU search, batch, brute-force, FAISS GPU, cuVS |
11. Квантование и сжатие: int8, binary, PQ
Квантование — это преобразование чисел из более точного формата в менее точный.
Цель: уменьшить память, ускорить вычисления и повысить cache locality.
11.1. float32
Стандартный формат:
- 4 байта на число;
- хорошая точность;
- большой объем хранения.
Для 1536 dim:
1536 * 4 = 6144 байта на вектор11.2. float16 / bfloat16
Половинная точность:
- 2 байта на число;
- примерно в 2 раза меньше памяти;
- часто приемлемое качество для retrieval;
- хорошо поддерживается GPU.
Для 1536 dim:
1536 * 2 = 3072 байта на вектор11.3. int8 quantization
int8 хранит каждую компоненту в 1 байте.
- в 4 раза меньше float32;
- может ускорить вычисления;
- нужны scale/zero-point или другая схема восстановления;
- качество зависит от распределения embedding’ов и метода квантования.
Упрощенная схема:
float_value ≈ scale * (int8_value - zero_point)Для 1536 dim:
1536 * 1 = 1536 байт на вектор11.4. Binary embeddings
Binary-представление хранит один бит на измерение.
Для 1536 dim:
1536 бит / 8 = 192 байтаЭто в 32 раза меньше, чем float32:
6144 / 192 = 32xПоиск можно ускорять через Hamming distance и битовые операции.
Но есть риск существенной потери качества, если просто взять знак float-компонент без правильного обучения.
11.5. Product Quantization
PQ — более структурированное сжатие, чем обычный int8 по каждой координате.
Оно кодирует не каждую координату отдельно, а под-векторы.
Пример для 768 dim:
- исходный размер float32:
768 * 4 = 3072байта; m = 64под-вектора;- 8 бит на код каждого под-вектора;
- PQ-код:
64байта; - сжатие:
3072 / 64 = 48x.
PQ часто используется, когда:
- векторов сотни миллионов или миллиарды;
- RAM/VRAM ограничены;
- допустима небольшая потеря recall;
- можно сделать reranking top candidates.
11.6. Компромисс качества
Любое сжатие — это компромисс:
| Формат | Экономия памяти | Скорость | Риск потери качества |
|---|---|---|---|
| float32 | нет | базовая | минимальный |
| float16 | 2x | часто лучше на GPU | обычно небольшой |
| int8 | 4x | может быть лучше | средний |
| binary | 32x для float32 | очень высокая на bit ops | может быть высокий |
| PQ | 10x–100x в зависимости от параметров | часто высокая | настраиваемый, зависит от m и codebooks |
12. GPU для ускорения поиска
GPU применяется в vector search по нескольким причинам:
- очень высокая пропускная способность памяти;
- много параллельных вычислительных блоков;
- эффективные matrix multiplication и dot product;
- поддержка float16/bfloat16/int8;
- ускорение training/build для некоторых индексов.
12.1. Когда GPU дает большой выигрыш
- Большие batch-запросы.
- Exact search по миллионам векторов, помещающимся в VRAM.
- IVF/PQ с GPU-реализацией.
- Рекомендательные системы с высоким QPS.
- Offline retrieval, evaluation, reindexing.
12.2. Когда GPU может не помочь
- Если данные не помещаются в VRAM и постоянно гоняются по PCIe.
- Если запросы одиночные и маленькие, а overhead передачи данных больше вычисления.
- Если bottleneck — metadata filters, сеть или storage.
- Если индекс оптимизирован под CPU/RAM и уже дает нужную latency.
12.3. FAISS GPU
FAISS от Meta AI — один из самых известных инструментов для similarity search.
Он поддерживает CPU и GPU индексы, включая Flat, IVF, PQ и их комбинации.
FAISS часто используют:
- как embedded-библиотеку внутри своих сервисов;
- для offline экспериментов;
- как backend в production-системах;
- для больших batch retrieval задач.
12.4. NVIDIA RAPIDS и cuVS
В экосистеме NVIDIA RAPIDS для vector search важны библиотеки RAFT/cuVS.
cuVS — это GPU-ускоренные алгоритмы для nearest-neighbor search, clustering и related workloads.
API менялись по мере развития RAPIDS, поэтому в production важно смотреть документацию именно вашей версии.
Обычно такие инструменты применяются, когда:
- нужно строить индексы на GPU;
- нужен ANN/точный kNN на GPU;
- данные уже находятся в GPU pipeline;
- используются RAPIDS cuDF/cuML и хочется избежать лишних копирований CPU ↔ GPU.
13. Distributed architecture и шардинг
Когда данных становится слишком много для одной машины, векторная база превращается в распределенную систему.
13.1. Шардинг
Шардинг означает, что данные делятся по нодам.
Shard 1: vectors 0–99M
Shard 2: vectors 100M–199M
Shard 3: vectors 200M–299M
Shard 4: vectors 300M–399MПри запросе:
- Query vector отправляется на все релевантные шарды.
- Каждый шард ищет свой локальный top-k.
- Координатор собирает результаты.
- Делает global merge по score.
- Возвращает итоговый top-k.
Query
↓
Coordinator
↓ ↓ ↓ ↓
Shard1 Shard2 Shard3 Shard4
↓ ↓ ↓ ↓
top-k top-k top-k top-k
↓ ↓ ↓ ↓
Global merge
↓
Final top-k13.2. Репликация
Репликация нужна для:
- отказоустойчивости;
- повышения read throughput;
- обслуживания rolling updates;
- снижения риска потери данных.
Если replication factor = 2, то хранение примерно удваивается.
Если raw vectors занимают 600 ГБ, с двумя репликами это уже около 1.2 ТБ только на векторы.
13.3. Проблема фильтров
В реальных приложениях почти всегда нужны metadata-фильтры:
Найди похожие документы,
где lang = "ru",
category = "legal",
created_at > "2025-01-01"Это сложнее, чем просто vector search.
Есть два подхода:
- Pre-filtering: сначала отфильтровать документы, потом искать векторы.
- Post-filtering: сначала найти кандидатов по vector search, потом отфильтровать.
Оба подхода имеют проблемы:
- pre-filtering может разрушить эффективность ANN-индекса;
- post-filtering может вернуть мало результатов, если фильтр строгий;
- сложные production-системы комбинируют стратегии.
13.4. Real-time ingestion
В production данные часто постоянно добавляются:
- новые документы;
- новые товары;
- новые пользовательские события;
- новые chunks для RAG;
- обновления embedding-модели.
Реальная vector DB должна решать:
- как быстро добавить вектор в индекс;
- как удалять и обновлять объекты;
- как делать compaction;
- как поддерживать consistency;
- как переиндексировать данные при смене embedding model;
- как не останавливать поиск во время rebuild.
14. Как выглядит pipeline в AI: RAG
Один из самых популярных сценариев vector DB — RAG,
Retrieval-Augmented Generation.
RAG нужен, чтобы LLM отвечала не только из своих параметров, а с опорой на внешние документы.
14.1. Индексация документов
Документы
↓
Очистка текста
↓
Разбиение на chunks
↓
Embedding model
↓
Vector DB
↓
ИндексПример chunk:
{
"chunk_id": "doc_17_chunk_004",
"document_id": "doc_17",
"text": "Для сброса пароля откройте страницу восстановления...",
"embedding": [0.031, -0.012, 0.088, ...],
"metadata": {
"source": "help/password-reset.md",
"lang": "ru",
"section": "account"
}
}14.2. Обработка запроса пользователя
Вопрос пользователя:
"Как мне восстановить пароль?"
↓
Embedding model:
query_vector = [0.028, -0.015, 0.091, ...]
↓
Vector DB:
top-5 похожих chunks
↓
Prompt для LLM:
"Ответь на вопрос, используя только этот контекст..."
↓
LLM:
"Чтобы восстановить пароль, откройте страницу..."14.3. Типичная логика RAG
- Пользователь задает вопрос.
- Система строит embedding вопроса.
- Vector DB ищет top-k похожих фрагментов.
- Опционально применяется keyword search или metadata filters.
- Опционально применяется reranker.
- Лучшие фрагменты добавляются в prompt.
- LLM генерирует ответ.
- Система возвращает ответ и, желательно, ссылки на источники.
14.4. Почему RAG не работает «сам по себе»
Проблемы часто не в vector DB, а в pipeline:
- плохое разбиение на chunks;
- неподходящая embedding model;
- не та метрика similarity;
- слишком маленький top-k;
- нет reranking;
- устаревшие документы;
- плохая очистка текста;
- неправильные metadata filters;
- LLM игнорирует контекст или галлюцинирует.
15. Hybrid search: BM25 + semantic vector search
Hybrid search — очень популярная вещь в современных AI-приложениях.
Он объединяет:
- keyword search, например BM25;
- semantic vector search по embedding’ам.
Зачем это нужно?
Vector search хорошо понимает смысловую близость:
"забыл пароль" ≈ "восстановление доступа"Но keyword search лучше ловит:
- точные артикулы;
- имена функций;
- ошибки вида
ERR_AUTH_401; - названия API-методов;
- юридические формулировки;
- редкие термины.
Пример запроса:
"Ошибка ERR_PAYMENT_102 при оплате картой"Векторный поиск может понять, что речь про оплату, но BM25 точно найдет ERR_PAYMENT_102.
Поэтому часто делают так:
- BM25 возвращает top-100 документов.
- Vector search возвращает top-100 документов.
- Результаты объединяются.
- Score нормализуются.
- Применяется fusion-алгоритм, например Reciprocal Rank Fusion.
- Опционально top-20 отправляются в reranker.
15.1. Reciprocal Rank Fusion
Один простой способ объединить результаты — RRF:
RRF_score(doc) = Σ 1 / (k + rank_i(doc))Где:
rank_i— позиция документа в конкретном списке результатов;k— константа, часто около 60;- сумма берется по всем системам поиска: BM25, vector, etc.
Hybrid search часто дает более стабильное качество, чем чистый vector search.
16. Embedding model критична
Векторная БД не создает смысл. Она не знает, что такое «пароль», «договор», «кот» или «оплата».
Она просто хранит точки и ищет ближайшие.
Смысл создает embedding model:
- OpenAI embeddings;
- BERT/Sentence-BERT;
- E5;
- BGE;
- Jina embeddings;
- Cohere embeddings;
- CLIP для image-text retrieval;
- domain-specific embeddings, обученные под конкретную область.
Если embedding model плохая или неподходящая, vector DB будет очень быстро находить плохие результаты.
16.1. Что важно при выборе модели
- Язык: хорошо ли модель работает с русским?
- Домен: понимает ли юридические, медицинские, технические тексты?
- Размерность: 384, 768, 1536, 3072 — влияет на память и скорость.
- Метрика: cosine, dot product, L2.
- Максимальная длина входа: сколько токенов можно embedding’ить за раз.
- Стоимость: особенно для SaaS embedding API.
- Latency: важно для real-time сценариев.
- Лицензия: важно для on-prem и commercial use.
- Стабильность версий: смена модели означает переиндексацию всех векторов.
16.2. Смена embedding model = новый индекс
Если вы меняете embedding model, старые и новые векторы обычно нельзя смешивать.
Даже если размерность совпадает, геометрия пространства может быть другой.
На практике смена модели означает:
- пересчитать embeddings для всех документов;
- создать новый индекс;
- протестировать recall/precision;
- провести A/B test;
- переключить traffic;
- удалить старый индекс после стабилизации.
17. FAISS, Milvus, NVIDIA RAPIDS/cuVS и другие инструменты
17.1. FAISS
FAISS — библиотека от Meta AI, опубликованная в 2017 году.
Она стала одним из стандартных инструментов для similarity search.
FAISS — это не полноценная распределенная база данных «из коробки» в стиле managed DB.
Это библиотека индексов. Вы сами решаете:
- где хранить metadata;
- как делать API;
- как шардировать;
- как реплицировать;
- как обновлять индексы;
- как мониторить production.
Зато FAISS очень мощный и гибкий:
- Flat;
- HNSW;
- IVF;
- PQ;
- OPQ;
- GPU search;
- различные метрики.
17.2. Milvus
Milvus — open-source vector database, ориентированная на production-сценарии.
Она поддерживает разные индексы, distributed deployment, metadata, collection management,
ingestion и интеграции.
Milvus часто выбирают, когда нужна именно база, а не только библиотека:
- коллекции;
- схемы;
- индексы;
- шардинг;
- репликация;
- management API;
- фильтры;
- интеграция с cloud/on-prem инфраструктурой.
17.3. NVIDIA RAPIDS/cuVS
NVIDIA RAPIDS — набор GPU-ускоренных библиотек для data science и analytics.
Для nearest neighbor search важны RAFT/cuVS. Это не «база данных» в классическом смысле,
а набор высокопроизводительных GPU-алгоритмов, которые можно использовать как часть своей системы.
Подходит, если:
- у вас уже есть GPU-инфраструктура;
- нужно ускорять ANN/kNN;
- нужно обрабатывать большие batch’и;
- вы строите собственный retrieval engine;
- вы хотите интеграцию с RAPIDS/cuDF/cuML.
17.4. Другие популярные решения
Кроме FAISS и Milvus, в экосистеме часто встречаются:
- pgvector — расширение PostgreSQL для vector search;
- Qdrant — vector DB на Rust с фильтрами и payload;
- Weaviate — vector database с GraphQL/REST и модулями;
- Elasticsearch / OpenSearch vector search — удобно для hybrid keyword + vector;
- Pinecone — managed vector database;
- Vespa — search engine с vector, ranking и large-scale serving;
- Redis Vector Search — vector search внутри Redis Stack;
- Chroma — популярна в прототипах и RAG-проектах;
- LanceDB — vector DB с columnar storage и AI-oriented workloads;
- ScaNN — библиотека Google для efficient vector similarity search.
Выбор зависит от задачи: embedded library, managed cloud, on-prem, hybrid search, масштаб, latency, стоимость,
лицензия и компетенции команды.
18. Реальные масштабы и история: 2015–2026
Точные внутренние масштабы крупных компаний часто не раскрываются или частично скрыты за NDA.
Но по открытым публикациям, инструментам и индустриальным трендам можно восстановить реалистичную картину.
| Год | Что происходило | Типичные масштабы и контекст |
|---|---|---|
| 2015 | Embeddings уже широко используются: word2vec, GloVe, ранние recommender systems, image retrieval. | Многие системы работают с миллионами-десятками миллионов векторов. Часто используются специализированные in-house решения, Annoy, LSH, KD-tree/ball-tree для меньших размерностей. |
| 2016 | Публикация HNSW. Графовые ANN-методы становятся очень важными. | HNSW показывает отличное соотношение recall/latency для in-memory поиска. Масштабы в десятки миллионов становятся практичнее при наличии RAM. |
| 2017 | Meta AI публикует FAISS. Векторный поиск становится намного доступнее для исследователей и инженеров. | FAISS активно применяется для миллионов и миллиардов векторов, особенно с IVF/PQ и GPU. |
| 2018 | Рост deep learning retrieval, face/image embeddings, recommendations. | Крупные компании имеют внутренние retrieval-системы на сотни миллионов и миллиарды объектов. Открытые инструменты становятся зрелее. |
| 2019 | Появляются/растут специализированные vector DB: Milvus, Weaviate, Pinecone. Microsoft Research публикует работы по DiskANN. | Фокус смещается от библиотек к production databases: API, кластеризация, metadata, ingestion, deployment. |
| 2020 | Google публикует ScaNN. Semantic search становится более практичным. | ANN-инструменты активно используются в search/recommendation. Миллионы-десятки миллионов векторов становятся обычным production-объемом. |
| 2021 | Растет интерес к pgvector, Qdrant, cloud vector search. Sentence transformers становятся массовыми. | Многие команды начинают хранить embeddings в Postgres/Elasticsearch/специализированных vector DB. |
| 2022 | LLM начинают резко менять спрос на semantic retrieval. | RAG еще не стал массовым словом, но semantic search уже активно используется в enterprise knowledge search. |
| 2023 | Взрыв RAG после массового распространения ChatGPT-подобных систем. | Vector DB становятся обязательным элементом AI stack. Даже небольшие команды начинают индексировать документацию, базы знаний, тикеты, чаты. |
| 2024 | Hybrid search, reranking, evaluations и production RAG становятся стандартом. | Типичные production-системы: от сотен тысяч до сотен миллионов chunks. Для миллиардов нужны distributed architecture, compression, GPU/SSD-aware индексы. |
| 2025 | Тренд на multimodal retrieval, agent memory, enterprise RAG, on-prem deployments. | Многие компании уходят от простых демо к сложным retrieval pipelines: ACL, freshness, citations, observability, evals, feedback loops. |
| 2026 | Vector search становится базовой инфраструктурой AI-приложений, как раньше full-text search стал базовой частью веб-приложений. | Реалистичные масштабы: миллионы — обычный уровень; десятки/сотни миллионов — серьезный production; миллиарды — специализированная distributed инфраструктура с компрессией, шардированием и often GPU/NVMe optimization. |
Важно: утверждения вроде «компания X хранит 50 миллиардов embedding’ов» часто невозможно проверить без внутренних данных.
Поэтому для архитектуры полезнее считать ресурсы самостоятельно: размерность, формат, индекс, реплики, QPS, latency,
refresh rate и стоимость железа.
18.1. Практические уровни масштаба
| Масштаб | Количество векторов | Типичное решение |
|---|---|---|
| Малый | до 100 тыс. | Postgres + pgvector, Chroma, FAISS Flat, локальный сервис |
| Средний | 100 тыс. – 10 млн | HNSW, pgvector/Qdrant/Milvus/Weaviate, RAM/NVMe |
| Большой | 10 млн – 100 млн | HNSW при достаточной RAM, IVF, distributed vector DB, hybrid search, careful filtering |
| Очень большой | 100 млн – 1 млрд | Шардинг, IVF-PQ, DiskANN-like, GPU, NVMe, репликация, observability |
| Гипермасштаб | 1 млрд+ | Специализированная инфраструктура, компрессия, много нод, partitioning, GPU/SSD-aware design, in-house оптимизации |
19. Когда нужны специализированные vector DB
Не всегда нужно сразу брать Milvus, Qdrant, Pinecone или строить кластер.
Иногда достаточно PostgreSQL с pgvector или FAISS в одном сервисе.
19.1. Когда можно начать просто
- до сотен тысяч embeddings;
- низкий QPS;
- прототип RAG;
- нет жестких требований по latency;
- простые metadata filters;
- команда уже хорошо знает PostgreSQL;
- данные легко переиндексировать.
19.2. Когда нужны специализированные решения
Специализированная vector DB становится оправданной, когда есть:
- десятки/сотни миллионов embedding’ов;
- low latency, например десятки миллисекунд;
- distributed cluster;
- real-time ingestion;
- hybrid search;
- GPU acceleration;
- сложные metadata filters;
- репликация и отказоустойчивость;
- мультиарендность;
- наблюдаемость: latency, recall, QPS, index size, cache hit rate;
- переиндексация без downtime.
19.3. Типичные сценарии
- RAG: поиск релевантных фрагментов документов для LLM.
- Semantic search: поиск по смыслу в документации, товарах, FAQ.
- AI agents memory: долговременная память агента.
- Recommendation systems: похожие товары, пользователи, видео, статьи.
- Image retrieval: поиск похожих изображений.
- Deduplication: поиск почти одинаковых документов или картинок.
- Fraud/anomaly detection: поиск похожих паттернов.
- Code search: поиск похожих функций, issues, snippets.
- Support automation: поиск похожих тикетов и ответов.
20. Примеры кода
20.1. Расчет cosine similarity, Euclidean distance и dot product на Python
import numpy as np
a = np.array([0.82, 0.10, 0.05, 0.01], dtype=np.float32)
b = np.array([0.79, 0.12, 0.07, 0.02], dtype=np.float32)
c = np.array([0.03, 0.11, 0.88, 0.20], dtype=np.float32)
def dot_product(x, y):
return float(np.dot(x, y))
def cosine_similarity(x, y):
return float(np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y)))
def euclidean_distance(x, y):
return float(np.linalg.norm(x - y))
print("dot(a, b):", dot_product(a, b))
print("cosine(a, b):", cosine_similarity(a, b))
print("l2(a, b):", euclidean_distance(a, b))
print("dot(a, c):", dot_product(a, c))
print("cosine(a, c):", cosine_similarity(a, c))
print("l2(a, c):", euclidean_distance(a, c))Ожидаемо a ближе к b, чем к c.
20.2. Нормализация векторов для cosine search
import numpy as np
vectors = np.array([
[0.82, 0.10, 0.05, 0.01],
[0.79, 0.12, 0.07, 0.02],
[0.03, 0.11, 0.88, 0.20],
], dtype=np.float32)
def normalize(x):
norms = np.linalg.norm(x, axis=1, keepdims=True)
return x / np.maximum(norms, 1e-12)
normalized_vectors = normalize(vectors)
query = np.array([[0.80, 0.09, 0.06, 0.01]], dtype=np.float32)
query = normalize(query)
# Для normalized vectors dot product == cosine similarity
scores = normalized_vectors @ query.T
print(scores.ravel())20.3. Пример FAISS: HNSW index
Пример показывает локальный HNSW-поиск. Для cosine similarity нормализуем векторы и используем inner product.
import numpy as np
import faiss
# Данные
d = 128 # размерность embedding
n = 100_000 # количество векторов
k = 5 # сколько соседей искать
np.random.seed(42)
xb = np.random.random((n, d)).astype("float32")
xq = np.random.random((1, d)).astype("float32")
# Нормализация для cosine similarity
faiss.normalize_L2(xb)
faiss.normalize_L2(xq)
# HNSW index
M = 32
index = faiss.IndexHNSWFlat(d, M, faiss.METRIC_INNER_PRODUCT)
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 64
index.add(xb)
distances, ids = index.search(xq, k)
print("IDs:", ids)
print("Scores:", distances)Здесь distances для METRIC_INNER_PRODUCT — это scores, где больше значит лучше.
20.4. Пример FAISS: IVF-PQ
IVF-PQ требует обучения индекса на выборке данных.
import numpy as np
import faiss
d = 128
n = 1_000_000
k = 10
np.random.seed(42)
xb = np.random.random((n, d)).astype("float32")
xq = np.random.random((5, d)).astype("float32")
# Для cosine similarity используем normalization + inner product
faiss.normalize_L2(xb)
faiss.normalize_L2(xq)
nlist = 4096 # количество IVF кластеров
m = 16 # количество PQ subquantizers
nbits = 8 # 8 бит на subquantizer
quantizer = faiss.IndexFlatIP(d)
index = faiss.IndexIVFPQ(
quantizer,
d,
nlist,
m,
nbits,
faiss.METRIC_INNER_PRODUCT
)
# train обязателен для IVF/PQ
train_sample = xb[np.random.choice(n, size=100_000, replace=False)]
index.train(train_sample)
index.add(xb)
# nprobe: сколько кластеров проверять
index.nprobe = 32
distances, ids = index.search(xq, k)
print(ids)
print(distances)Увеличение nprobe обычно повышает recall, но увеличивает latency.
20.5. Пример Milvus: коллекция с вектором и HNSW
API Milvus развивается, поэтому для production проверяйте документацию вашей версии.
Ниже — концептуальный пример через pymilvus.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
collection_name = "articles_demo"
# Если коллекция уже есть, удалим для демо
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = client.create_schema(
auto_id=False,
enable_dynamic_field=True
)
schema.add_field(
field_name="id",
datatype=DataType.INT64,
is_primary=True
)
schema.add_field(
field_name="text",
datatype=DataType.VARCHAR,
max_length=2048
)
schema.add_field(
field_name="embedding",
datatype=DataType.FLOAT_VECTOR,
dim=4
)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="HNSW",
metric_type="COSINE",
params={
"M": 16,
"efConstruction": 200
}
)
client.create_collection(
collection_name=collection_name,
schema=schema,
index_params=index_params
)
data = [
{
"id": 1,
"text": "Как сбросить пароль?",
"embedding": [0.82, 0.10, 0.05, 0.01],
"category": "account"
},
{
"id": 2,
"text": "Я забыл пароль, что делать?",
"embedding": [0.79, 0.12, 0.07, 0.02],
"category": "account"
},
{
"id": 3,
"text": "Как приготовить пасту карбонара?",
"embedding": [0.03, 0.11, 0.88, 0.20],
"category": "cooking"
}
]
client.insert(collection_name=collection_name, data=data)
client.load_collection(collection_name)
query_vector = [[0.80, 0.09, 0.06, 0.01]]
results = client.search(
collection_name=collection_name,
data=query_vector,
anns_field="embedding",
limit=2,
search_params={
"metric_type": "COSINE",
"params": {
"ef": 64
}
},
output_fields=["text", "category"]
)
for hit in results[0]:
print(hit["id"], hit["distance"], hit["entity"])20.6. Пример pgvector в PostgreSQL
Для небольших и средних проектов удобно начать с PostgreSQL и pgvector.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE articles (
id bigserial PRIMARY KEY,
title text,
content text,
embedding vector(4)
);
INSERT INTO articles (title, content, embedding)
VALUES
('Password reset', 'Как сбросить пароль?', '[0.82,0.10,0.05,0.01]'),
('Forgot password', 'Я забыл пароль, что делать?', '[0.79,0.12,0.07,0.02]'),
('Carbonara', 'Как приготовить пасту карбонара?', '[0.03,0.11,0.88,0.20]');
-- Поиск ближайших по cosine distance.
-- В pgvector оператор <=> обычно используется для cosine distance.
SELECT id, title, content, embedding <=> '[0.80,0.09,0.06,0.01]' AS distance
FROM articles
ORDER BY embedding <=> '[0.80,0.09,0.06,0.01]'
LIMIT 2;Для ускорения можно создавать HNSW или IVFFlat индексы, если ваша версия pgvector их поддерживает:
CREATE INDEX articles_embedding_hnsw_idx
ON articles
USING hnsw (embedding vector_cosine_ops);20.7. Пример NVIDIA RAPIDS/cuVS: концептуальный GPU kNN
API RAPIDS/cuVS может отличаться между версиями. Ниже — примерный смысл:
данные находятся на GPU, строится индекс или используется brute-force search.
import cupy as cp
# Пример данных на GPU
n = 1_000_000
d = 128
k = 10
xb = cp.random.random((n, d), dtype=cp.float32)
xq = cp.random.random((1, d), dtype=cp.float32)
# Нормализация для cosine через dot product
xb = xb / cp.linalg.norm(xb, axis=1, keepdims=True)
xq = xq / cp.linalg.norm(xq, axis=1, keepdims=True)
# Brute-force scores на GPU:
# scores shape: (1, n)
scores = xq @ xb.T
# top-k
topk_indices = cp.argpartition(scores[0], -k)[-k:]
topk_scores = scores[0, topk_indices]
# сортировка top-k по убыванию
order = cp.argsort(-topk_scores)
topk_indices = topk_indices[order]
topk_scores = topk_scores[order]
print(topk_indices)
print(topk_scores)Это не замена полноценному ANN-индексу, но показывает, почему GPU удобен:
dot product по миллионам векторов превращается в матричную операцию.
Для production лучше смотреть FAISS GPU или cuVS ANN-индексы конкретной версии.
20.8. Упрощенный RAG pipeline на Python
def chunk_document(text, chunk_size=800, overlap=100):
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunks.append(text[start:end])
start = end - overlap
return chunks
def embed_texts(texts, embedding_client):
# embedding_client — любой клиент:
# OpenAI, Cohere, локальная BGE/E5/Jina модель и т.д.
return embedding_client.embed(texts)
def index_documents(documents, vector_db, embedding_client):
records = []
for doc in documents:
chunks = chunk_document(doc["text"])
embeddings = embed_texts(chunks, embedding_client)
for i, (chunk, emb) in enumerate(zip(chunks, embeddings)):
records.append({
"id": f"{doc['id']}_{i}",
"document_id": doc["id"],
"text": chunk,
"embedding": emb,
"metadata": {
"source": doc["source"],
"lang": doc.get("lang", "ru")
}
})
vector_db.upsert(records)
def answer_question(question, vector_db, embedding_client, llm):
query_embedding = embed_texts([question], embedding_client)[0]
hits = vector_db.search(
vector=query_embedding,
top_k=5,
filters={
"lang": "ru"
}
)
context = "\n\n".join(hit["text"] for hit in hits)
prompt = f"""
Ответь на вопрос, используя только контекст ниже.
Если ответа нет в контексте, скажи, что информации недостаточно.
Контекст:
{context}
Вопрос:
{question}
"""
return llm.generate(prompt)21. Краткое резюме
Векторная база данных — это фундаментальная часть современного AI stack.
Именно такие системы делают возможными:
- RAG;
- semantic search;
- AI agents memory;
- recommendation systems;
- image retrieval;
- поиск похожих документов;
- поиск по смыслу в корпоративных знаниях;
- мультимодальный поиск.
Главное, что нужно запомнить:
Vector DB — это highly optimized engine для nearest-neighbor search в высокоразмерном пространстве.
Ее ценность не в том, что она хранит массивы float’ов, а в том, что она умеет быстро искать похожие объекты
на больших масштабах.
Ключевые компоненты:
- embedding model создает смысловое пространство;
- vector DB хранит embeddings и metadata;
- similarity metric определяет, что такое «похожесть»;
- ANN index делает поиск быстрым;
- quantization снижает память и стоимость;
- GPU/NVMe/RAM определяют реальные performance limits;
- distributed architecture нужна для сотен миллионов и миллиардов векторов;
- hybrid search часто дает лучшее качество, чем чистый vector search;
- RAG pipeline зависит не только от базы, но и от chunking, embeddings, reranking и prompt design.
Если вы только начинаете, не нужно сразу строить миллиардный кластер.
Начните с простой архитектуры:
- выберите хорошую embedding model под ваш язык и домен;
- сделайте корректный chunking;
- индексируйте данные в pgvector, FAISS, Qdrant, Milvus или другом инструменте;
- измерьте качество retrieval;
- добавьте hybrid search и reranking;
- только потом оптимизируйте индексы, память, GPU и шардирование.
Векторная база — это не магия и не «ИИ внутри базы». Это инженерная система, которая очень быстро отвечает
на вопрос:
«Какие объекты в моей базе находятся ближе всего к этому смысловому запросу?»
И именно этот простой вопрос лежит в основе огромного количества современных AI-приложений.