133 lines
8.3 KiB
Markdown
133 lines
8.3 KiB
Markdown
# 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 <https://git.lambda.coredump.ru/BtoB_team/image_recognition.git>
|
||
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` с фиксированными промптами
|