Косинусное сходство простыми словами: у смысла есть угол
Косинусное сходство простыми словами: ИИ превращает тексты в векторы и по углу между ними видит, что две фразы близки по смыслу. Разбираем на примерах.
Косинусное сходство это способ измерить, насколько два текста близки по смыслу, через угол между их векторами. Сначала каждый текст превращается в эмбеддинг: длинный список чисел, который описывает его смысл как точку в многомерном пространстве. У модели OpenAI text-embedding-3-small таких чисел 1536. Тексты о похожем оказываются в этом пространстве рядом и «смотрят» в одну сторону, тексты о разном расходятся в стороны. Дальше чистая геометрия: берём два вектора и считаем косинус угла между ними. Единица означает одно направление, смыслы совпадают. Ноль означает прямой угол, тексты друг с другом не связаны. Значения около минус единицы означали бы противоположность, но у текстов встречаются редко. Так ИИ сравнивает не буквы, а направления: фразы «клиент оплатил счёт» и «деньги от заказчика пришли» не совпадают ни одним словом, но их векторы смотрят почти в одну точку, и косинусное сходство у них высокое. На этом принципе держится вся семантическая память ассистента.
Из текста в вектор: где у смысла появляются координаты
Чтобы сравнивать смыслы, их сначала нужно перевести в числа. Это делает модель эмбеддингов. В руководстве OpenAI эмбеддинг определяют как вектор, список чисел с плавающей точкой, который измеряет связанность текстов: малые расстояния между векторами означают высокую связанность, большие означают низкую. Модель text-embedding-3-small выдаёт на каждый текст 1536 чисел, старшая text-embedding-3-large выдаёт 3072. Любопытная деталь из того же руководства: вектор старшей модели можно укоротить до 256 чисел, и он всё равно останется точнее полного вектора модели предыдущего поколения.
Полторы тысячи чисел звучат абстрактно, поэтому представьте дегустационную карту вина. Сомелье описывает бутылку по шкалам: кислотность, сладость, танины, тело. Два вина с похожими профилями окажутся похожи на вкус, даже если сделаны на разных континентах. Эмбеддинг делает то же самое с текстом, только шкал полторы тысячи и человеческих названий у них нет: модель сама выучила, какие оси нужны, чтобы различать смыслы. Каждое число это координата по одной из осей, а весь вектор это точка в пространстве смыслов. Письмо о задержке оплаты и заметка «дебиторка по проекту N» лягут в этом пространстве рядом, а рецепт борща уедет далеко в сторону.
Что измеряет косинус: угол вместо совпадения букв
Теперь представьте векторы как стрелки, выходящие из одной точки. У пары стрелок есть угол, и косинус этого угла удобен как мера сходства. Стрелки смотрят в одну сторону: угол ноль, косинус равен единице, смыслы совпадают. Стрелки перпендикулярны: косинус равен нулю, тексты друг о друге ничего не знают. Чем меньше угол, тем ближе косинус к единице и тем ближе две мысли друг к другу.
Проверим на примере. Фразы «отчёт за март готов» и «мартовскую отчётность закончили» не имеют ни одной общей словоформы, но их стрелки почти параллельны: сходство высокое. Фраза «купить корм коту» смотрит совсем в другую сторону от обеих: сходство около нуля. Дословный поиск в этой паре отчётов не нашёл бы ничего, потому что сравнивает буквы. Косинус находит, потому что сравнивает направления.
Почему направление, а не расстояние между точками? У вектора есть ещё длина, но для смысла она второстепенна: тема текста живёт в направлении стрелки. Косинус от длины не зависит вовсе, поэтому короткая заметка и длинный документ об одном и том же получают высокое сходство. На практике разница ещё тоньше: OpenAI нормирует свои эмбеддинги к единичной длине, все стрелки одинаковые, важно только направление. Из этого следуют два удобства, которые руководство OpenAI называет прямо: косинус считается простым скалярным произведением, то есть очень дёшево, а ранжирование по косинусу и по обычному евклидову расстоянию даёт одинаковый порядок результатов. Поэтому спорить о выборе метрики почти не приходится: OpenAI рекомендует косинусное сходство, оговариваясь, что выбор функции расстояния обычно мало что меняет.
Как найти похожее среди миллиарда записей
Посчитать один косинус дёшево. Но память рабочего ассистента это не пара записей, а тысячи и миллионы, и сравнивать запрос с каждой подряд слишком долго. Задачу поиска ближайших векторов на больших объёмах решила работа «Billion-scale similarity search with GPUs» (Johnson, Douze, Jégou, 2017), из которой выросла открытая библиотека Faiss. Авторы перенесли поиск соседей на графические процессоры и получили скорость в 8,5 раза выше прежнего рекорда для GPU. Масштабы там впечатляют до сих пор: граф ближайших соседей для 95 миллионов картинок из набора Yfcc100M они построили за 35 минут, а индекс, связывающий миллиард векторов, менее чем за 12 часов на четырёх видеокартах 2015 года.
Для Вас из этого важно одно: поиск по смыслу давно перестал быть роскошью. Алгоритмы приближённого поиска не перебирают записи подряд, а идут по заранее построенной карте к ближайшим соседям коротким путём. Поэтому ассистент находит нужный фрагмент среди сотен тысяч записей за доли секунды, и с ростом архива это время почти не растёт. База знаний, которую Вы копите годами, остаётся быстрой.
Причём здесь память ассистента
Косинусное сходство это рабочий механизм памяти, а не абстракция из учебника. Как устроены остальные части, слои памяти, чанкинг, ночная консолидация, мы разбираем в обзоре память ИИ-ассистента. Здесь важна сама цепочка: каждый Ваш вопрос превращается в вектор, база сравнивает его с векторами сохранённых записей и отдаёт модели самые близкие по смыслу фрагменты. Именно поэтому настоящая память находит договорённость месячной давности, даже когда Вы формулируете вопрос совершенно другими словами, чем писали тогда.
У Хермес этот механизм работает под капотом каждого ответа. Ваши переписки, документы и решения лежат в векторной базе на Вашем сервере, и когда Вы спрашиваете «что мы решили по ценам для того клиента из Казани», она ищет не слово «Казань», а направление смысла. Вам при этом не нужно знать ни про косинусы, ни про векторы: у смысла есть угол, и ассистент просто выбирает записи, где этот угол к Вашему вопросу самый малый. Вся геометрия остаётся за кулисами, а Вам достаётся ответ по делу.
Что такое косинусное сходство простыми словами?
Это мера близости двух текстов по смыслу. Каждый текст превращается в вектор, стрелку в многомерном пространстве, и сравниваются направления этих стрелок. Косинус угла между ними равен единице, когда направления совпадают, и нулю, когда тексты друг с другом не связаны. Чем меньше угол, тем ближе смыслы. Поэтому фразы, не совпадающие ни одним словом, могут получить высокое сходство, если говорят об одном и том же.
Чем косинусное сходство отличается от поиска по ключевым словам?
Поиск по словам сравнивает буквы: найдётся только то, где запрос дословно совпал с текстом. Косинусное сходство сравнивает направления векторов, то есть смысл. Запрос «деньги от заказчика пришли» найдёт запись «клиент оплатил счёт», хотя общих слов у них нет. Обратная сторона: точные артикулы и номера договоров дословный поиск находит надёжнее, поэтому на практике оба подхода часто совмещают.
Какие значения принимает косинусное сходство и что они означают?
От минус единицы до единицы. Единица означает одинаковое направление векторов: смыслы совпадают. Ноль означает прямой угол: тексты друг с другом не связаны. Минус единица означает противоположные направления; у текстовых эмбеддингов такие значения на практике почти не встречаются. Рабочая зона обычно лежит между нулём и единицей: чем ближе к единице, тем ближе тексты по смыслу.
Что такое векторный поиск похожести (similarity search)?
Это поиск записей, чьи векторы ближе всего к вектору запроса. Вопрос превращается в эмбеддинг, база сравнивает его с векторами сохранённых записей и возвращает ближайшие по сходству. Чтобы не перебирать миллионы записей подряд, используют приближённые алгоритмы и библиотеки вроде Faiss: в работе Johnson et al. (2017) индекс соседей для миллиарда векторов построили менее чем за 12 часов.
источники (2)
- Vector embeddings · OpenAI
- Billion-scale similarity search with GPUs · arXiv, Johnson et al. · 2017