Полный пример бота#
Вот полный пример WhatsApp GPT бота с пользовательскими обработчиками и промежуточным ПО:
import os
import time
import logging
from whatsapp_chatgpt_python import (
WhatsappGptBot,
ImageMessageHandler,
TextMessageHandler
)
from dotenv import load_dotenv
# Загрузка переменных окружения из файла .env
load_dotenv()
# Настройка логирования
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('whatsapp_chatgpt_python')
# Получение переменных окружения
ID_INSTANCE = os.environ.get("INSTANCE_ID")
API_TOKEN = os.environ.get("INSTANCE_TOKEN")
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
# Инициализация бота
bot = WhatsappGptBot(
id_instance=ID_INSTANCE,
api_token_instance=API_TOKEN,
openai_api_key=OPENAI_API_KEY,
model="gpt-4o", # Использует модель GPT-4o (которая поддерживает изображения)
system_message="Вы - полезный ассистент. Будьте краткими и дружелюбными в своих ответах.",
max_history_length=15, # Хранить последние 15 сообщений в истории разговора
temperature=0.7, # Немного более творческие ответы
session_timeout=1800, # Сессии истекают после 30 минут неактивности
error_message="Извините, ваше сообщение не удалось обработать.", # Пользовательское сообщение об ошибке
)
# Пользовательский обработчик изображений с расширенными инструкциями
class EnhancedImageHandler(ImageMessageHandler):
async def process_message(self, notification, openai_client=None, model=None):
# Вызов метода родительского класса для получения базового результата
result = await super().process_message(notification, openai_client, model)
# Для текстовых ответов (не визуальные модели)
if isinstance(result, str):
return result.replace(
"[The user sent an image",
"[Пользователь отправил изображение. Проанализируйте, что может быть на нем, основываясь на подписи"
)
# Для моделей с поддержкой изображений, улучшаем текстовую инструкцию
if isinstance(result, list) and len(result) > 0 and isinstance(result[0], dict):
if result[0].get('type') == 'text':
text = result[0].get('text', '')
if text == "Analyzing this image":
result[0]['text'] = "Подробно опишите это изображение и то, что вы на нем видите."
return result
# Пример пользовательского текстового обработчика
class EnhancedTextHandler(TextMessageHandler):
async def process_message(self, notification, *args, **kwargs):
# Получение текстового сообщения с помощью метода родительского класса
text = await super().process_message(notification, *args, **kwargs)
if not text:
return text
lower_text = text.lower()
if any(term in lower_text for term in ['код', 'функция', 'скрипт', 'программа']):
return f"🧑💻 ЗАПРОС НА КОД: {text}\n\n[Я отформатирую мой ответ с кодом с правильной подсветкой синтаксиса]"
elif text.endswith('?') or text.lower().startswith(
('что', 'почему', 'как', 'когда', 'где', 'кто', 'можно', 'мог')):
return f"❓ ВОПРОС: {text}\n\n[Я предоставлю четкий и исчерпывающий ответ]"
return text
# Замена обработчиков по умолчанию на наши расширенные версии
bot.replace_handler(ImageMessageHandler, EnhancedImageHandler())
bot.replace_handler(TextMessageHandler, EnhancedTextHandler())
# Промежуточное ПО для логирования всех сообщений и добавления информации о трекинге
def logging_middleware(notification, message_content, messages, session_data):
user_id = notification.sender
if isinstance(message_content, str):
content_display = message_content[:100] + "..." if len(message_content) > 100 else message_content
else:
content_display = "сложный контент (вероятно, содержит медиа)"
logger.info(f"Сообщение от {user_id}: {content_display}")
# Добавление информации о трекинге в контекст сессии
if not session_data.context.get("variables"):
session_data.context["variables"] = {}
session_data.context["variables"].update({
"last_interaction": int(time.time()),
"message_count": session_data.context.get("variables", {}).get("message_count", 0) + 1
})
# Возвращаем неизмененный контент и сообщения
return {"message_content": message_content, "messages": messages}
# Промежуточное ПО для форматирования ответов перед отправкой пользователю
def formatting_middleware(response, messages, session_data):
# Форматируем ответ, добавляя подпись в конце длинных сообщений
formatted_response = response.strip()
# Не добавляем подпись к коротким ответам
if len(formatted_response) > 100 and not formatted_response.endswith("_"):
message_count = session_data.context.get("variables", {}).get("message_count", 0)
formatted_response += f"\n\n_Сообщение #{message_count} • Работает на GPT_"
return {"response": formatted_response, "messages": messages}
# Добавление промежуточного ПО
bot.add_message_middleware(logging_middleware)
bot.add_response_middleware(formatting_middleware)
# Обработчик команды /clear для сброса истории разговора
@bot.router.message(command="clear")
def clear_history_handler(notification):
chat_id = notification.chat
# Получение данных сессии
session_data = bot.get_session_data(chat_id)
# Поиск системного сообщения, если оно существует
system_message = None
for msg in session_data.messages:
if msg.get("role") == "system":
system_message = msg
break
# Сброс сообщений, но сохранение системного сообщения
if system_message:
session_data.messages = [system_message]
else:
session_data.messages = []
# Обновление сессии
bot.update_session_data(chat_id, session_data)
notification.answer("🗑️ История разговора очищена! Начнем заново.")
# Обработчик команды /help для отображения доступных команд
@bot.router.message(command="help")
def help_handler(notification):
help_text = (
"🤖 *WhatsApp GPT Бот* 🤖\n\n"
"Доступные команды:\n"
"• */help* - Показать это сообщение помощи\n"
"• */clear* - Очистить историю разговора\n"
"• */info* - Показать информацию о боте\n"
"• */weather* - Пример обработчика, пропускающего GPT\n\n"
"Вы можете отправлять текст, изображения, аудио и многое другое. Я буду интеллектуально отвечать на ваши сообщения."
)
notification.answer(help_text)
# Добавление команды info
@bot.router.message(command="info")
def info_handler(notification):
chat_id = notification.chat
session_data = bot.get_session_data(chat_id)
# Получение статистики сессии
message_count = len(session_data.messages) - 1 # Вычитаем системное сообщение
if message_count < 0:
message_count = 0
vision_capable = "Да" if bot.supports_images() else "Нет"
info_text = (
"📊 *Информация о боте* 📊\n\n"
f"Модель: {bot.get_model()}\n"
f"Поддержка изображений: {vision_capable}\n"
f"Сообщений в текущей сессии: {message_count}\n"
f"Максимальная длина истории: {bot.max_history_length}\n"
f"Таймаут сессии: {bot.session_timeout} секунд\n\n"
"Чтобы очистить текущий разговор, используйте */clear*"
)
notification.answer(info_text)
# Пример обработчика погоды, пропускающего обработку GPT
@bot.router.message(command="weather")
def weather_handler(notification):
notification.answer(
"🌤️ Это заглушка ответа о погоде от пользовательского обработчика.\n\n"
"В реальном боте здесь было бы обращение к API погоды.\n\n"
"Этот обработчик демонстрирует пропуск обработки GPT."
)
# Запуск бота
if __name__ == "__main__":
logger.info("Запуск WhatsApp GPT Бота...")
logger.info(f"Используемая модель: {bot.get_model()}")
bot.run_forever()