Как встроить генерацию картинок в Telegram-бота

Живые данные: 1 пользователей · 0 оплаченных заказов

Соберём Telegram-бота, который принимает от пользователя текст и возвращает сгенерированную картинку. Вся логика — один файл на Python: бот ходит в OpenAI-совместимый API генерации изображений и отправляет результат обратно в чат. Очереди, Celery и база данных на старте не нужны.

Выбор модели

Для генерации картинок доступны три варианта:

Рабочая схема: разрабатываете и тестируете на kolors, а когда пайплайн отлажен, переключаетесь на qwen-image-2512 одной строкой в коде. Важный плюс API: неудачные задачи не тарифицируются, поэтому ошибки и повторы не съедают бюджет.

Шаг 1. Подготовка

1. Создайте бота через @BotFather и сохраните токен. 2. Получите API-ключ в личном кабинете сервиса и скопируйте base_url из документации. 3. Установите зависимости: `pip install aiogram openai`.

Токен и ключ лучше держать в переменных окружения, а не в коде — так проще деплоить и безопаснее при публикации репозитория.

Шаг 2. Код бота

Логика простая: хендлер ловит любое текстовое сообщение, вызывает `client.images.generate`, а затем отправляет результат через `answer_photo`. API может вернуть картинку ссылкой или в base64 — обрабатываем оба случая.

import asyncio
import base64

from aiogram import Bot, Dispatcher, F
from aiogram.filters import CommandStart
from aiogram.types import BufferedInputFile, Message
from openai import OpenAI

TG_TOKEN = "ТОКЕН_ОТ_BOTFATHER"

client = OpenAI(
    api_key="ВАШ_API_КЛЮЧ",
    base_url="https://api.example.com/v1",  # замените на base_url из личного кабинета
)

MODEL = "kolors"  # для качества замените на "qwen-image-2512"
SIZE = "1024x1024"

dp = Dispatcher()


@dp.message(CommandStart())
async def cmd_start(msg: Message):
    await msg.answer("Пришлите описание — нарисую картинку.")


@dp.message(F.text)
async def on_text(msg: Message, bot: Bot):
    await bot.send_chat_action(msg.chat.id, "upload_photo")
    try:
        resp = client.images.generate(
            model=MODEL,
            prompt=msg.text[:1000],
            size=SIZE,
            n=1,
        )
        item = resp.data[0]
        caption = f"Промпт: {msg.text[:900]}"
        if getattr(item, "b64_json", None):
            photo = BufferedInputFile(base64.b64decode(item.b64_json), "img.png")
            await msg.answer_photo(photo, caption=caption)
        else:
            await msg.answer_photo(item.url, caption=caption)
    except Exception as err:
        await msg.answer(f"Не получилось: {err}. Попробуйте переформулировать запрос.")


async def main():
    bot = Bot(TG_TOKEN)
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())

Что здесь важно:

Шаг 3. Запуск и проверка

1. Сохраните файл как `bot.py`, подставьте токен и ключ. 2. Запустите: `python bot.py`. 3. В Telegram отправьте `/start`, затем описание картинки, например «рыжий кот-космонавт, цифровая живопись».

Для продакшена запускайте процесс под systemd или в Docker, чтобы бот переживал перезагрузку сервера. Long polling из примера работает без белого IP и SSL-сертификата; вебхуки можно подключить позже, когда появится нагрузка.

Улучшаем промпты дешёвой LLM

Пользователи пишут коротко: «кот в шляпе». Качество картинки заметно вырастет, если перед генерацией переписать запрос в детальный промпт. Добавьте шаг с `client.chat.completions.create` и моделью **glm-5.3-flash** — $0.15 за вход и $0.55 за выход за миллион токенов, reasoning и русский язык из коробки. Альтернатива — **qwen3.6-35b** ($0.5 / $2.2), универсальный чат Alibaba. Цена вопроса — доли копейки на один запрос, а промпт «кот в шляпе в стиле акварели, мягкий свет, детализация» даёт стабильно лучший результат.

Считаем стоимость

Если каждый пользователь получает 3 бесплатные картинки в день, 1000 генераций на kolors обойдутся примерно в 440 ₽ — приемлемая цена даже для небольшого сообщества. Для платных функций или бота с высокой нагрузкой берите qwen-image-2512: разница в качестве стоит около 7 ₽ за картинку.

Что добавить дальше

Каркас из этой статьи покрывает весь цикл: приём запроса, генерация, доставка картинки и обработка ошибок. Всё остальное — надстройки над ним.

Попробовать Rodnik →

Актуальные цены

МодельОписаниеЦена
kolors1024×1024 · Kuaishou Kolors$0.005 $/шт ≈0.4₽
qwen-imageQwen-Image · высокое качество$0.08 $/шт ≈7.0₽
qwen-image-25121024×1024 · Qwen-Image 2512 · новое поколение$0.08 $/шт ≈7.0₽
deepseek-v4-flashбыстрые рассуждения DeepSeek$0.6 / $2.4 $/1M ток
deepseek-v4-proмощные рассуждения DeepSeek$2.6 / $7 $/1M ток
glm-4.5-airбыстрая и дешёвая · RU$0.25 / $1.2 $/1M ток
glm-4.5vзрение GLM · RU$0.3 / $1.5 $/1M ток
glm-5.2Zhipu · баланс цена/качество$1.3 / $5.2 $/1M ток
glm-5.3флагман Zhipu · reasoning$1.8 / $7 $/1M ток
glm-5.3-flashфлагманская flash-модель · reasoning · RU$0.15 / $0.55 $/1M ток
kimi-k2.7-codeкод и агенты Moonshot$1.4 / $6 $/1M ток
qwen3-vl-32bзрение: фото → текст$0.25 / $1 $/1M ток
qwen3.5-122bфлагманский MoE Alibaba$0.6 / $2.4 $/1M ток
qwen3.6-35bуниверсальный чат Alibaba$0.5 / $2.2 $/1M ток
qwen3.8-27bновейшая модель Alibaba · reasoning$0.5 / $2.5 $/1M ток
kimi-k3флагман Moonshot · агенты и длинный текст$5 / $25 $/1M ток
bge-m3эмбеддинги для RAG · ru/en/zh + 100 языков$0.01 $/1M ток
wan22-t2v480p · Wan 2.2 текст→видео · $0.40 за ролик$0.4 $/сек ≈35.2₽
wan22-i2v480p · Wan 2.2 фото→видео · $0.40 за ролик$0.4 $/сек ≈35.2₽

Курс: 1$ ≈ 88₽. Неудачные задачи не тарифицируются.