Векторные базы данных и 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 — векторы окажутся в разных пространствах, и косинусная близость между ними будет бессмысленной. Модель для индексации и для запросов — всегда одна.
На диаграмме — два параллельных потока. Верхний (синий): индексация — документ проходит через 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 — «противоположны».
Но проще представить на плоскости:
Диаграмма иллюстрирует главное: релевантные документы (зелёные) группируются рядом друг с другом и рядом с запросом. Нерелевантные (серые) — далеко, в других областях пространства. Обратите внимание на косинусы: 0.98 и 0.95 для платёжной тематики — практически идеальное совпадение. 0.15 и ниже — документы из совсем других доменов, они не попадут в выдачу.
Важно понимать: на реальных embedding-моделях размерность не 2, а 1536. Представить 1536-мерное пространство невозможно — но принцип тот же. Векторная БД ищет ближайших соседей по углу, и чем больше размерность, тем дороже поиск.
Чанкинг: как нарезать документы правильно
Индексировать целый документ одним вектором — плохая идея. Представьте ADR на три страницы: решение описано в начале, а контекст и альтернативы — в середине и конце. Если превратить всё это в один эмбеддинг, поиск по запросу «как мы решили проблему с платёжным шлюзом» может вернуть этот ADR. Но с низким косинусом — потому что две трети документа про другое.
Поэтому документы разбивают на чанки — фрагменты по 200–800 токенов. И уже каждый чанк индексируют отдельным вектором.
| Стратегия | Размер чанка | Плюсы | Минусы |
|---|---|---|---|
| Fixed-size | 256–512 токенов | Просто, предсказуемо | Рвёт предложения, теряет смысл |
| Semantic (по абзацам/секциям) | 200–800 токенов | Сохраняет смысловые блоки | Требует структурированных документов |
| Sliding window | 512 токенов, 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-модель тут ни при чём. Она просто показала то, что вы написали.