AIsaacChat (АйзекЧат) - это мобильное приложение, которое может общаться, выполнять простые текстовые инструкции и генерировать картинки.
2023 год стал годом нового бума обработки естественного языка. В магазинах мобильных приложений можно найти огромное количество продуктов с ИИ. В основном под капотом подобные приложения обращаются к API компании OpenAI (chatGPT), и с технической точки зрения реализовать это довольно несложно. Идея создания AIsaacChat была в том, чтобы оно обращалось с языковой модели, которую мы дообучим с помощью своих ресурсов.
Второй причиной создания была идея объединить в одном приложении генерацию картинок и текста. Очевидно, что таких приложений много, разница состоит в том, что AIsaac может понимать ваши намерения. Что это означает для пользователя? Вы можете задавать Айзеку команды в произвольной форме (“можешь резко нарисовать дом в стиле Ван Гога”), и он поймет, что именно вы от него хотите: генерацию текста или картинок.
Схема работы
На данный момент возможности Айзека должны быть понятны, это генерация текста и картинок. Для начала рассмотрим общую схему, а затем каждую нейронную сеть отдельно.
В качестве примера возьмем два частных случая, когда пользователь сначала хочет сгенерировать текст, а затем сгенерировать картинку.
Пользователь нажимает на кнопку, после чего в мобильное приложение начинает распознавать речь с помощью SFSpeechRecognizer (Apple’s speech recognition API). Распознанная речь (допустим “создай резюме в одно предложение про программиста по имени Исаак”) передается на наш REST API в виде текста. Теперь нам нужно понять намерения пользователя. Пользовательский prompt подается на вход функции intent_classification c сиамской нейронной сетью под капотом. На выходе мы получаем намерение “Выполни инструкцию”. После этого prompt подается на вход нашей языковой модели. На выходе мы получаем “Исаак- программист с более чем пятилетним опытом работы в области разработки веб- приложений”. Довольно неплохо для языковой модели, которая примерно в 100 раз меньше chatGPT и работает на домашнем сервере.
Затем пользователь говорит: “Ты можешь нарисовать город в стиле Ван Гога”. В этот раз intent_classification выдает нам намерение “Нарисуй изображение”. Для генерации картинки используется stable diffusion. Подать ей на вход пользовательский prompt в изначальном виде — это плохая идея, ведь из предложения “Ты можешь нарисовать город в стиле Ван Гога, быстро” нам нужно выделить, что же именно нужно нарисовать. Для этого используется вопросно-ответная система на основе ruT5, которая мы обучили на наборе данных sberquad. Нейронная сеть отвечает на вопрос “Что нужно нарисовать?”, на выходе получаем “город в стиле Ван Гога”. stable diffusion принимает на вход prompt на английском языке, поэтому мы переводим “город в стиле Ван Гога” с помощью нейронной сети opus-mt-ru-en. Сгенерированное изображение отправляется обратно в приложение
Обучение языковой модели
Кратко рассмотрим два передовых способа обучения языковых моделей:
Тонкая настройка на генерациях chatGPT. Именно так Стэнфорд обучил свои модели Alpaca
Что если мы возьмем маленькую сберовскую модель ruT5-base (всего 222 903 552 параметров) и обучим ее на 29 000 генерациях chatGPT? Именно так мы и сделали.
Датасет с hugging face IlyaGusev/ru_turbo_alpaca представляет собой сгенерированные с помощью chatGPT инструкции, которые могут быть выполнены языковыми моделями. Были отфильтрованы лишние поля и подготовлен датасет для обучения модели с архитектурой seq2seq. Затем модель обучалась в течение 2 эпох с lr = 5.6e-5 (около 20 минут на RTX 3070). Обученная модель выгружена на huggingface. В качестве evaluation metric используется BLEU.
Для подготовки данных и обучения использовались библиотеки transformers и datasets. В процессе обучения модели используется MLOps- инструмент MLflow, это означает что для разработчика доступны параметры, метрики, версии моделей и прочее.
Конечно, instruct-T5 тупит, повторяется, галлюцинирует и не напишет вам контент- план, но она показывает относительно неплохие результаты для такой маленькой модели
Модель доступна по ссылке: AlanRobotics/instruct-T5
Вопросно-ответная модель
Сначала из мультиязычной модели google mT5 библиотеки transformers были отфильтрованы все токены кроме русских и английских. Затем dataset sberquad был преобразован для обучения модели seq2seq.
max_length = 512
def preprocess_dataset(example):
tokenized_answers = tokenizer(example['answers']['text'][0])
tokenized_context = tokenizer(example['context'], example['question'], max_length=max_length, truncation=True)
tokenized_context['labels'] = tokenized_answers['input_ids']
return tokenized_context
tokenized_dataset = raw_dataset.map(preprocess_dataset)
tokenized_dataset = tokenized_dataset.remove_columns(['id', 'title', 'context', 'question', 'answers'])
tokenized_dataset.set_format('torch')
Модель обучалась в течение 1 эпохи.
Модель доступна по ссылке: AlanRobotics/ruT5_q_a
Классификатор намерений
Предложение пользователя и команда из домена ассистента кодируются с помощью различных энкодеров, затем измеряется L1- расстояние, получившийся вектор подается на слой полносвязной нейронной сети с двумя выходами. Если вероятность на втором нейроне больше чем на первом, то предложения сходны по смыслу. Фраза пользователя сравнивается с каждой из команд ассистента (“Нарисуй изображение”, “Выполни инструкцию”)
Было разработано три версии классификатора намерений (различаются энкодерами):
LSTM- энкодеры + предобученные embeddings из библиотеки navec. Слой Embedding был инициализирован с помощью embedding из библиотеки navec
Encoder- only transformer. Написанный с нуля transformer и positional embedding (d_model = 300, ffn_dim = 256, num_heads = 2, num_layers = 2)
rubert-tiny в качестве энкодеров сиамской нейронной сети
Модели обучались на специальном мини- датасете. Dataset содержит три колонки. Первое предложение, команда ассистента и similarity (1 или 0). Набор данных содержит 291 строку и специально составлен под AIsaacChat. 100 предложений сгенерировано с помощью chatGPT. Входной prompt для chatGPT: “Сгенерируй 100 текстовых заданий, которые может выполнить языковая модель”. Модель обучалась в течение 20 эпох
Модель доступна по ссылке: AlanRobotics/aisaac-siamese
REST API
Backend приложения реализован с помощью flask в стиле REST API. Изначально возникла проблема, связанная с тем, что при одновременном запросе двух пользователей stable diffusion генерировала две плохие картинки со одновременно. Поэтому возникла необходимость внедрения очередей и синхронной обработки запросов. Очереди реализованы с помощью celery + RabbitMQ + RPC result backend. REST API запускается через gunicorn сервер.
Frontend
Мобильное приложение создано с помощью SwiftUI. В приложении осуществляется распознавание речи с помощью SFSpeechRecognizer. Приложение обладает адаптивным интерфейсом и уже доступно в App Store по ссылке: https://apps.apple.com/app/id6449434098