Как создать ассистента для поиска по видео
Всем привет! Меня зовут Георгий, я старший разработчик-исследователь в MTS AI. Одной из задач, которыми я занимаюсь в компании, является умная видеоаналитика. Это мощный инструмент, особенно с учетом современных технологий искусственного интеллекта, который может использоваться во многих отраслях: от торговли до обслуживания клиентов.
При этом у сегодняшних систем видеоаналитики есть существенное ограничение: они заточены под узкие задачи и конкретные типы событий — например, распознавание автомобильных номеров, пересечение границ, детектирование лиц. Конечно, прогресс не стоит на месте, и за прошедший год появилось много мультимодальных моделей, способных отвечать на широкий спектр вопросов по видео -, но они работают лишь на очень коротких роликах и требуют серьезных вложений в «железо».
Тем не менее представьте, что можно создать общую систему видеоаналитики, которая заранее не настроена на определенные события. Она гибкая и умеет понимать задачи во время общения с пользователем. Запросы могут быть разнообразными, например: «предупреди меня, если в кадре произойдет ЧП, например, пожар или драка» или «я хочу найти кадры с желтыми автомобилями такси».
Можно ли найти подход, при котором система сможет отвечать на широкий спектр вопросов по видео, но при этом будет способна обрабатывать длинные видеозаписи и останется нетребовательной к железу? В этой статье я расскажу про один из способов создания такого решения — на примере поиска по видео.
Как сделать такую систему?
Первое, что приходит в голову при желании собрать текстовый поиск по видео, — разбить видео на кадры (или маленькие видеоролики), перевести их в текст с помощью большой модели, а дальше применить какой-нибудь стандартный RAG (Retrieval Augmented Generation) код.
RAG, или Retrieval-Augmented Generation, — это метод, используемый в искусственном интеллекте, который объединяет поиск информации и генерацию текста. Сначала система RAG ищет релевантную информацию из большого количества заранее проиндексированных данных (говоря простым языком, «гуглит» по вашей базе данных), затем она генерирует ответ, используя полученную информацию.
Такой путь приходит в голову многим. Я тоже сначала выбрал его. Чтобы переводить видео в текст, я перебирал мультимодальные сети — начиная с топовых и тяжелых, на основе 7B языковых моделей. Этот путь оказался рабочим, но тупиковым: инференс таких моделей требует около 16ГБ видеопамяти и длится от нескольких секунд на каждый обрабатываемый кадр — слишком медленно и дорого для массовой индексации длинных видео.
Следующим вариантом была легкая модель BLIP (не знаменитая BLIP-2, а просто BLIP). При верных настройках она дает детальное описание кадра на ГПУ всего за 0.5 секунды, и весит в разы меньше современных мультимодалок — все еще предлагая неплохое текстовое описание кадров. Какое-то время мне хватало BLIP.
Но потом и она показалась слишком тяжелой. Я стал искать пути оптимизации — и нашел. Все мультимодальные языковые модели состоят из image encoder-а и языковой модели. Именно image encoder дает мне то, в чем я нуждаюсь — переводит изображение в вектор (набор векторов) некоторого семантического пространства. Языковая модель — это просто лишняя нагрузка на этапе индексации данных. Я убрал из своего кода LLM, оставив только легковесный image encoder. Это ускорило инференс на 1–2 порядка. Следующая схема описывает результат такой работы.
Чат ассистент для поиска по видео может быть построен по аналогии с RAG, известным многим NLP-специалистам. Зеленые стрелки показывают процесс индексации видео (делается заранее).
Голубые стрелки — общение с пользователем, после того, как данные были проиндексированы.
Описание схемы
Эта система состоит из трех ключевых элементов:
Для быстрого поиска данные нужно индексировать. Для этого нужна векторная база данных (Vector database) — она позволяет находить для любого заданного вектора (query) k ближайших векторов приблизительно за константное время (О (1)). Один из самых популярных инструментов для такого быстрого поиска — это FAISS (Facebook AI Similarity Search).
Для того, чтобы с этой векторной базой данных можно было работать, необходимо проецировать кадры из видео и текстовые вопросы пользователя в единое пространство. На схеме за этой отвечают Frames embedder и Query Embedder. Для этих целей можно использовать единую модель из семейства CLIP (Contrastive Language-Image Pre-training) — это модели на основе трансформера ViT, проецирующая изображения и текстовые описания в единое векторное пространство. Почитать об этих моделях можно на сайте OpenAI. А подобрать нужный чекпоинт можно у laion или EVA CLIP — там недавно выкатили монстра аж на 18 миллиардов параметров. В своем коде я взял, напротив, одну из самых легких из имеющихся моделей CLIP.
Далее необходим дополнительный код для работы с видео, чтобы можно было доставать нужные нам кадры. В своем коде я использовал ffmpeg и OpenCV.
Этих трех элементов уже достаточно для построения системы поиска кадров на видео по их текстовому описанию. Однако можно добавить еще немного кода для улучшения user experience:
Интерфейс телеграм-бота, написанный на библиотеке telethon. Отказ от привычного telebot в пользу telethon продиктован желанием обходить ограничение на загрузку файлов в бота (при использовании telebot и стандартного Telegram API боту нельзя передавать файлы > 20 МБ).
Модели семейства CLIP тренируются на английском языке. Дополнительный вызов LLM (можно обращаться к любой хорошей модели, проще всего по API) позволяет превратить запрос «найди мне на этом видео кота» в «please find me a cat in this video» (а еще лучше — просто в «cat»). В своем коде я обращаюсь по API к нашей модели MTS AI Chat. Перевод запроса на английский язык — не идеальное решение. Например, слово «ручка» имеет совершенно различные переводы на английский (a pen, a handle, an arm), что может создавать проблемы в некоторых случаях. Идеальным решением был бы «русскоязычный CLIP».
Найденные кадры — это замечательно, но будет еще лучше, если бот их еще прокомментирует. Вот здесь уже пригодится мультимодальная LLM. Во-первых, мультимодальная LLM улучшает качество сервиса — она напишет ответ на вопрос пользователя, отталкиваясь от найденных изображений. Во-вторых, в случае если пайплайн возвращает кадры, на которых нет ответа на вопрос (False positive срабатывания), мультимодальная LLM может убрать их из поисковой выдачи. Для подбора оффлайн мультмодалок можно отталкиваться от бенчмарка BradyFU. Либо использовать API. Пока свое собственное мультимодальное API у меня не развернуто, для демо в телеграмм я решил временно прибегнуть к GPT-4 Vision API в low detail режиме. Подчеркну, что эти вызовы — лишь косметический штрих в общем коде, сам поиск работает оффлайн без обращения к тяжелым и платным API =)
Что получилось?
Попробовать, как работает полученная схема, можно через телеграмм. Бот открыт: https://t.me/CamerOn_Video_Search_Bot
Все ли он находит? Нет, не все и не всегда. Но с большей частью запросов он справляется довольно хорошо. Иногда помогает уточнение запроса — скажем, в видео могут не найтись «люди», но могут найтись «три мужчины за праздничным столом». Скорее всего это связано с выбранной моделью image encode—a. Если на видео что-то точно есть, а у вас оно не находится — попробуйте переформулировать запрос.
Собранный пайплайн был протестирован на нашем внутреннем датасете VQA (Visual Question Answering). Он отличается от обычных VQA для мультимодальных LLM тем, что длина роликов измерялась десятками минут), вопросы приближены к реальным запросам систем видеонаблюдения (ситуации вроде конфликтов, ДТП или открытого огня). Несмотря на самый легкий image encoder, покрытие (recall) на нашем тестовом датасете достигает 80%. К слову, при переключении описания кадров с эмбедингов CLIP на текстовые описания падает не только скорость работы (в 10–100 раз), но и метрики — RECALL опускается до уровня 35–70% (в зависимости от того, какая именно LLM анализирует текстовые описания найденных кадров). Но даже с лучшими LMM результат хуже — скорее всего причина в том, что при переводе данных из эмбедингов CLIP в текст информация теряется — какими бы хорошим адаптерами мы это не делали.
Насколько это ресурсоемко?
В пайплайне не используются никакие тяжелые элементы (конечно, есть обращения к тяжелым API –, но они опциональны!). Единственная неотъемлемая нейросеть — laion/CLIP-ViT-B-32-laion2B-s34B-b79K — весит 600 МБ. Это позволяет без проблем запускать код обработки видео на ноутбуке, а также, теоретически, на более слабом железе — вплоть до одноплатных компьютеров (автор это не проверял — в RAM поместиться модель должна). Подключение языковых моделей, включая мультимодальные, — опционально (поиск кадров по текстовому описанию будет работать и без ЛЛМ), развернуты они могут быть удаленно. Можно запускать этот код и получать текстовые описания и без мультмодальных сетей — эмбеддинги клипа можно проецировать в те или иные слова (теги, классы) через натренированный линейный слой (но лучше через промежуточный трансформер, как сделали в работе BLIP-2).
На GPU этот написанный на python код обрабатывает видео примерно в 10 раз быстрее, чем оно длится. Это не предел — сама обработка кадра через CLIP занимает миллисекунды -, но для демонстрации сгодится.
Для демонстрации работы кода удобнее всего было бы взять широко известные фильмы (бот прекрасно ищет на длинных видео), но это потребовало решения вопросов с авторскими правами.
Поэтому я просто снял окружающие меня объекты в процессе написания этой статьи и провел работу бота на получившемся видео.
Послесловие: real-time конфигурируемая система
Такой подход к видеоаналитике — работа с общими дескрипторами кадров — теоретически позволяет конфигурировать систему на специфические пользовательские запросы при помощи общения в реальном времени
Процесс взаимодействия пользователя с системой начинается с общения через чат-бота. Например, пользователь сможет получать предупреждения, когда на видео появятся одновременно мусороуборочная машина и дворник. Чат-бот выполняет функции пользовательского интерфейса, приема запросов, идентификации целевых ситуаций, а после, отправляет эти описания на векторизацию (через модель CLIP).
Модель CLIP преобразует фразы с описанием целевых ситуаций в векторы. Также она кодирует отобранные кадры из видеопотока в векторы с фиксированным шагом (например, каждый десятый кадр). Особенность модели заключается в том, что и текстовые описания и изображения проецируются в единое векторное пространство. Эти векторы затем тщательно сравниваются с векторами, сформированными из текстовых запросов пользователя.
На основе предварительно установленного порогового значения средней квадратической ошибки (MSE) система может принять решение о том, что произошло значимое событие, соответствующее предпочтениям пользователя для оповещения. Для более точной оценки, этот процесс может быть дополнен с помощью мультимодальной модели, чтобы точно отфильтровать возможные ложные срабатывания. Однако стоит отметить, что этот этап является опциональным.
Наконец, пользователь получает уведомление о возможной идентификации запрошенного события, в которое будет включена кадровая съемка в качестве визуального подтверждения.
Гибко конфигурируемая видеоаналитика: Вместо векторной базы данных FAISS можно поставить компаратор поступающих в режиме реального времени эмбеддингов и эмбеддинга от запроса пользователя («Пожар», «Снегоуборочная техника», «Проникновение людей на территорию») — это позволит каждому пользователю конфигурировать систему видеонаблюдения под себя при помози «всего одной sms». Зеленые стрелки показывают процесс настройки (делается заранее).
Голубые стрелки — общение с пользователем, после того, как обозначенные события произошли в кадре.
Заключение
Создание систем анализа видео при помощи LLM (мультимодальных или обычных) выглядит возможным, но требует выполнения двух важных условий:
Перевод видео для индексации (или других действий) должен производиться не в текст, а в семантические дескрипторы (эмбеддинги) того или иного рода при помощи таких моделей как CLIP (если важно единое пространство с текстом) или моделей типа DINOv2 (если выравнивание с текстом не так важно).
Подключением тяжелых языковых моделей (мультимодальных либо обычных) должно производиться только в ключевых этапах пайплайна (настройка / обработка результата) может быть тем самым сбалансированным решением, которое позволяет подключать к системам анализа видео большие языковые модели, не прибегая к излишним нагрузкам на вычислительные ресурсы (таким, которые потребовались бы при покадровом переводе в текст).
Выполнение этих условий оставляет пространство возможностей для построения сбалансированного решения, которое будет иметь почти такие же возможности, как мультимодальные LLM, но будет требовать почти так же мало вычислительных ресурсов, как существующие решения.