# Qwen Telegram Bot Telegram-бот на Python с четырьмя функциями: - 📷 **описание изображений** — присылаешь фото, бот возвращает текстовое описание через vision-модель Qwen - 📊 **генерация графиков** — по текстовому запросу бот просит LLM написать код на matplotlib, выполняет его и отправляет PNG - 🏛 **архитектурные схемы** — по описанию системы LLM генерирует DOT, Graphviz рендерит это в PNG - ♻️ **воспроизведение с фото** — кидаешь фото графика или архитектурной схемы, бот распознаёт тип, извлекает структуру и отрисовывает заново в своём стиле ## Стек - [python-telegram-bot](https://docs.python-telegram-bot.org/) — асинхронный клиент Telegram Bot API - [openai](https://github.com/openai/openai-python) SDK — работа с любым OpenAI-совместимым провайдером (OpenRouter, DashScope, vLLM и др.) - [matplotlib](https://matplotlib.org/) + numpy — рендеринг графиков - [Graphviz](https://graphviz.org/) + [python-graphviz](https://github.com/xflr6/graphviz) — рендеринг архитектурных схем из DOT - [uv](https://docs.astral.sh/uv/) — менеджер пакетов и виртуальных окружений ## Требования - Python **3.11+** - установленный `uv` ([инструкция](https://docs.astral.sh/uv/getting-started/installation/)) - **бинарь Graphviz** в `$PATH` (нужен для команды `/arch`): - Linux: `sudo apt install graphviz` - macOS: `brew install graphviz` - Windows: [скачать с graphviz.org](https://graphviz.org/download/) - токен Telegram-бота от [@BotFather](https://t.me/BotFather) - API-ключ провайдера, поддерживающего мультимодальную модель Qwen ## Установка ```bash git clone cd image_recognition # создаёт .venv и ставит зависимости из pyproject.toml + uv.lock uv sync ``` ## Конфигурация Скопируй шаблон и впиши свои ключи: ```bash cp .env.example .env ``` > ⚠️ Для функции описания изображений модель должна быть **мультимодальной (VL)**. Текстовая модель упадёт при попытке передать ей картинку. ## Запуск ```bash uv run bot.py ``` Бот запускается в режиме long-polling и пишет лог в stdout. ## Использование | Действие | Что делает бот | | ------------------------------------ | ----------------------------------------------------------- | | `/start` или `/help` | Показать справку | | Отправить фото (без подписи-команды) | Вернуть описание изображения | | `/plot <описание>` | Сгенерировать и прислать matplotlib-график | | `/arch <описание>` | Нарисовать архитектурную схему через Graphviz | | `/repro` + фото | Распознать график/схему и отрисовать её заново | Примеры запросов к `/plot`: ``` /plot sin(x) и cos(x) на отрезке [0, 2π] /plot затухающая синусоида на [0, 10] /plot столбчатая диаграмма продаж по месяцам с рандомными значениями /plot гистограмма нормального распределения, 1000 сэмплов ``` Примеры запросов к `/arch`: ``` /arch React-фронт, FastAPI-бэкенд, Postgres и Redis за nginx /arch микросервисы: auth, orders, payments. Общаются через RabbitMQ, у каждого своя БД Postgres, Prometheus собирает метрики /arch телеграм-бот, принимает вебхуки, складывает задачи в очередь Celery с Redis-брокером, воркеры пишут результаты в S3 ``` ### Как пользоваться `/repro` Два варианта: 1. **Прикрепить фото с подписью** `/repro` — бот сразу обработает его. 2. **Ответить** `/repro` на сообщение с фото (reply-to-message). Бот классифицирует изображение как график (`plot`) либо архитектурную схему (`architecture`), извлекает структуру через vision-модель, генерирует для неё matplotlib-код или DOT и отрисовывает заново. Это не попиксельная копия — это реконструкция: бот старается передать тот же тип графика/те же компоненты и связи, но стиль будет его собственный. ## Структура проекта ``` . ├── bot.py # основной скрипт: конфиг, LLM-клиент, хэндлеры Telegram ├── pyproject.toml # зависимости и метаданные проекта для uv ├── uv.lock # фиксация версий (создаётся после uv sync) ├── .env.example # шаблон переменных окружения └── .env # реальные ключи (в git не коммитить!) ``` ## Работа с зависимостями ```bash uv add <пакет> # добавить зависимость uv remove <пакет> # убрать зависимость uv sync # синхронизировать .venv с lock-файлом uv run <команда> # выполнить команду в окружении проекта ``` ## ⚠️ Безопасность Код для построения графиков **генерируется LLM и исполняется через `exec`** в урезанном неймспейсе (без `import`, без `open`, с ограниченным набором builtins). Этого достаточно для локального использования и dev-стенда, но **это не песочница**. Архитектурные схемы безопаснее: Graphviz парсит DOT как данные, а не исполняет его как код, поэтому инъекция через промпт там в худшем случае даст кривую или огромную картинку. Для публичного бота стоит изолировать исполнение `/plot`, например: - отдельный воркер-процесс с `resource.setrlimit` (CPU, память, время) - Docker-контейнер без сети и с read-only FS - [nsjail](https://github.com/google/nsjail) / [firejail](https://firejail.wordpress.com/) - вместо `exec` — разобрать запрос в ограниченный DSL, а уже его превратить в matplotlib-вызовы детерминированным кодом ## Возможные улучшения - webhook вместо polling для продакшена - очередь задач (arq / Celery) для тяжёлого рендеринга - кэш описаний по хэшу изображения - вывод сгенерированного кода графика в подписи к картинке (дебаг-режим) - rate-limiting на пользователя - тесты для `render_plot` с фиксированными промптами