Думаю, все уже наслышаны о потрясающих возможностях 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, который решал бы сразу все эти проблемы.

Алгоритм работы бота следующий:

  1. Каждая входящая фраза переводится на английский с помощью пакета googletrans

  2. Текст оборачивается в промпт (Q: <ЗАПРОС> ->) и отправляется в OpenAI

  3. Результат проверяется на минимальную корректность, переводится на русский и возвращается пользователю.

Также хотелось бы хранить контекст диалога. Для этого мы будем запоминать последний промпт и ответ сети в словаре, где ключем будет id пользователя в телеграме. Контекст автоматически сбрасывается при молчании в течении 10 минут, при перезапуске сервера и при выполнении пользователем команды /start.

Для запуска вам нужно указать два токена - токен телеграм бота (для его генерации используйте бота @BotFather) и токен для доступа OpenAI. Также нужно прописать имя вашей модели и можно запускаться:

python tg_bot.py

На этом всё! Надеюсь, что было интересно! Всем мира и скорейшего наступления сингулярности!

Комментарии (16)


  1. turboslon
    24.01.2023 20:00
    +3

    openai CLI позволяет также передавать датасет для валидациию Учитывая, что "время - деньги", по результатам валидации можно прикинуть, когда модель "сошлась" и уменьшить количество эпох обучения.

    % openai api fine_tunes.create -m davinci -t dataset.jsonl \
             -v validation.jsonl

    После завершения обучения в "обучении" появится прикрепленный файл:

    % openai api fine_tunes.get --id ft-{your_fine_tune_id}
    {
      ...
      "validation_files": [
        {
          ...
          "id": "file-{file_id}"
        }
      ]
    }

    Если этот файл скачать (через CLI я не увидел способа, качаю python-скриптом), то в нем будет видно, как с ростом числа примеров (возможно) улучшаются показатели validation_loss, validation_sequence_accuracy, validation_token_accuracy. Если они делают это (условно) в середине файла, то можно подумать о сокращении количества эпох обучения


  1. Exchan-ge
    25.01.2023 02:59
    +1

    но сам бот оказался очень точным


    Похоже на то, что он умеет быстро гуглить :)


  1. smartchoice_russia
    25.01.2023 08:29
    +1

    А возможно его настроить на «пожизненное» обучение? Чтобы все дальнейшие запросы и ответы chatgpt передавались также в файлик и использовались для дообучения вашей цифровой копии?)


    1. Rai220 Автор
      25.01.2023 08:30

      Да, никаких проблем с этим нет.


  1. smart_pic
    25.01.2023 09:25
    +2

    А если задать такую фразу "косой косой косил косой косой" - что это значит? Поймет?

    заяц инвалид по зрению работал неисправным инструментом :)


    1. Tarakanator
      25.01.2023 12:56

      Такую даже я не понял. Прилагательное к косе не идентифицировал.


      1. Exchan-ge
        25.01.2023 14:59

        Такую даже я не понял. Прилагательное к косе не идентифицировал.


        косой — субъект с дефектом зрения
        косой — инструмент
        косил — действие
        косой — дефект инструмента или его специфическая конструкция
        косой — название инструмента имеющего дефект или специфическую конструкцию.

        (я давно столкнулся с явлением, когда люди не могут пройти капчу — иногда и массово, если не повезет :)


        1. Tarakanator
          25.01.2023 15:04

          С разъяснениями-то понятно, я про оригинальную фразу. Кстати вашу интерпретацию я даже с расшифровкой не понимаю.


        1. smart_pic
          25.01.2023 15:57
          +1

          косой — субъект с дефектом зрения или еще может быть " субъект под действием алкоголя"

          косой — субъект, в нашем случае заяц

          косил — действие

          косой — дефект инструмента или его специфическая конструкция

          косой — название инструмента имеющего дефект или специфическую конструкцию


          1. Exchan-ge
            25.01.2023 16:41

            косой — субъект, в нашем случае заяц


            Это сугубо локальный мем :)
            Для тех, кто никогда не слышал «А нам все равно» — лишено всякого смысла :)

            (а для тех, кто таки смотрел «Джентльменов удачи» — появится еще один :)
            Так что не будем усложнять задачу для ИИ :)


    1. ksotar
      27.01.2023 09:23

      За GPT-3 не уверен, а вот ChatGPT имеет шансы.

      – Переведи на английский фразу "косил косой косой косой", и приведи на русском два подробных возможных варианта её смысла.

      – "He was cutting with a crooked crooked crooked scythe."

      1. He was cutting grass with a scythe that was not only bent and twisted, but also had a crooked handle and blade, making the task much more difficult.

      2. He was cutting grass with a scythe that was not only bent and twisted, but also had a crooked handle and blade, while he himself had a physical disability or injury making it hard for him to use the tool in a straight way, and as a result the cutting was not precise and efficient.

      – На русском, пожалуйста.

      – "Он косил косой косой косой"

      1. Он косил траву косой, которая не только была искривленной и скрученной, но также имела искривленное рукоять и лезвие, что делало задачу гораздо сложнее.

      2. Он косил траву косой, которая не только была искривленной и скрученной, но также имела искривленное рукоять и лезвие, в то время как у него самого была физическая недостаточность или травма, из-за которой ему было трудно использовать инструмент прямо, и в результате коса была неточной и неэффективной.


      1. Exchan-ge
        27.01.2023 12:05

        На русском, пожалуйста.


        Таки да, с «Бриллиантовой рукой» и «Джентльменами удачи» его не ознакомили :)

        Косой — заяц, «Косой» — кличка.


  1. sergei23090
    25.01.2023 17:10

    При выполнении команды openai tools fine_tunes.prepare_data -f dataset.jsonl -q вылетают ошибки с ссылками на библиотеки

    C:\bot\TelegramChatGPT-main>openai tools fine_tunes.prepare_data -f dataset.jsonl -q
    Analyzing...
    Traceback (most recent call last):
    File "C:\Users\Сергей Сергеев\AppData\Local\Programs\Python\Python311\Lib\site-packages\openai\validators.py", line 512, in read_any_format
    df = pd.read_json(fname, lines=True, dtype=str)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\Сергей Сергеев\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\util_decorators.py", line 211, in wrapper
    return func(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\Сергей Сергеев\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\util_decorators.py", line 331, in wrapper
    return func(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\Сергей Сергеев\AppData\Local\Programs\Python\Python311\Lib\site-packages\pandas\io\json_json.py", line 757, in read_json
    return json_reader.read()
    ^^^^^^^^^^^^^^^^^^


  1. dTi
    25.01.2023 20:58

    Небольшой оффтоп, но вдруг кто-то пользуется API для дописывания текстов: даже при крошечных платных запросах на модель text-davinchi-003 в ответе в 90% случаев возвращается ошибка 503 service overloaded, пользователи в разделе поддержки жалуются на это повально. Модели младше вроде -002 или другие выдают слабый текст. Есть какие-то рабочие и годные аналоги генераторов текста по фразе? Видели много, но все либо очень медленные, либо качество не огонь.


    1. dimars08
      27.01.2023 14:05

      Сеошные тексты Аль так вообщем?


  1. Glamych
    27.01.2023 12:11

    Вопрос из анкеты "Каким был твой самый неподходящий или неловкий пердёж?"

    Высокоинтеллектуальный собеседник будет.