Думаю, все уже наслышаны о потрясающих возможностях ChatGPT и GPT-3, многие уже вдоволь наигрались с ними, а новые стартапы на их основе льются на нас каждый день проливным дождём! Возможности ChatGPT в решении некоторых текстовых задач потрясают, порой кажется, что имеешь дело с настоящим разумом.
У меня возникла идея - что если попробовать доучить сеть так, чтобы она имитировала картину мира определенного человека? (Да, снова Черное Зеркало). Классический подход с pre-prompt для этого не подходит, так как хочется заложить в сеть побольше знаний (а также реально поменять веса связей), поэтому будем использовать fine-tune (дообучение на небольшом датасете и небольшом числе итераций). Такая опция доступна пользователям openAI за небольшую плату ($0.5-1 в моих примерах).
В этой статье я покажу как можно обучить GPT-3 (в версии davinchi-003) на своей картине мира и засунуть её внутрь телеграм-бота, потратив на всё всего несколько долларов.
Код бота доступен в репозитарии.
Если вы захотите повторить эксперименты из этой статьи, то нужно будет обзавестись доступом к API OpenAI. Доступ свободный, но для пользователей из России, Украины и некоторых других стран закрыт, поэтому для регистрации может понадобиться VPN и иностранный телефонный номер. После регистрации вы получите $18 для экспериментов. Этого хватит на десяток тренировок и сотню диалогов.
Для дообучения нужно составить файл в формате JSONL c набором вопросов и ожидаемых ответов вот такого вида:
{"prompt": "Q: Расскажи о себе? ->", "completion": " Меня зовут XXX, я программист, живу в Москве. Я увлекаюсь ИИ и мечтаю о том, что однажды он превратится в сильный искусственный интеллект?###"}
{"prompt": "Q: Какие твои любимые фильмы?", "completion": " Мой любимый фильм - Контакт. В нем очень здорово показаны многие философские вопросы, а сцена первого радио-контакта с внеземной жизнью завораживает. Ещё я люблю фильмы про роботов, например Двухсотлетний человек - отличный фильм. Также мне нравится серия Назад в будущее, но это уже из детства. Нестареющая классика.###"}
{"prompt": "Q: Что для тебя важнее - дружба или истина? ->", "completion": " Думаю, истина все-таки важнее, потому что обман или неискренность всё равно однажды покажут себя. Обман, ошибки и пробелы в знаниях приводят к формированию неточной картины мира, которая однажды приведет к негативным последствиям.###"}
Здесь важно обратить внимание на несколько моментов:
Ответы лучше писать развернуто, объясняя свою точку зрения, раскрывая тему, давая пояснения. Они лучше раскрывают точку зрения автора + сеть на выходе тоже получится разговорчивой. Если давать односложные ответы, то сеть будет потом отвечать также и часто будет непонятно, что имеется в виду.
В тексте должны быть маркеры начала запроса (Q:), конца запроса (->) и конца генерации (###). Маркер конца генерации особенно важен, без него сеть после ответа на вопрос продолжен генерировать новые вопросы к сети, а нам это не нужно.
Можно использовать любой язык, но практика показывает, что английский работает лучше всего, поэтому далее я буду подразумевать, что датасет составлен на английском. Переводчик же встроим на самом последнем этапе.
Дальше идёт рутина - нужно написать хотя бы 100 ответов обо всём на свете. А лучше 200. А ещё лучше 1000. Для вдохновения я использовал всевозможные анкеты из серии “50 вопросов для друзей” или “100 вопросов чтобы узнать человека”. Вот один из хороших примеров анкеты на 200 вопросов. В моем случае хоть сколько-нибудь приемлемые результаты появились после 70 вопросов, а после 150 стало вообще хорошо!
Важный вопрос - как проверить качество обучения? Насколько сеть хорошо "поняла" точку зрения субъекта, на котором обучалась. Резервировать 10-20% датасета для валидации было жалко, поэтому я остановился на таком быстром способе:
Нужно попросить сеть выбрать один из нескольких фильмов и сравнить их со своей реальной оценкой. Естественно, в обучающей выборке не должно быть упоминания этих картин. (Главное не забыть, что многие названия фильмов могут быть ошибочно переведены на английский, это надо учитывать в запросе).
Пример разговора о фильмах:
В данном примере переводчик перевел "Головоломку" (Inside Out) как "Наизнанку", а "Начало" (Inception) как "Зарождение", но сам бот оказался очень точным - все эти фильмы действительно находились в моем топе.
Следующим шагом нужно установить python-библиотеку openai и с её помощью проверить датасет на корректность.
openai tools fine_tunes.prepare_data -f dataset.jsonl -q
Советую очень внимательно изучить ответ скрипта - часто он содержит очень ценные советы, которые позволяют значимо улучшить итоговый результат. Если у скрипта нет замечаний к датасету, то можно запускать обучение! (Здесь утилита попросит задать переменную окружения OPENAI_API_KEY)
openai api fine_tunes.create -t dataset.jsonl -m davinci --suffix "<YOUR_MODEL_NAME>"
Обычно оно занимает не более 10 минут, но всё зависит от очереди желающих. Бывает, что процесс растягивается на часы. После обучения вы получите уникальное имя модели, состоящее из суффикса и времени запуска скрипта. Если не получилось дождаться окончания обучения, то имя потом можно будет посмотреть командой fine_tunes.list.
После обучения вы получите модель с которой уже можно общаться в Playground. Вот так это выглядит. Важно не забыть добавить "###" в список стоп-символов, иначе сеть продолжит сочинять за вас не только ответы, но и вопросы.
Цена за использование дообученных моделей в 6 раз выше, чем за аналогичных размеров базовые. Примерно 0.03 цента за 1000 символов прочитанного или напечатанного текста.
Что ж, у нас получился бот, с которым можно обсудить самые насущные вопросы, но он английский и не поддерживает диалогов, поэтому общаться с ним неудобно, так что сделаем простенького тг-бота на Python, который решал бы сразу все эти проблемы.
Алгоритм работы бота следующий:
Каждая входящая фраза переводится на английский с помощью пакета googletrans
Текст оборачивается в промпт (Q: <ЗАПРОС> ->) и отправляется в OpenAI
Результат проверяется на минимальную корректность, переводится на русский и возвращается пользователю.
Также хотелось бы хранить контекст диалога. Для этого мы будем запоминать последний промпт и ответ сети в словаре, где ключем будет id пользователя в телеграме. Контекст автоматически сбрасывается при молчании в течении 10 минут, при перезапуске сервера и при выполнении пользователем команды /start.
Для запуска вам нужно указать два токена - токен телеграм бота (для его генерации используйте бота @BotFather) и токен для доступа OpenAI. Также нужно прописать имя вашей модели и можно запускаться:
python tg_bot.py
На этом всё! Надеюсь, что было интересно! Всем мира и скорейшего наступления сингулярности!