image_recognition/README.md
2026-05-26 23:43:07 +03:00

145 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Qwen Console App
Консольное приложение на Python с четырьмя функциями:
- 📷 **описание изображений** — указываешь путь к файлу, приложение возвращает текстовое описание через vision-модель Qwen
- 📊 **генерация графиков** — по текстовому запросу LLM пишет код на matplotlib, приложение выполняет его и сохраняет PNG
- 🏛 **архитектурные схемы** — по описанию системы LLM генерирует DOT, Graphviz рендерит это в PNG
- ♻️ **воспроизведение с фото** — указываешь путь к фото графика или схемы, приложение распознаёт тип и отрисовывает заново
## Стек
- [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/)
- 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
```
Переменные окружения:
| Переменная | Обязательна | По умолчанию | Описание |
| --------------------- | ----------- | ----------------------------------------- | ------------------------------------------- |
| `LLM_API_KEY` | ✅ | — | API-ключ провайдера |
| `LLM_BASE_URL` | ❌ | `https://llm.lambda.coredump.ru/v1` | Base URL OpenAI-совместимого API |
| `LLM_MODEL` | ❌ | `qwen3.5-122b` | Имя модели |
| `LLM_DISABLE_THINKING`| ❌ | `false` | Отключить reasoning (для Qwen3/DeepSeek-R1) |
> ⚠️ Для команды `describe` и `repro` модель должна быть **мультимодальной (VL)**. Текстовая модель упадёт при попытке передать ей картинку.
## Запуск
```bash
uv run src/app.py
```
Приложение запускается в интерактивном режиме и ждёт команд.
## Использование
```
>>> <команда> <аргумент>
```
| Команда | Что делает |
| ------------------------- | ------------------------------------------------------------- |
| `describe <путь>` | Описать изображение |
| `plot <описание>` | Сгенерировать matplotlib-график → сохраняется в `plot.png` |
| `arch <описание>` | Нарисовать архитектурную схему → сохраняется в `arch.png` |
| `repro <путь>` | Воспроизвести график/схему с картинки → сохраняется в `repro.png` |
| `help` | Показать справку |
| `exit` / `quit` / Ctrl+C | Выйти из приложения |
Примеры для `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`:
```
>>> repro chart.png
>>> repro /home/user/screenshots/arch_diagram.jpg
```
Результат `repro` — это не попиксельная копия, а реконструкция: приложение старается передать тот же тип графика / те же компоненты и связи, но стиль будет его собственный.
## Структура проекта
```
.
├── app.py # основной скрипт: конфиг, LLM-клиент, консольный цикл
├── 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-вызовы детерминированным кодом
## Возможные улучшения
- история команд (readline / prompt_toolkit)
- автодополнение путей к файлам по Tab
- флаг `--open` для автоматического открытия PNG после генерации
- кэш описаний по хэшу изображения
- вывод сгенерированного кода графика в режиме отладки (`--debug`)
- тесты для `render_plot` с фиксированными промптами