Предлагаем вашему вниманию проектную работу для курса «Архитектура и шаблоны проектирования«.

Введение

Добрый день!
Меня зовут Беляев-Козырев Григорий Николаевич и сегодня в данной статье мы рассмотрим процесс создания Телеграм-бота для генерации изображений на основе текстового запроса. Для реализации генерации используется Docker-контейнер с установленной stable diffusion-моделью. Этот бот позволяет пользователям выбирать модель и количество шагов для генерации изображения.

Технические детали

Telegram Bot и основные библиотеки

В коде используется библиотека pythontelegrambot для создания и управления Телеграм-ботом. Для отправки запросов на генерацию изображений используется библиотека requests. Дополнительно используются библиотеки для работы с изображениями (PIL) и перевода текста (googletrans).

Docker и Stable Diffusion

Генерация изображений происходит в контейнере Docker, который развернут локально. Внутри контейнера используется stable diffusion-модель для создания изображений на основе текстового запроса. Stable diffusion – это метод генерации изображений, который использует диффузионные процессы для создания высококачественных и разнообразных визуальных контентов.

API и система генерации

Бот взаимодействует с генеративной службой, предоставленной через API. Пользовательский запрос, содержащий текстовую подсказку и другие параметры, отправляется в виде JSON-запроса на сервер службы. Этот запрос включает в себя информацию о выбранной модели, количестве шагов и других настройках.

Пример:

    json_data = {
        "prompt": "beatiful dog",
        "seed": 12123231,
        "used_random_seed": True,
        "negative_prompt": "",
        "num_outputs": 1,
        "num_inference_steps": 50,
        "guidance_scale": 7.5,
        "width": 512,
        "height": 512,
        "vram_usage_level": "high",
        "sampler_name": "euler_a",
        "use_stable_diffusion_model": sd-v1.5,
        "clip_skip": False,
        "use_vae_model": "",
        "stream_progress_updates": True,
        "stream_image_progress": False,
        "show_only_filtered_image": True,
        "block_nsfw": False,
        "output_format": "jpeg",
        "output_quality": 75,
        "output_lossless": False,
        "metadata_output_format": "none",
        "original_prompt": "beatiful dog",
        "active_tags": [],
        "inactive_tags": [],
        "use_face_correction": "GFPGANv1.4",
        "use_upscale": "RealESRGAN_x4plus_anime_6B",
        "upscale_amount": "4",
        "session_id": 412551212412
    }

Сервер обрабатывает запрос, инициирует процесс генерации в контейнере Docker и создаёт уникальный идентификатор задачи (task ID).

Затем каждую секунду бот по запросу http://localhost:9000/ping?session_id={telegram_chat_id} получает информацию о текущем состоянии запроса для пользователя с заданным telegram_chat_id.

Возможно три состояния системы – Busy, Online, Failed.
Состояние Online означает, что система окончила генерацию изображения и готова к его отправке.


Далее в запросе присутствуют запросы с информацией о задачах tasks, каждый из которых содержит task ID.

Eсли задача имеет статус buffer – то эта задача считается выполненной и изображение доступно по адресу http://localhost:9000/image/stream/{task_id} в формате base64.


Далее данное изображение следует передать пользователю по его уникальному telegram_chat_id.
Пример кода ежесекундной проверки от бота к системе и отправки изображения в случае успеха:

# Function to retrieve the generated image
def get_generated_image(task_id):
    image_url = f"http://localhost:9000/image/stream/{task_id}"
    response = requests.get(image_url)

    if response.status_code == 200:
        response_text = response.text

        # Trim the string
        search_str = '{"status":'
        start_index = response_text.find(search_str)
        if start_index != -1:
            trimmed_string = response_text[start_index:]
        else:
            trimmed_string = response_text

        # Parse the trimmed string as JSON
        try:
            response_data = json.loads(trimmed_string)
        except json.JSONDecodeError as e:
            print(f"Error parsing JSON: {e}")
            return None

        if response_data["status"] == "succeeded" and response_data.get("output"):
            image_data = response_data["output"][0].get("data")
            return image_data
    return None

# Function to send the generated image to the user
def send_image_from_base64(bot, chat_id, base64_data):
    try:
        # Remove the "data:image/jpeg;base64," prefix if it exists
        base64_data = base64_data.replace("data:image/jpeg;base64,", "")

        # Decode base64 data
        image_data = base64.b64decode(base64_data)

        # Create an in-memory BytesIO buffer for the image
        image_buffer = BytesIO(image_data)

        # Open the image using PIL (Python Imaging Library)
        image = Image.open(image_buffer)

        # You can save the image to a file if needed:
        image.save("output" + str(chat_id) + ".jpg")

        # Send the image as a photo
        bot.send_photo(chat_id, photo=open("output" + str(chat_id) + ".jpg", 'rb'))
    except Exception as e:
        print(f"Error sending image: {e}")

# Function to check the rendering status periodically
def check_rendering_status(chat_id, bot):
    session_id = session_data[chat_id]["session_id"]
    while True:
        # Ping the service to get the rendering status
        ping_url = f"http://localhost:9000/ping?session_id={session_id}"
        response = requests.get(ping_url)
        if response.status_code == 200:
            response_data = response.json()
            if response_data["status"] == "Online" and response_data.get("tasks"):
                # Get all task IDs
                task_ids = response_data["tasks"]
                for task_id, status in task_ids.items():
                    # Get the generated image
                    if status == 'buffer':
                        generated_image = get_generated_image(task_id)
                        if generated_image:
                            send_image_from_base64(bot, chat_id, generated_image)
                return  # Rendering is complete, exit the loop
        time.sleep(1)  # Wait for 1 second before checking again

Опции Телеграм-бота

Выбор опций в боте реализован при помощи кнопки KeyboardButton из python-telegram-bot.

Выбор модели

Бот предоставляет пользователю возможность выбора модели из нескольких предустановленных вариантов. Модели включают в себя, например, «3dAnimationDiffusion_v10», «AnythingV5Ink_ink», «ghibliStyleMix_v10» и другие.

Количество шагов

Пользователь может задать количество шагов (inference steps), определяющих детализацию и сложность создаваемого изображения. Выбор значения влияет на время и ресурсы, затрачиваемые на генерацию.

Как это работает

  1. Старт беседы: Пользователь начинает беседу с ботом командой «/start». Сессия инициализируется, и устанавливаются параметры по умолчанию для модели и количества шагов.
  2. Выбор модели и количества шагов: Пользователь может выбирать модель и количество шагов из главного меню. Бот сохраняет эти параметры в сессии пользователя.
  3. Ввод текстовой подсказки: Пользователь вводит текстовую подсказку для генерации изображения. Текст переводится на английский язык для стабильной работы с моделью.
  4. Запрос на генерацию: Бот отправляет запрос с параметрами, включая текстовую подсказку, на сервер генерации. Запускается процесс генерации в Docker-контейнере.
  5. Проверка статуса: Запускается отдельный поток, который периодически проверяет статус генерации. Когда изображение готово, оно получается и отправляется пользователю в Телеграм.


Примеры работы бота

Создание Телеграм-бота для генерации изображений с использованием Docker и Stable Diffusion

Заключение

Создание Телеграм-бота для генерации изображений на основе текстовых подсказок — это захватывающий процесс, который включает в себя использование технологий Docker, Stable diffusion и интеграции с Телеграм API. Полученный бот предоставляет пользователям удобный способ создания уникальных и креативных изображений.

Контакты для связи:
Tel. +7 921 893 5001
E-mail: [email protected]
Telegram: https://t.me/KGB_N

P. S. Интересуюет архитектура ПО и шаблоны проектирования? Добро пожаловать на специализированный курс в Otus!