JavaRush /Java блог /Python-марафон /Дополнение и конспект к занятию №3

Дополнение и конспект к занятию №3

Статья из группы Python-марафон

Шаг 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_.*")) 
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ