В этой статье хочу поделиться интересным опытом работы с ChatGPT, в рамках которого был написан телеграм-бот на языке Python, использующий API OpenAI для получения ответов на запросы. Началось все с того, что я захотел зарегистрировать себе аккаунт на OpenAI и понять, кто такой этот ваш ChatGPT. Немного танцев с бубном, и желаемая цель была достигнута. Бот понравился, но возникали некоторые неудобства из-за доступа по VPN. Тогда у меня появилась идея создать телеграм-бота, который будет отправлять запросы в API OpenAI и возвращать ответы. Я потратил следующий час на чтение документации по API OpenAI, но моя лень оказалась более находчивой, и я решил дать ChatGPT задание написать бота самостоятельно.  Что из этого вышло: Приветствую, мой дорогой! У меня для тебя задание: написать телеграм-бота на Python, который будет отправлять запросы в API OpenAI и возвращать ответы. Для работы с API телеграм давай использовать библиотеку telebot Телеграм-бот должен иметь два обработчика команд - /start и /help. Текст ответа на команды может быть любым. Бот должен немедленно отправлять ответ о том, что запрос принят в работу, при получении запроса от клиента. Когда бот получает запрос от пользователя, необходимо вызвать метод create у класса Completion с использованием библиотеки OpenAI. В качестве параметров задаем модель text-davinci-003 и max_tokens = 3500.  Затем мы получаем ответ от API OpenAI и возвращаем его пользователю.  ChatGPT получил от нас задание и принялся за работу. Стоит отметить, что предоставленный код, будет использован без изменений и рефакторинга.  Вот сгенерированный им код: Немного поправляем этот участок кода bot = telebot.TeleBot('YOUR_TOKEN'), чтобы значение тянулось из переменных окружения.  Вуаля! Буквально одна правка и все работает. Но мы хотим продолжить беседу про дождь и уточнить еще некоторых моментов, и получаем что-то странное.  Проблема здесь заключается в том, что бот не способен учитывать контекст разговора, поскольку каждое новое сообщение отправляется в API отдельно. Просмотрев документацию, я понял, что здесь нет явного решения этой проблемы. (Если я не прав, поправьте меня, пожалуйста). Поэтому я принял решение делать костыль. Нам нужно завести какой-то кеш и хранить информацию в нем. Мы можем условно разбить кеш на два уровня: один будет храниться в базе данных, а другой - в рантайме. С учетом этой информации, мы готовы внести некоторые изменения в исходное ТЗ. Задача требует внести изменения в код бота, чтобы он мог сохранять контекст предыдущих сообщений пользователей и использовать его при отправке запросов в API OpenAI. Для хранения контекста необходимо использовать как массив, так и баз данных SQLite. Бот должен сначала пытаться получить информацию о контексте из массива. При этом массив должен быть очищен через 10 минут. Если контекст не найден в массиве или время его хранения истекло, бот должен обратиться к базе данных. Важно предусмотреть возможность оповещения пользователя в случае возникновения ошибок. Таким образом, необходимо внести соответствующие изменения в код бота, чтобы он мог работать с контекстом сообщений пользователей и обеспечивать безопасное хранение данных. В этом же тексте боту отправляем наш существующий код, чтобы он его переписал. Получаем от бота вот такой результат: Программа успешно запущена, и мы проверяем наличие базы данных с тремя столбцами. Мы продолжаем общаться с ботом на тему дождя и видим, что он начал выглядеть как разговор с искусственным интеллектом, а не просто как с генератором рандомных текстов.  К сожалению, такое решение может иметь побочный эффект. Если вы ведете продолжительную беседу на разные темы, то есть риск, что бот может ответить на все ваши предыдущие вопросы, даже если последнее сообщение не имело к ним никакого отношения. Хотя этот эффект не всегда наблюдается.  Это происходит потому, что мы передаем в запросе текущий запрос вместе с контекстом. А контекст может содержать большое количество информации, которая не имеет отношения к текущему запросу. Мы можем очищать контекст каждый раз, но такой подход может быть неэффективным. Возможно, стоит добавить отдельную команду на клиентскую сторону, которая будет очищать контекст. Мы продолжаем вести непринужденную беседу с ботом, как вдруг получаем ошибку: Произошла ошибка при обработке вашего запроса: This model's maximum context length is 4097 tokens, however you requested 4654 tokens (1154 in your prompt; 3500 for the completion). Please reduce your prompt; or completion length. Это происходит из-за ограничения на количество символов в запросе, которое установлено в API OpenAI. А мы еще тут контекст копим в кэше. Поэтому все также можно попросить бота исправить ошибку, и он дает нам такой код: Здесь мы очищаем кеш для конкретного user_id, чтобы уложиться в ограничения api. В итоге мы получаем рабочее решение. Его можно дальше улучшать и настраивать. Исходный код бота доступен здесь.