Крок 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_.*"))
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ