Алексей Маркин рабочий журнал

ищет по заголовкам и тексту записей и заметок

запись 3 сентября 2026 г. · 4 мин
Все статьи

Эмбеддинги: что они меряют и чего не меряют

Близость векторов — это не близость смысла в том виде, в каком её понимает человек. Разбираю, где расходится, почему поиск находит не то и что с этим делать.

Симптом узнаваемый: поиск по базе стабильно находит документы «про то же самое», но не тот, который отвечает на вопрос. Ищут «можно ли отменить заказ после оплаты» — приходит абзац про то, как оформить заказ.

Дело не в плохой модели эмбеддингов. Дело в том, что она меряет не то, что мы от неё ждём.

Что такое близость векторов

Модель эмбеддингов переводит текст в вектор так, чтобы тексты, встречающиеся в похожих контекстах, оказывались рядом. Обучение построено на употреблении: если два фрагмента окружены похожими словами и решают похожие задачи, их векторы сближаются.

Это и есть определение «похожести», которое вы получаете. Не «утверждают одно и то же», не «отвечают на один вопрос», а употребляются похоже.

Разница выглядит академической ровно до первого разбора выдачи.

Где расходится

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

Вопрос и ответ — разные жанры. Вопрос «как отменить заказ» и инструкция «для отмены нажмите…» написаны по-разному: разная длина, разная лексика, разная грамматика. Их векторы могут оказаться дальше друг от друга, чем вопрос и другой вопрос. Отсюда практика хранить рядом с фрагментом сформулированные вопросы, на которые он отвечает, — и искать по ним.

Редкие идентификаторы усредняются. ERR_2041 и ERR_2043 для модели почти одно и то же: она видит похожую последовательность символов в похожем окружении. Точное совпадение по редкому токену векторный поиск не гарантирует, и это причина, по которой в базах с артикулами, кодами и названиями функций нужен гибрид с обычным полнотекстовым поиском.

Домен смещает всё. Модель, обученная на общем вебе, разложит ваши внутренние термины по общему смыслу слов, а не по вашему. «Карточка» в вашей компании может означать конкретный документ, а для модели это что-то между визиткой и банковской картой.

Что с этим делать

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

Ставить реранкер. Модель, которая смотрит на пару «вопрос + фрагмент» целиком, а не на два независимых вектора, различает отрицание заметно лучше. Она дороже, поэтому и применяется к пятидесяти кандидатам, а не ко всей базе.

Складывать с полнотекстовым поиском. Дешёвая мера, закрывающая целый класс промахов на идентификаторах.

Хранить формулировку вопроса рядом с фрагментом. Работает лучше, чем кажется, и не требует ничего, кроме дисциплины при написании базы.

Мнение, с которым спорят

Смена модели эмбеддингов почти никогда не является главным рычагом. Разница между актуальными моделями на прикладной задаче меньше, чем разница между хорошей и плохой нарезкой документов.

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

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

Чего я делать не стал бы

Не стал бы полагаться на порог косинусной близости как на признак релевантности. Абсолютные значения ничего не значат сами по себе: они зависят от модели, от длины текста и от домена. Осмысленно только сравнение кандидатов между собой.

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

Открытый вопрос

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