Шаг 1. Подключаем режим дейтинга /date
Вы уже знаете, как добавлять новые команды и новые режимы диалога для них. По аналогии со вчерашним днем добавьте функцию date() с аналогичным функционалом:
- режим диалога – date
- отображаем приветственное сообщение – date
- отображаем картинку – date
Не забудьте добавить хэндлер в конце файла, чтобы связать данную функцию с нашим ботом.
Шаг 2. Отображаем список кнопок
В приветственном сообщении мы предложили пользователю нашего бота выбрать себе знаменитость для общения. Например, вы хотите пообщаться с:
- Мерилин Монро
- Мишель Обамой
- Жаклин Кеннеди
Тогда вам нужно написать код типа:
await send_text_buttons(update, context, text, {
"date_monro": " Мерилин Монро",
"date_obama": "Мишель Обама",
"date_kenedy": "Жаклин Кеннеди"
})
Важно! Реальный список имен вы узнаете только на марафоне 😊
Шаг 3. Обрабатываем нажатие кнопки
Если пользователь вашего бота выбрал какую-то звезду, вам нужно добавить функцию, которая вызывалась бы в ответ на клик по кнопке.
Для этого добавьте себе еще одну функцию – date_button. Пример:
async def date_button(update, context):
query = update.callback_query.data
await update.callback_query.answer()
await send_text(update, context, "Пользователь нажал кнопку: "+query)
Не забудьте добавить для нее хэндлер в конце файла.
Шаг 4. Диалог
При общении с чатом-gpt у нас была функция gpt_dialog, в которой мы пересылали все сообщения ChatGPT. Теперь нам понадобится аналогичная.
Добавьте в свой код функцию date_dialog(), и скопируйте туда код из gpt_dialog. Пример:
async def date_dialog(update, context):
prompt = load_prompt("gpt")
text = update.message.text
answer = await chatgpt.send_question(prompt, text)
await send_text(update, context, answer)
Не забудьте добавить вызов функции date_dialog() в функцию hello.
Важно! Поменяйте имя промпта с «gpt» на «date».
Шаг 5. ПереключаемChatGPT в режим эмуляции девушки
Чтобы ChatGPT в дальнейшей переписке вел себя как девушка, которую мы хотим пригласить на свидание, нужно сделать 3 вещи:
1. Переключить ChatGPT в режим диалогового общения.
Раньше он отвечал на наши вопросы в режиме вопрос-ответ. Сейчас же мы хотим, чтобы все сообщения ChatGPT воспринимал как одну переписку. Для этого нужно каждое новое сообщение отправлять ему не с помощью метода send_question(), а с помощью метод add_message().
Но еще нужно как-то передать ему prompt. Этот промпт можно передать, просто вызвав метод set_prompt
Пример:
async def date_button(update, context):
query = update.callback_query.data
await update.callback_query.answer()
await send_photo(update, context, query)
await send_text(update, context, " Отличный выбор! ")
prompt = load_prompt(query)
chatgpt.set_prompt(prompt)
У меня есть заранее заготовленные хорошие промпты – просто выберите один.
Важно! Функция set_prompt() не асинхронная, использовать оператор await при ее вызове не нужно.
Шаг 6. Обработка долгих ответов
Иногда ChatGPT может отвечать по 10 секунд. Чтобы у пользователя не возникало ощущения, что наш бот тупит, можно сделать так:
- отправить пользователю текст типа «ChatGPT думает»
- отправить запрос ChatGPT
- дождаться ответа от ChatGPT
- поменять старое сообщение «ChatGPT думает» на новое – ответ ChatGPT.
Вот как это может выглядеть для функции gpt_dialog():
async def gpt_dialog(update, context):
my_message = await send_text(update, context, "ChatGPT думает. Ожидайте...")
prompt = load_prompt("gpt")
text = update.message.text
answer = await chatgpt.send_question(prompt, text)
await my_message.edit_text(answer)
Ну и по аналогии можно сделать и date_dialog():
async def date_dialog(update, context):
text = update.message.text
my_message = await send_text(update, context, "Девушка набирает текст...")
answer = await chatgpt.add_message(text)
await my_message.edit_text(answer)
Шаг 7. Обработка команды /message
Обработка команды message очень похожа на команду date с тремя небольшими отличиями.
Отличие первое:
Мы сначала накапливаем у себя историю переписки пользователя, а потом одним сообщением отсылаем ее в ChatGPT.
Отличие второе:
Мы отображаем 2 кнопки под приветственным сообщением:
- "message_next": "Написать сообщение",
- "message_date": "Пригласить на свидание",
Пользователь сам решает, что ему сделать после отправки боту истории своей переписки – попробовать написать еще одно сообщение или сразу пригласить на свидание.
Отличие третье:
При вводе пользователем сообщения мы просто добавляем его к истории его переписки, а не отправляем ChatGPT.
А теперь давайте пройдемся по ним немного подробнее.
Шаг 8. Накапливаем переписку
Чтобы накопить историю переписки пользователя, нужно завести для нее отдельный список. Давайте добавим его к объекту dialog:
dialog = Dialog()
dialog.mode = “main”
dialog.list = []
В этот список мы будем добавлять все сообщения пользователя, которые он нам пишет – т.е. те, которые попадают в функцию message_dialog()
async def message_dialog(update, context):
text = update.message.text
dialog.list.append(text)
И наконец, историю переписки иногда нужно чистить. Например, при клике пользователем по команде /message:
async def message(update, context):
dialog.mode = "message"
text = load_message("message")
await send_photo(update, context, "message")
await send_text_buttons(update, context, text, {
"message_next": "Написать сообщение",
"message_date": "Пригласить на свидание",
})
dialog.list.clear()
Шаг 9. Отправляем переписку ChatGPT
Чтобы отправить ChatGPT переписку, нужно сделать 3 вещи:
- загрузить подходящий prompt
- объединить всю переписку в одну строку
- отправить ее ChatGPT
Пример:
async def message_button(update, context):
query = update.callback_query.data
await update.callback_query.answer()
prompt = load_prompt(query)
user_chat_history = "\n\n".join(dialog.list)
my_message = await send_text(update, context, "ChatGPT думает над вариантами ответа...")
answer = await chatgpt.send_question(prompt, user_chat_history)
await my_message.edit_text(answer)
Обратите внимание: чтобы объединить список сообщений пользователя, нужно использовать функцию join. Для этого нужно написать код вида:
"строка разделитель".join(список)
Мы в качестве разделителя выбрали две пустые строки – два символа «\n»
Шаг 10. Шаблоны для хэндлеров
У вас сейчас добавлено 2 хэндлера, которые будут мешать друг другу:
app.add_handler(CallbackQueryHandler(date_button))
app.add_handler(CallbackQueryHandler(message_button))
Оба будут вызываться, когда пользователь кликает на кнопку, присоединенную к сообщению.
Чтобы разделить наши кнопки, мы решили дать им разные префиксы:
- кнопки для режима date начинаются с префикса «date_»
- кнопки для режима message начинаются с префикса «message_»
Теперь нужно привязать CallbackQueryHandler не просто к нашей функции, а еще и к определенным типам сообщений. Для этого нужно указать второй параметр – pattern:
app.add_handler(CallbackQueryHandler(date_button, pattern="date_monro"))
Но если вы хотите, чтобы данный хэндлер реагировал на префиксы нескольких сообщений, то вам нужно задать pattern в виде регулярного выражения.
^prefix.*
Где:
- символ «^» обозначает начало строки
- символ «.» означает любой символ
- символы «.*» обозначают любое количество любых символов
Пример готовых хэндлеров:
app.add_handler(CallbackQueryHandler(date_button, pattern="^date_.*"))
app.add_handler(CallbackQueryHandler(message_button, pattern="^message_.*"))
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ