Векторные базы данных в ИИ: что это такое, как они устроены, как работают и зачем нужны

09-05-2026, 1:56
Просмотров: 1
Векторная база данных — это специализированный движок для хранения и быстрого поиска
похожих объектов в высокоразмерном пространстве. В контексте искусственного интеллекта она чаще всего
хранит embedding’и: числовые представления текстов, изображений, аудио, товаров, пользователей,
документов или фрагментов знаний.

Если совсем коротко:

SQL — библиотекарь ищет книгу по точному номеру полки, ID, дате или категории.
Vector DB — библиотекарь ищет книги, «похожие по смыслу» на ваш запрос.

Для архитектора важнейшая мысль такая:

Векторная база данных — это не просто хранилище float[]. Это highly optimized engine
для nearest-neighbor search в высокоразмерном пространстве: индексы, ANN-поиск,
масштабирование, фильтрация, hybrid search, ingestion, репликация, GPU-ускорение и управление памятью.

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. Как работает поиск в векторной базе

Типичный процесс:

  1. Берем исходные документы, товары, картинки или сообщения.
  2. Разбиваем их на фрагменты, если нужно. Например, документ на chunks по 300–1000 токенов.
  3. Прогоняем каждый объект через embedding model.
  4. Получаем вектор фиксированной размерности.
  5. Сохраняем вектор в Vector DB вместе с ID и metadata.
  6. Строим индекс для быстрого поиска.
  7. При запросе пользователя также строим embedding запроса.
  8. Ищем ближайшие векторы.
  9. Возвращаем исходные документы, фрагменты или ID.
  10. Опционально rerank’им результаты более дорогой моделью.

Упрощенно:

Пользовательский запрос
        ↓
Embedding model
        ↓
query_vector = [0.01, -0.04, 0.19, ...]
        ↓
Vector DB similarity search
        ↓
Top-5 похожих документов
        ↓
LLM / приложение / recommender

6. Почему нужен 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 ГБ при идеальном последовательном чтении
HDD100–250 МБ/сдесятки минут
SATA SSD400–550 МБ/соколо 19–26 минут
NVMe SSD PCIe 4.03–7 ГБ/спримерно 1.5–3.5 минуты
DRAM50–300+ ГБ/спримерно 2–12 секунд
GPU HBM1–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. Как они устроены внутри: структуры индексации

Внутри векторной базы есть несколько ключевых слоев:

  1. Vector storage — хранение самих embedding’ов.
  2. Metadata storage — хранение ID, JSON-полей, ссылок на документы.
  3. Index — структура для ускорения similarity search.
  4. Query planner — решает, как совместить vector search и metadata filters.
  5. Execution engine — выполняет поиск, reranking, merge результатов с шардов.
  6. Replication/sharding layer — распределение данных по нодам.
  7. 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.
Идея похожа на разбиение пространства на кластеры.

Процесс:

  1. Берем обучающую выборку векторов.
  2. Кластеризуем их, например с помощью k-means.
  3. Получаем nlist центроидов — центры кластеров.
  4. Каждый вектор кладем в ближайший кластер/inverted list.
  5. При поиске сначала находим ближайшие к query кластеры.
  6. Сканируем только эти списки, а не всю базу.

Важные параметры:

ПараметрЧто означает
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 слишком дорого.

Упрощенно:

  1. Вектор размерности d делится на m под-векторов.
  2. Для каждого подпространства обучается маленький codebook, например 256 центроидов.
  3. Каждый под-вектор заменяется ID ближайшего центроида.
  4. Если codebook имеет 256 центроидов, ID помещается в 1 байт.

Пример:

  • исходный вектор: 1536 float32;
  • размер: 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 — это сочетание трех факторов:

  1. Много объектов: миллионы, сотни миллионов, миллиарды.
  2. Высокая размерность: 384, 768, 1536, 3072+ измерений.
  3. Float storage: каждый float32 занимает 4 байта.

Посмотрим на размер одного вектора:

Размерностьfloat32float16 / bfloat16int8binary
3841536 байт768 байт384 байта48 байт
7683072 байта1536 байт768 байт96 байт
15366144 байта3072 байта1536 байт192 байта
307212288 байт6144 байта3072 байта384 байта

Но хранение вектора — это только часть стоимости. Еще нужны:

  • ID объекта;
  • metadata;
  • индекс;
  • служебные структуры;
  • WAL/segments/compaction data;
  • реплики;
  • возможная копия исходных float-векторов для reranking;
  • кэш.

Поэтому реальная система почти всегда требует больше места, чем «просто размер embedding’ов».

9. Сколько памяти нужно для скольких векторов

Ниже — расчеты без индексов, только массивы embedding’ов.
Для простоты считаем 1 ГБ как 1 000 000 000 байт.

9.1. Только векторы, без индексов и metadata

Количество векторов384 dim float32768 dim float321536 dim float323072 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

Количество векторовfloat32float16int8binary
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 PQPQ-коды + 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 ГБ.

Цена — потеря точности. Часто делают так:

  1. IVF-PQ быстро находит top-100 или top-1000 кандидатов.
  2. Затем кандидаты 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нетбазоваяминимальный
float162xчасто лучше на GPUобычно небольшой
int84xможет быть лучшесредний
binary32x для float32очень высокая на bit opsможет быть высокий
PQ10x–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

При запросе:

  1. Query vector отправляется на все релевантные шарды.
  2. Каждый шард ищет свой локальный top-k.
  3. Координатор собирает результаты.
  4. Делает global merge по score.
  5. Возвращает итоговый top-k.
Query
  ↓
Coordinator
  ↓       ↓       ↓       ↓
Shard1  Shard2  Shard3  Shard4
  ↓       ↓       ↓       ↓
top-k   top-k   top-k   top-k
  ↓       ↓       ↓       ↓
Global merge
  ↓
Final top-k

13.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.
Есть два подхода:

  1. Pre-filtering: сначала отфильтровать документы, потом искать векторы.
  2. 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

  1. Пользователь задает вопрос.
  2. Система строит embedding вопроса.
  3. Vector DB ищет top-k похожих фрагментов.
  4. Опционально применяется keyword search или metadata filters.
  5. Опционально применяется reranker.
  6. Лучшие фрагменты добавляются в prompt.
  7. LLM генерирует ответ.
  8. Система возвращает ответ и, желательно, ссылки на источники.

14.4. Почему RAG не работает «сам по себе»

Проблемы часто не в vector DB, а в pipeline:

  • плохое разбиение на chunks;
  • неподходящая embedding model;
  • не та метрика similarity;
  • слишком маленький top-k;
  • нет reranking;
  • устаревшие документы;
  • плохая очистка текста;
  • неправильные metadata filters;
  • LLM игнорирует контекст или галлюцинирует.

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, старые и новые векторы обычно нельзя смешивать.
Даже если размерность совпадает, геометрия пространства может быть другой.

На практике смена модели означает:

  1. пересчитать embeddings для всех документов;
  2. создать новый индекс;
  3. протестировать recall/precision;
  4. провести A/B test;
  5. переключить traffic;
  6. удалить старый индекс после стабилизации.

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.
Но по открытым публикациям, инструментам и индустриальным трендам можно восстановить реалистичную картину.

ГодЧто происходилоТипичные масштабы и контекст
2015Embeddings уже широко используются: word2vec, GloVe, ранние recommender systems, image retrieval.Многие системы работают с миллионами-десятками миллионов векторов. Часто используются специализированные in-house решения, Annoy, LSH, KD-tree/ball-tree для меньших размерностей.
2016Публикация HNSW. Графовые ANN-методы становятся очень важными.HNSW показывает отличное соотношение recall/latency для in-memory поиска. Масштабы в десятки миллионов становятся практичнее при наличии RAM.
2017Meta 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.
2020Google публикует ScaNN. Semantic search становится более практичным.ANN-инструменты активно используются в search/recommendation. Миллионы-десятки миллионов векторов становятся обычным production-объемом.
2021Растет интерес к pgvector, Qdrant, cloud vector search. Sentence transformers становятся массовыми.Многие команды начинают хранить embeddings в Postgres/Elasticsearch/специализированных vector DB.
2022LLM начинают резко менять спрос на semantic retrieval.RAG еще не стал массовым словом, но semantic search уже активно используется в enterprise knowledge search.
2023Взрыв RAG после массового распространения ChatGPT-подобных систем.Vector DB становятся обязательным элементом AI stack. Даже небольшие команды начинают индексировать документацию, базы знаний, тикеты, чаты.
2024Hybrid 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.
2026Vector 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.

Если вы только начинаете, не нужно сразу строить миллиардный кластер.
Начните с простой архитектуры:

  1. выберите хорошую embedding model под ваш язык и домен;
  2. сделайте корректный chunking;
  3. индексируйте данные в pgvector, FAISS, Qdrant, Milvus или другом инструменте;
  4. измерьте качество retrieval;
  5. добавьте hybrid search и reranking;
  6. только потом оптимизируйте индексы, память, GPU и шардирование.

Векторная база — это не магия и не «ИИ внутри базы». Это инженерная система, которая очень быстро отвечает
на вопрос:

«Какие объекты в моей базе находятся ближе всего к этому смысловому запросу?»

И именно этот простой вопрос лежит в основе огромного количества современных AI-приложений.

Комментарии:
    » Векторные базы данных в ИИ: что это такое, как они устроены, как работают и зачем нужны