Задать вопрос
@Levovich

Как сделать генерацию изображений для тг-бота?

Я создал тг-бота, задействующего функционал моделей от ollama, а так же hugging face. И не могу добавить ему адекватную возможность генерации изображений по запросам. Сейчас он может отвечать на вопросы, генерировать код и считывать информацию с изображений. Я пытался сам, но бот выдает ошибку: ⚠️ HuggingFace не смог сгенерировать изображение.

Причина:
Not Found
объясните все как можно проще т.к. я в программировании почти не смыслю. так же у меня ограничение по срокам, примерно неделя.
# ================= UTF-8 FIX FOR WINDOWS =================
import os
import sys
os.environ["PYTHONUTF8"] = "1"
sys.stdout.reconfigure(encoding="utf-8")
# ========================================================

import re
import base64
import requests
from telegram import Update
from telegram.ext import (
    ApplicationBuilder,
    CommandHandler,
    MessageHandler,
    ContextTypes,
    filters,
)

# ================= НАСТРОЙКИ =================

TELEGRAM_BOT_TOKEN = "7076531027:AAEhLmNxcG4rVmJNSf8otuk9JoqwwYZP0Ps"
HF_TOKEN = "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"

OLLAMA_CHAT_URL = "http://localhost:11434/api/chat"
OLLAMA_GENERATE_URL = "http://localhost:11434/api/generate"
HF_IMAGE_MODEL_URL = (
    "https://router.huggingface.co/hf-inference/models/"
    "stabilityai/sdxl-turbo"
)

HF_HEADERS = {
    "Authorization": f"Bearer {HF_TOKEN}"
}

TEXT_MODEL = "qwen2.5-coder:7b"
VISION_MODEL = "llava:latest"

# ========================================================


def split_text_safe(text: str, max_len: int = 4000):
    if "```" in text:
        return [text]

    parts, current = [], ""
    for line in text.split("\n"):
        if len(current) + len(line) > max_len:
            parts.append(current)
            current = line
        else:
            current += ("\n" if current else "") + line
    if current:
        parts.append(current)
    return parts


def is_code_request(text: str) -> bool:
    keywords = [
        "код", "напиши", "пример", "скрипт",
        "python", "js", "javascript", "c++",
        "функция", "класс", "бот", "api"
    ]
    return any(k in text.lower() for k in keywords)


def ask_text_ai(prompt: str, is_code: bool = False) -> str:
    system_prompt = (
        "Ты русскоязычный ИИ-ассистент.\n"
        "Отвечай СТРОГО на русском языке.\n"
    )

    if is_code:
        system_prompt += (
            "Ты опытный программист.\n"
            "Пиши ТОЛЬКО рабочий код.\n"
            "НЕ выдумывай несуществующие библиотеки и API.\n"
            "Если информации недостаточно — задай уточняющий вопрос.\n"
            "Перед кодом КРАТКО опиши логику.\n"
            "Код оформляй ТОЛЬКО в ```.\n"
        )
    else:
        system_prompt += (
            "Отвечай кратко и по делу.\n"
            "Не используй код, если его не просят.\n"
        )

    payload = {
        "model": TEXT_MODEL,
        "stream": False,
        "messages": [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": prompt}
        ]
    }

    r = requests.post(OLLAMA_CHAT_URL, json=payload, timeout=120)
    return r.json()["message"]["content"]

def generate_image(prompt: str) -> tuple[bytes | None, str | None]:
    payload = {
        "inputs": prompt,
        "options": {
            "wait_for_model": True
        }
    }

    try:
        r = requests.post(
            HF_IMAGE_MODEL_URL,
            headers=HF_HEADERS,
            json=payload,
            timeout=300
        )

        content_type = r.headers.get("content-type", "")

        # ✅ УСПЕХ — ПРИШЛА КАРТИНКА
        if r.status_code == 200 and "image" in content_type:
            return r.content, None

        # ⚠️ HF вернул JSON (ошибка / статус)
        try:
            data = r.json()
            error = data.get("error", str(data))
        except Exception:
            error = r.text

        return None, error

    except Exception as e:
        return None, str(e)


async def handle_image_generation(update: Update, context: ContextTypes.DEFAULT_TYPE):
    chat_id = update.effective_chat.id

    prompt = " ".join(context.args)
    if not prompt:
        await update.message.reply_text(
            "❌ Использование:\n/img описание изображения"
        )
        return

    await context.bot.send_chat_action(chat_id, "upload_photo")

    image_bytes, error = generate_image(prompt)

    if not image_bytes:
        await update.message.reply_text(
            "⚠️ HuggingFace не смог сгенерировать изображение.\n\n"
            f"Причина:\n{error}"
        )
        return

    await context.bot.send_photo(
        chat_id,
        photo=image_bytes,
        caption=f" Запрос:\n{prompt}"
    )


def ask_vision_ai(prompt: str, image_bytes: bytes) -> str:
    image_base64 = base64.b64encode(image_bytes).decode("utf-8")

    payload = {
        "model": VISION_MODEL,
        "prompt": (
            "Опиши изображение.\n"
            "Если есть текст — перепиши его.\n\n"
            f"{prompt}"
        ),
        "images": [image_base64],
        "stream": False
    }

    r = requests.post(OLLAMA_GENERATE_URL, json=payload, timeout=180)
    data = r.json()

    if "response" not in data:
        return f"⚠️ Неожиданный ответ Ollama:\n{data}"

    return data["response"]


def normalize_russian(text: str) -> str:
    payload = {
        "model": TEXT_MODEL,
        "stream": False,
        "messages": [
            {
                "role": "system",
                "content": (
                    "Ты редактор русского текста.\n"
                    "Исправь стиль, грамматику и логику.\n"
                    "Убери английские слова.\n"
                    "Отвечай только на русском."
                )
            },
            {
                "role": "user",
                "content": text
            }
        ]
    }

    try:
        r = requests.post(OLLAMA_CHAT_URL, json=payload, timeout=60)
        return r.json()["message"]["content"]
    except Exception:
        return text


# ================= HANDLERS =================

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(
        " Lion.AI запущен, я умею:\n\n"
        "• Отвечать на вопросы\n"
        "• Писать код\n"
        "• Считывать информацию с изображений\n"
        "• Генерировать картинки с помощью команды /img"
    )


async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    chat_id = update.effective_chat.id
    await context.bot.send_chat_action(chat_id, "typing")

    user_text = update.message.text
    code_request = is_code_request(user_text)

    answer = ask_text_ai(user_text, is_code=code_request)

    for part in split_text_safe(answer):
        await context.bot.send_message(
            chat_id,
            part,
            parse_mode="Markdown"
        )


async def handle_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    chat_id = update.effective_chat.id
    await context.bot.send_chat_action(chat_id, "typing")

    photo = update.message.photo[-1]
    file = await context.bot.get_file(photo.file_id)
    image_bytes = await file.download_as_bytearray()

    caption = update.message.caption or "Опиши изображение"

    answer = ask_vision_ai(caption, image_bytes)
    answer = normalize_russian(answer)

    for part in split_text_safe(answer):
        await context.bot.send_message(
            chat_id,
            part,
            parse_mode="Markdown"
        )


# ================= MAIN =================

def main():
    app = ApplicationBuilder().token(TELEGRAM_BOT_TOKEN).build()

    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("img", handle_image_generation))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_text))
    app.add_handler(MessageHandler(filters.PHOTO, handle_photo))


    print("✅ Бот запущен")
    app.run_polling()


if __name__ == "__main__":
    main()
  • Вопрос задан
  • 74 просмотра
Подписаться 1 Простой 1 комментарий
Помогут разобраться в теме Все курсы
  • Нетология
    Python-разработчик: расширенный курс + нейросети
    12 месяцев
    Далее
  • Академия Eduson
    Python-разработчик
    9 месяцев
    Далее
  • Skillbox
    Python-разработчик
    10 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
@Everything_is_bad
я в программировании почти не смыслю.
следующий

TELEGRAM_BOT_TOKEN = "7076531027:AAEhLmNxcG4rVmJNSf8otuk9JoqwwYZP0Ps"
HF_TOKEN = "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"
если это реальные токены, то быстро беги их менять
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы