Logo
Overview

Векторные базы данных и embeddings: как устроен поиск в RAG простыми словами

June 29, 2026
9 min read

Векторные базы данных и embeddings: как устроен поиск в RAG простыми словами

Векторная база данных — это не про векторы из школьной геометрии и не про базы данных в привычном смысле. Это про то, как компьютер понимает, что фразы «платёжный шлюз» и «оплата картами» — про одно и то же, хотя слова в них разные. И делает он это не через словари синонимов и не через регулярные выражения. Он переводит текст в числа. Много чисел. А потом ищет по ним ближайших соседей.

Если вам когда-нибудь приходилось объяснять коллегам, почему поиск по Confluence не находит документ, в котором написано «интеграция с эквайрингом», когда вы ищете «оплата через банк» — вы уже столкнулись с ограничениями текстового поиска. Векторный поиск решает эту проблему на другом уровне. Не по словам. По смыслу.

Что такое embedding и зачем он нужен

Embedding (эмбеддинг, векторное представление) — это числовой вектор фиксированной размерности, в который embedding-модель превращает текст так, что семантически близкие фразы оказываются рядом в векторном пространстве.

Обычный текстовый поиск (тот же Ctrl+F или LIKE в SQL) ищет точное совпадение строк. Написали «интеграция с эквайрингом» — найдёт только документы, где есть ровно эта фраза. Написали «подключение платёжной системы» — тишина. Хотя речь об одном и том же.

Embedding-модель решает это иначе. Она обучена на гигантских массивах текста и «понимает», что слова и фразы, встречающиеся в похожих контекстах, должны иметь похожие векторы. После обучения модели фразе «платёжный шлюз» присваивается вектор из, скажем, 1536 чисел. Фразе «оплата картами» — другой вектор, но такой, что расстояние между ними маленькое. А фразе «производительность базы данных» — вектор, который от первых двух далеко. В этом и есть суть: близость в векторном пространстве = семантическая близость.

Стоит отметить: embedding-модель ничего не «знает» о вашем проекте. Она не читала ваши ADR и не в курсе, какой у вас стек. Она опирается на паттерны, выученные на общем корпусе текстов. Но этого достаточно, чтобы отличить требование к производительности от UI-спецификации — потому что на обучающих данных она видела тысячи таких примеров.

Как embedding-модель превращает текст в вектор

Процесс выглядит как чёрный ящик, но если заглянуть внутрь, там нет магии. Есть два этапа: токенизация и собственно преобразование в вектор.

Токенизация. Текст разбивается на токены — кусочки слов, целые слова или спецсимволы. Фраза «система должна обрабатывать 1000 заказов» превращается в последовательность чисел-идентификаторов из словаря модели. Это не сам embedding, а его «сырьё».

Преобразование. Последовательность токенов пропускается через нейронную сеть (обычно transformer), и на выходе модель выдаёт вектор фиксированной размерности. Важно: для одной и той же фразы на одном и том же языке модель всегда выдаст один и тот же вектор (детерминированно). Никакой случайности.

Что немаловажно: разные embedding-модели дают разные векторы для одного текста. Поэтому нельзя часть документов проиндексировать через text-embedding-3-small, а поисковые запросы векторизовать через multilingual-e5-large — векторы окажутся в разных пространствах, и косинусная близость между ними будет бессмысленной. Модель для индексации и для запросов — всегда одна.

100%
graph LR
  A["Текст документа: Система должна обрабатывать 1000 заказов в минуту"] --> B["Embedding-модель text-embedding-3-small"]
  B --> C["Вектор 1536 чисел"]
  C --> D["Векторная БД: индексация"]
  E["Запрос: Какие требования к производительности?"] --> F["Embedding-модель та же"]
  F --> G["Вектор запроса"]
  D --> H["Поиск ближайших соседей ANN"]
  G --> H
  H --> I["Top-K чанков: релевантные документы"]
  style A fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style B fill:#f0a500,stroke:#c88400,color:#fff
  style C fill:#7b68ee,stroke:#5a4db2,color:#fff
  style D fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style E fill:#50c878,stroke:#3a9a5c,color:#fff
  style F fill:#f0a500,stroke:#c88400,color:#fff
  style G fill:#7b68ee,stroke:#5a4db2,color:#fff
  style H fill:#7b68ee,stroke:#5a4db2,color:#fff
  style I fill:#50c878,stroke:#3a9a5c,color:#fff

На диаграмме — два параллельных потока. Верхний (синий): индексация — документ проходит через embedding-модель, превращается в вектор из 1536 чисел и сохраняется в векторной базе. Нижний (зелёный): поиск — запрос пользователя векторизуется той же моделью, затем по вектору ищутся ближайшие соседи среди проиндексированных документов. Результат — top-K наиболее релевантных чанков.

Этот процесс называется ANN-поиск (Approximate Nearest Neighbour) — «приближённый поиск ближайших соседей». Приближённый — потому что для миллиона векторов полный перебор занял бы вечность, и векторные БД используют специальные индексы (HNSW, IVF), которые жертвуют долями процента точности ради скорости.

Векторная база данных: не просто хранилище

Обычная база данных хранит строки и ищет по индексу: WHERE department = 'billing'. Векторная БД хранит эмбеддинги и ищет по близости: «дай 5 ближайших векторов к тому, что прислал пользователь». Это принципиально другой тип запроса и другой тип индекса.

Для команды аналитиков с парой тысяч документов выбор векторной БД — вопрос скорее инфраструктурный, чем технический. Если PostgreSQL уже есть — расширение PGVector закроет потребности без дополнительного сервиса. Если базы нет и прототип нужен через неделю — Chroma на Python. Если нужна фильтрация по метаданным («ADR за 2025 год от команды биллинга») — Qdrant. Если объём документов перевалил за миллион — Milvus.

База данныхТипОсобенностиПорог входа
PGVector (расширение PostgreSQL)SQL + векторный индексPlug-and-play, если PostgreSQL уже естьНизкий
ChromaЛёгкая векторная БДPython-native, идеальна для прототипаОчень низкий
QdrantВекторная БДФильтрация по метаданным, высокая скоростьСредний
WeaviateВекторная БД + GraphQLВстроенные модули для chunking и embeddingsСредний
MilvusРаспределённая векторная БДМиллиарды векторов, Kubernetes-nativeВысокий

Примечательно, что за последние два года векторный поиск из нишевой технологии превратился в commodity. Ровно в тот момент, когда LLM научились генерировать связные ответы, векторные БД стали стандартным компонентом архитектуры. Одно без другого работает — но вместе даёт RAG.

Косинусная близость: почему «похожесть» — это угол

Математически близость двух векторов чаще всего измеряется косинусным расстоянием — косинусом угла между ними. Косинус 1 означает «векторы направлены в одну сторону» (максимальная похожесть), 0 — «перпендикулярны» (независимы), −1 — «противоположны».

Но проще представить на плоскости:

100%
graph TB
  subgraph PROSTRANSTVO["Векторное пространство (упрощённо 2D для визуализации)"]
      V1["Оплата картами<br/>вектор: (0.85, 0.20)"]
      V2["Платёжный шлюз<br/>вектор: (0.78, 0.25)"]
      V3["Производительность БД<br/>вектор: (-0.70, 0.55)"]
      V4["Время отклика API<br/>вектор: (-0.72, 0.52)"]
      V5["UI кнопки<br/>вектор: (0.10, -0.80)"]
      Q["Запрос «способы оплаты»<br/>вектор: (0.80, 0.22)"]
  end
  
  Q -.->|"косинус 0.98"| V1
  Q -.->|"косинус 0.95"| V2
  Q -.->|"косинус 0.15"| V3
  Q -.->|"косинус 0.12"| V4
  Q -.->|"косинус 0.05"| V5
  
  style PROSTRANSTVO fill:#fafafa,stroke:#ccc,color:#333
  style V1 fill:#50c878,stroke:#3a9a5c,color:#fff
  style V2 fill:#50c878,stroke:#3a9a5c,color:#fff
  style V3 fill:#e0e0e0,stroke:#999,color:#333
  style V4 fill:#e0e0e0,stroke:#999,color:#333
  style V5 fill:#e0e0e0,stroke:#999,color:#333
  style Q fill:#4a90d9,stroke:#2c5f8a,color:#fff

Диаграмма иллюстрирует главное: релевантные документы (зелёные) группируются рядом друг с другом и рядом с запросом. Нерелевантные (серые) — далеко, в других областях пространства. Обратите внимание на косинусы: 0.98 и 0.95 для платёжной тематики — практически идеальное совпадение. 0.15 и ниже — документы из совсем других доменов, они не попадут в выдачу.

Важно понимать: на реальных embedding-моделях размерность не 2, а 1536. Представить 1536-мерное пространство невозможно — но принцип тот же. Векторная БД ищет ближайших соседей по углу, и чем больше размерность, тем дороже поиск.

Чанкинг: как нарезать документы правильно

Индексировать целый документ одним вектором — плохая идея. Представьте ADR на три страницы: решение описано в начале, а контекст и альтернативы — в середине и конце. Если превратить всё это в один эмбеддинг, поиск по запросу «как мы решили проблему с платёжным шлюзом» может вернуть этот ADR. Но с низким косинусом — потому что две трети документа про другое.

Поэтому документы разбивают на чанки — фрагменты по 200–800 токенов. И уже каждый чанк индексируют отдельным вектором.

СтратегияРазмер чанкаПлюсыМинусы
Fixed-size256–512 токеновПросто, предсказуемоРвёт предложения, теряет смысл
Semantic (по абзацам/секциям)200–800 токеновСохраняет смысловые блокиТребует структурированных документов
Sliding window512 токенов, overlap 128Не теряет контекст на границахДублирование, рост индекса

Для проектной документации (ADR, ТЗ, спеки) семантическая стратегия работает лучше всего. Каждый раздел ADR — отдельный чанк: «Контекст», «Решение», «Последствия». При запросе «какие решения касаются аутентификации» retrieval вернёт ровно секцию «Решение» из нужных ADR, а не смесь из контекста и альтернатив.

Стоит отметить: если чанки слишком мелкие (100 токенов), retrieval вернёт три несвязанных обрывка фраз, и LLM честно попытается собрать из них ответ — сконструировав правдоподобную, но ложную интерпретацию. Это классический галлюциноз от плохого чанкинга.

Типичные ошибки при работе с векторным поиском

Давайте честно: первые два-три запуска RAG почти всегда разочаровывают. Поиск находит не то, ответы поверхностные, а иногда модель несёт откровенную чушь со ссылкой на ваши же документы. Разберём, что идёт не так.

Разные embedding-модели для индексации и запросов. Самая частая ошибка. Проиндексировали через OpenAI, а запросы векторизуете через self-hosted модель — и удивляетесь, что поиск возвращает случайный мусор. Модель должна быть одна.

Слишком большие чанки. В чанк на 2000 токенов попадает три разных темы. Embedding получается «размазанным» — он не представляет ни одну из тем хорошо. Retrieval по такому чанку работает как поиск по книге, где вы ищете не по главам, а по случайным половинкам страниц.

Отсутствие метаданных. Если при индексации вы не сохранили дату, автора и статус документа, retrieval может вернуть ADR, который был отвергнут два года назад. LLM добросовестно сошлётся на него. Фильтрация по метаданным — не фича, а обязательный компонент.

Игнорирование переранжирования (re-ranking). Базовый ANN-поиск возвращает top-K чанков по косинусной близости. Но косинус — грубая метрика. Без re-ranker (например, Cohere Rerank) вы рискуете получить чанки, которые численно близки к запросу, но содержательно не отвечают на вопрос.

Завышенные ожидания. Векторный поиск находит похожее. Он не анализирует, не синтезирует и не проверяет факты. Если в проекте никто не написал требования к безопасности — embedding-модель их не придумает. Она скажет «не найдено». Это честно.

Если вы только начинаете разбираться с RAG — почитайте RAG для системных аналитиков: строим базу знаний на LLM. Там — полный пайплайн от индексации до ответа и разбор retrieval-стратегий вроде HyDE. А когда RAG заработает и захочется подключить его к живым источникам (Jira, Confluence), посмотрите AI-ассистент аналитика на MCP — там про то, как LLM через Model Context Protocol получает доступ к задачам, документам и базе данных напрямую.

Заключение

Embeddings и векторные базы данных — это не магия и не хайп. Это инженерное решение конкретной проблемы: как искать по смыслу, а не по словам. Работает оно не идеально — чанкинг требует настройки, re-ranking добавляет latency, а без метаданных retrieval превращается в лотерею. Но когда всё настроено правильно, поиск по корпоративной базе знаний перестаёт быть квестом «в каком Confluence-спейсе и какими словами это записано».

Подводя итог: векторный поиск — это не замена аналитику и не серебряная пуля. Это линза, через которую ваша документация становится видимой для машины. А что машина с этой видимостью сделает — зависит от того, как вы настроите пайплайн. И да, если после индексации выяснится, что половина ADR противоречит другой половине — embedding-модель тут ни при чём. Она просто показала то, что вы написали.