Ведущий инженер-программист Иностудио Рассказываем о том, как внедряли новомодные AI-инструменты в проект. Как это повлияло на его популярность и что за этим последовало — читайте в статье. Технические особенности проекта: Фреймворк — Laravel БД — PostgreSQL Кэш/очереди — Redis Архитектура — основной кластер DigitalOcean Kubernetes и графический кластер GKE Изначально проект задумывался как сайт с набором инструментов для работы с документами и изображениями. Сайт содержит различные утилиты конвертации, преобразования и редактирования контента. После удачного старта и растущей популярности клиент принял решение о расширении инструментария.   Было решено интегрировать дополнительные инструменты для работы с видеоконтентом и продолжить работу над актуальностью ранее созданных. Но после анализа состояния проекта один из векторов дальнейшего развития заключался в работе c AI-решениями. О них и пойдёт речь в этой статье. Технические особенности: OpenCV, Pillow, Numpy, Onnxruntime Остановимся на особенностях реализации. За основу мы взяли инструмент remBg. Он построен с использованием целого набора библиотек, указанных выше. Алгоритм работы. Открывается изначальное изображение: И происходит приведение к объекту Pillow: Прогрузка натренированной ранее модели на основе U2net в данном случае: Получение маски исходного изображения на основе прогноза: Форматирование полученной маски (сглаживание, обработка) с помощью OpenCV: Наложение маски на исходное изображение: Сохранение нового изображения: Это «в двух словах» о принципе работы утилиты. Для своих целей мы взяли реализацию для CLI, добавили необходимые для работы типы изображений и их обработку. Напомню, что у нас стояла задача не только удалять, но и менять фон, если это необходимо. Поэтому добавили ещё метод заливки фона из изображения или просто цветом: В репозитории remBg можно выкачать уже обученные модели или обучить свою. Для уже обученных используется U2net и DUTS-TR dataset. Для более подробной информации есть описание. Для наших целей пока что достаточно обученных. Скриншот утилиты: В дальнейшем использовали эту реализацию для Profile Photo Maker — более продвинутого инструмента в виде конструктора. Для каждого типа утилит используется своя очередь.   При обработке, например джобы, происходит обновление статусов в БД, вытаскивается исходный файл из digitalOcean space. После этого задача отправляется на обработку через драйвер. В качестве основы для драйвера взяли https://github.com/alchemy-fr/BinaryDriver Он отлично себя зарекомендовал в реализации PHP-FFMPEG. Используется symfony/process для обработки с необходимой нам обёрткой в виде класса Abstract Binary. Основной метод формирует CLI-команду в таком виде: Всё просто.    Изначально работали со Stable Diffusion версии 1.4.  На huggingface довольно неплохо описан стандартный способ интеграции. Однако на нашей сборке GKE с T4 GPU возникли проблемы производительности, которые не удовлетворяли клиента. Stable Diffusion — это целый набор компонентов и моделей для преобразования текста в изображение. На первом этапе происходит преобразование текста в токены с помощью нейронки CLIPText. Далее текстовые токены и массив информации изображения (latent) отправляются в скрытое пространство нейросети Unet. Там происходит процесс диффузии с необходимым количеством итераций и последующая конвертация полученной после обработки информации в картинку.  Здесь, как мне кажется, отлично описали алгоритм. Сейчас у нас запущена обработка на более современной модели. В качестве метода обработки входного шума остановились на семплере DDIM (Denoising Diffusion Implicit Models) в 50 шагов. Наиболее оптимальные для нужд клиента результаты и время обработки. Upscaler не используем после получения результата — отдаём в 512x512. Вернёмся к нашей проблеме. Для оптимизации стали использовать библиотеку diffusers, которая представляет собой некоторый набор диффузионных моделей, доступ к которым можно получить в две строки. Плюс переключили на загрузку весов float16 вместо float32. Помимо этого установили xFormers для оптимизации памяти. Библиотека оптимизирует использование видеокарт Nvidia на архитектурах Pascal, Turing, Ampere (30XX), Lovelace (40XX) или Hopper (GH100). В целом генерация вышла на комфортные 10 секунд. Однако выгрузка модели при «холодном» запуске занимает ещё около 10 секунд. То есть это время просто теряется, несмотря на то, что мы храним модель на ssd volume без предзагрузок. Был вариант написания «демона» для того, чтобы модель была всё время в памяти. Но пообщавшись с разработчиками, пришли к выводу не инициализировать веса с помощью device_map=«auto». Это привело к значительному ускорению при инициализации. Рекомендации по поводу этого добавили в релиз и документацию, кстати 🙂 Пользователю предлагается выкачать уже сгенерированное изображение по ранее сформулированным текстам. Либо сгенерировать новое. Страница галереи выглядит так: Обработка схожа с обработкой утилиты удаления фона. Генерация, как я сказал выше, происходит в кластере GKE на T4 GPU в 8 потоков. Утилита стала очень популярна, GPU работают практически без перерывов. Клиент доволен, реклама запущена. За основу взята LaMa.  Backend. Сделали по аналогии с утилитами выше — драйвер обернули в очереди. Работает также в нашем выделенном кластере на GPU. Frontend. Для утилиты необходимо отдавать маску изображения с выделенными областями, которые нейронка с помощью быстрого преобразования Фурье распознает и начнёт обрабатывать. Небольшая пояснительная картинка алгоритма преобразования: Скорость обработки замечательная, никаких проблем с оптимизацией не возникло. Как это выглядит у пользователя: Оригинал картинки:   После удаления:   UI представляет собой набор инструментов для выделения областей удаления — кисть и зумирование. Плюс реализована история изменений — пользователь может отменять действия. Frontend написан на VueJS. Реализация инструментария с использованием KonvaJS. После того как пользователь закончил выбор областей, мы генерируем на фронте файл маски и отправляем на сервер для последующего прокидывания в S3. После чего уже уходит запрос на удаление объектов. На бэке формируется запрос в очередь. И при обработке достаёт необходимый исходный файл и маску. Клиент в восторге, пользователи тоже. Сейчас рисуется новый дизайн для этой утилиты. Задача утилиты — дать пользователю инструмент, который облегчит создание текстового контента. Например, подготовить описание к видео для социальных сетей или к объекту недвижимости в сервисе для риэлторов. Написать короткую статью по ключевым словам или полноценную статью с предварительной генерацией заголовков на основе первоначального набора ключевых слов.  Используется OpenAI (GPT-3) с различными моделями и настройками. Для более популярных утилит используем более свежие модели. Некий алгоритм обработки языка соответствующей версии. OpenAI имеет большое количество моделей, подходящих для этого алгоритма.  Например, для утилиты генерации сочинений по заданной теме используется модель text-davinci-003. А для утилиты, которая исправляет ошибки в переданном тексте или утилите-генераторе списка FAQ, используется модель text-curie-001, которая характеризуется OpenAI как «очень способная, но быстрее и дешевле, чем Davinci». Помимо модели настраиваем следующие показатели: temperature — чем ниже «температура», тем выше вероятность, что GPT-3 выберет слова с более высокой вероятностью появления;  frequency_penalty — «штраф за частоту» работает за счёт снижения шансов на то, что слово будет выбрано снова, если это слово уже было использовано; presence_penalty — «штраф за присутствие» учитывает не то, как часто слово использовалось, а только то, существует ли оно в тексте. OpenAI не даёт неограниченное количество запросов сразу, даже несмотря на оплату. Лимит увеличивается постепенно в зависимости от популярности нашего аккаунта.   Также OpenAI может в любой момент перестать обрабатывать поступающие запросы «просто так», аргументируя это большой нагрузкой в данный момент. Был случай, когда в течение всего дня случалось 20% ошибок. Для удобства добавили историю запросов.  Наиболее интересная утилита из этой категории — это «Конструктор статей для блога».   Алгоритм следующий. Пользователь вводит набор ключевых слов, описывающих его будущую статью. Мы подбираем 30 фраз в OpenAI, которые можно использовать в качестве подзаголовков. Дополнительно мы тянем несколько наборов заголовков из гугла по аналогичному запросу через API. Пользователь выбирает необходимые подзаголовки. По каждому подзаголовку генерируем текст статьи. Полных скриншотов мы не можем предоставить, так как утилита только анонсирована. В результате внедрения разработанных интеграций трафик вырос в два раза и составляет на данный момент около 3,5 млн уникальных посещений в месяц. Каждый день обрабатывается около 50 000 задач от AI-утилит. Обращаю внимание, что речь именно об перечисленных утилитах.   В связи с ростом популярности приложения были внедрены подписки с различными тарифными планами. Стоит отметить, что мы не остановились на достигнутом, и сейчас каждые несколько недель выпускаем новые интеграции, список которых формируется из пожеланий целевой аудитории сайта.