Фото животных через embeddings: матчи и дедупликация в «Найди друга»
В «Найди друга» добавили сопоставление фотографий через embeddings: поиск ближайших соседей, дедупликация найденных животных и temporal decay в скоринге.

Для «Найди друга» сделали embedding-based сопоставление фотографий: снимок животного превращается в вектор, дальше система ищет ближайших соседей и использует этот сигнал в ранжировании.
Формат задачи был простой только на словах. Пользователь видит объявление о найденном коте и надеется, что это его потеряшка. Если рядом есть два рыжих кота из одного района, система не должна уверенно подсовывать совпадение только потому, что картинки похожи цветом и сценой. И наоборот: если одного найденного кота сфотографировали несколько людей, эти объявления не должны жить как независимые сущности и размазывать выдачу.
Было: похожие фото давали слишком много шума
В проекте уже есть естественная неоднозначность: животные одной породы, одного окраса и из одного района могут выглядеть почти одинаково на плохих снимках. Рыжий кот на асфальте, рыжий кот у подъезда, рыжий кот в переноске — для человека это разные ситуации, но для автоматического поиска по одному признаку легко получить слишком смелый матч.
Отдельная боль — дубли. Один найденный кот может попасть в сервис несколько раз: его сфотографировали несколько людей, кто-то выложил кадр крупнее, кто-то — сбоку. Без visual similarity такие объявления сложно склеивать: текст может отличаться, описание может быть коротким, а координаты — близкими, но не одинаковыми.
Поэтому фото решили использовать как отдельный сигнал, но не как окончательный вердикт.
Стало: каждый снимок ищем как вектор
Мы добавили пайплайн, где каждый снимок превращается в embedding — числовой вектор, который хранит визуальные признаки изображения. При поиске система берёт вектор нового фото и ищет ближайших соседей среди уже известных снимков.
Это дало два рабочих сценария.
Первый — ранжирование потенциальных совпадений. Если пользователь добавил потерянного кота, система может поднять выше найденных животных с визуально похожими фото. Но это именно ранжирование: два рыжих кота в одном районе не превращаются автоматически в «нашёлся». Так меньше ложных надежд, особенно на однотипных снимках.
Второй — дедупликация найденных объявлений. Если одного кота сфотографировали несколько людей, visual similarity помогает понять, что это может быть один и тот же объект в разных объявлениях. Такие кандидаты можно группировать и показывать аккуратнее, не заставляя пользователя проходить одинаковые карточки подряд.
Живая деталь: на первых обсуждениях хотелось сделать визуальное совпадение главным сигналом. Потом быстро упёрлись в рыжих котов. У них слишком много общего на уровне картинки, а цена ошибки для пользователя неприятная: человек начинает надеяться раньше времени. Поэтому embeddings остались сильным, но не единственным фактором в scoring.
Время тоже влияет на релевантность
Для матчей добавили temporal decay: релевантность совпадения падает со временем. Логика тут прикладная. Фото может быть очень похожим, но если объявление стареет, его вес в выдаче должен снижаться.
Это не отменяет визуальную близость. Старое объявление всё ещё может попадать в кандидаты, если снимок действительно близок к запросу. Но в scoring время работает как отдельный коэффициент, чтобы свежие и визуально похожие объявления не терялись среди старых карточек.
С temporal decay был отдельный компромисс: если слишком рано давить старые объявления, можно потерять важный след; если почти не давить, выдача начинает держаться за давние совпадения. Поэтому decay вынесли в scoring, где его можно настраивать отдельно от visual similarity.
Что получилось поменять
Было: система видит набор объявлений, где два похожих рыжих кота из одного района и несколько карточек одного найденного кота выглядят как одинаково вероятные варианты.
Стало: у каждого фото есть embedding, по нему находятся ближайшие соседи, а дальше visual similarity участвует в ранжировании и дедупликации. Время объявления учитывается через temporal decay, поэтому релевантность матча постепенно снижается.
Для пользователя это выглядит без лишней технической демонстрации: похожие животные поднимаются выше, дубли найденных объявлений проще группировать, а старые совпадения не перетягивают на себя всю выдачу.