Add README.md
This commit is contained in:
@@ -0,0 +1,282 @@
|
|||||||
|
# selectel-ml-tui
|
||||||
|
|
||||||
|
TUI-приложение (Python 3.10+) для отображения потребления **ИИ-роутера Selectel**
|
||||||
|
прямо в терминале. Работает на Ubuntu (22.04+/24.04) и macOS (12+).
|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
- Дашборд потребления за месяц (сумма, запросы, input/output/cache токены)
|
||||||
|
- Метрики за 24 часа (доступность, TTFT, задержка) — общие и по моделям
|
||||||
|
- Бюджет роутера (лимит/расход/остаток) и лимиты по API-ключам
|
||||||
|
- История потребления по дням с Unicode-бар-графиком (локальный SQLite-кэш)
|
||||||
|
- Детализация метрик конкретной модели (Enter в таблице моделей)
|
||||||
|
- Офлайн-режим: при недоступности API показывает последние данные из кэша
|
||||||
|
- Автообновление по интервалу из конфигурации (по умолчанию 60 с)
|
||||||
|
- Экспорт истории в CSV/JSON, диагностика окружения (`doctor`)
|
||||||
|
|
||||||
|
## Интерфейс
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ Selectel ML Tokens ──────────────── online · 1 186,73 ₽ ───────┐
|
||||||
|
│ ┌─ Потребление за месяц ─┐ ┌─ Метрики за 24 часа ──────────────┐ │
|
||||||
|
│ │ Сумма: 1 186,73 ₽ │ │ Доступность: 100,0% │ │
|
||||||
|
│ │ Запросы: 1 096 │ │ TTFT: 3 670,0 мс │ │
|
||||||
|
│ │ Токены: 482 749 246 │ │ Запросы: 1 097 │ │
|
||||||
|
│ │ Input: 244 004 716 │ │ Input/Output/Cache: … │ │
|
||||||
|
│ │ Output/Cache: … │ └───────────────────────────────────┘ │
|
||||||
|
│ │ Бюджет: 2 000 ₽ │ │
|
||||||
|
│ └────────────────────────┘ │
|
||||||
|
│ По моделям │
|
||||||
|
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Модель │ Запросы │ Доступность │ TTFT, мс │ Задержка, мс │ │
|
||||||
|
│ │ deepseek-v4-pro │ 1028 │ 100,0% │ 3,69 │ 12,29 │ │
|
||||||
|
│ └──────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ r — обновить h — история k — ключи s — настройки q — выход │
|
||||||
|
└──────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
Экран **История** (**h**): бар-график стоимости по дням + таблица
|
||||||
|
(период 7/30/90 дней — кнопками). Экран **Ключи** (**k**): лимиты и расход по
|
||||||
|
API-ключам. Экран **Настройки** (**s**): интервал обновления, «Очистить кэш»,
|
||||||
|
пути и маскированный токен. **Esc** — назад.
|
||||||
|
|
||||||
|
## Горячие клавиши
|
||||||
|
|
||||||
|
| Клавиша | Действие |
|
||||||
|
|---|---|
|
||||||
|
| `r` | Обновить данные |
|
||||||
|
| `h` | История потребления |
|
||||||
|
| `k` | API-ключи и лимиты |
|
||||||
|
| `s` | Настройки |
|
||||||
|
| `q` | Выход |
|
||||||
|
| `Esc` | Назад (с экрана истории/настроек/модели) |
|
||||||
|
| `Enter` / клик | Детализация метрик модели (в таблице «По моделям») |
|
||||||
|
|
||||||
|
На macOS горячие клавиши — обычные символьные (`r/h/s/q`); Option/Command
|
||||||
|
зарезервированы системой и не используются.
|
||||||
|
|
||||||
|
## Требования
|
||||||
|
|
||||||
|
- Python 3.10+
|
||||||
|
- Ubuntu 22.04+/24.04, macOS 12+
|
||||||
|
- Терминал с поддержкой цвета и UTF-8 (GNOME Terminal, Konsole, tmux,
|
||||||
|
Terminal.app, iTerm2)
|
||||||
|
|
||||||
|
## Источники данных
|
||||||
|
|
||||||
|
- **Billing Statistics API** (`https://api.selectel.ru`, заголовок `X-Token`):
|
||||||
|
стоимость потребления ИИ-роутера (провайдер `aig`) по дням/часам. Параметры
|
||||||
|
`start`/`end` принимаются в полном ISO-формате (`YYYY-MM-DDTHH:MM:SS.000`),
|
||||||
|
короткие даты дополняются клиентом автоматически. Значение `value` в копейках.
|
||||||
|
- **Gateway API ИИ-роутера** (`/aig/gateway/v1/*`, IAM-токен проекта + `X-Project-Id`):
|
||||||
|
токены, метрики, каталог моделей.
|
||||||
|
- **IAM-авторизация**: `POST https://cloud.api.selcloud.ru/identity/v3/auth/tokens`
|
||||||
|
(логин/пароль сервисного пользователя, scope project, TTL 24 ч, кэш с
|
||||||
|
автообновлением за 5 минут до истечения).
|
||||||
|
|
||||||
|
## Получение токенов (панель Selectel)
|
||||||
|
|
||||||
|
- **Статический токен** (billing-метрики): панель `my.selectel.ru` → профиль →
|
||||||
|
**Доступ** → **API-ключи**. Вставьте токен в мастер настройки.
|
||||||
|
- **IAM-токен** (gateway: сумма/токены/модели/ключи): нужен **сервисный
|
||||||
|
пользователь**. Создайте его в `my.selectel.ru` → **IAM** → **Сервисные
|
||||||
|
пользователи** (имя без email, например `ml-monitor`), назначьте роль на
|
||||||
|
нужный ML-проект. Затем в `selectel-ml-tui config` укажите имя сервисного
|
||||||
|
пользователя, его пароль, `project_id` и `domain_id` (номер аккаунта).
|
||||||
|
Без сервисного пользователя доступна только стоимость из billing.
|
||||||
|
|
||||||
|
Подробнее об API: [Selectel ML / управление роутером](https://selectel.ru/services/ml/) —
|
||||||
|
внутренние API панели и документация по биллингу.
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make install # Ubuntu/macOS
|
||||||
|
# или
|
||||||
|
./scripts/install_ubuntu.sh # Ubuntu
|
||||||
|
./scripts/install_macos.sh # macOS
|
||||||
|
# или make install-ubuntu / make install-macos
|
||||||
|
```
|
||||||
|
|
||||||
|
Всё сводится к двум командам на каждой ОС:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu
|
||||||
|
sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
|
||||||
|
pip install --user . # или ./scripts/install_ubuntu.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install python@3.11 # или ./scripts/install_macos.sh
|
||||||
|
pip install --user .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make run
|
||||||
|
# или
|
||||||
|
.venv/bin/selectel-ml-tui run
|
||||||
|
# или (с корректным TERM/LANG, подходит для tmux/ssh)
|
||||||
|
./scripts/run.sh run
|
||||||
|
```
|
||||||
|
|
||||||
|
CLI-точка входа: `selectel-ml-tui` (console_scripts), а также `python -m selectel_ml_tui`.
|
||||||
|
|
||||||
|
При первом запуске без настроенных учётных данных выводится подсказка
|
||||||
|
(`selectel-ml-tui config`); `selectel-ml-tui doctor` предупреждает, что токен
|
||||||
|
не настроен.
|
||||||
|
|
||||||
|
TUI-дашборд:
|
||||||
|
- **Dashboard**: потребление за месяц (сумма, токены), метрики за 24 часа,
|
||||||
|
таблица «По моделям»; статус в заголовке — `online`/`offline`
|
||||||
|
- **r** — обновить, **h** — история, **s** — настройки, **q** — выход
|
||||||
|
- Автообновление по интервалу из конфигурации (по умолчанию 60 с)
|
||||||
|
- При недоступности API показывает последние данные из кэша (офлайн)
|
||||||
|
- **История** (**h**): таблица по дням из кэша + Unicode-бар-график стоимости,
|
||||||
|
выбор периода 7/30/90 дней (кнопки)
|
||||||
|
- **Модель** (Enter/клик в таблице моделей): детализация метрик конкретной модели
|
||||||
|
- **Настройки** (**s**): изменение интервала обновления (сохранение в конфиг),
|
||||||
|
«Очистить кэш», пути к конфигу/БД, маскированный токен
|
||||||
|
- Навигация: **Esc** — назад
|
||||||
|
|
||||||
|
## Конфигурация
|
||||||
|
|
||||||
|
```bash
|
||||||
|
selectel-ml-tui config # интерактивный мастер настройки
|
||||||
|
selectel-ml-tui config --path # показать пути конфигурации
|
||||||
|
selectel-ml-tui config --show # показать текущие настройки (секреты маскируются)
|
||||||
|
```
|
||||||
|
|
||||||
|
Настройки хранятся в `config.toml`, учётные данные (пароль сервисного
|
||||||
|
пользователя, статический токен) — в `credentials.json` в каталоге конфигурации
|
||||||
|
(права 0600). Каталог: Linux — `~/.config/selectel-ml-tui`, macOS —
|
||||||
|
`~/Library/Application Support/selectel-ml-tui`.
|
||||||
|
|
||||||
|
Переменные окружения имеют приоритет над файлом конфигурации:
|
||||||
|
|
||||||
|
- `SELCTEL_API_URL` — базовый URL API (вместо `api_base_url`)
|
||||||
|
- `SELCTEL_TOKEN` — статический токен (вместо `static_token`)
|
||||||
|
- `SELCTEL_SERVICE_USER`, `SELCTEL_PASSWORD` — сервисный пользователь
|
||||||
|
- `SELCTEL_PROJECT_ID`, `SELCTEL_DOMAIN_ID` — проект и аккаунт
|
||||||
|
- остальные поля: `SELCTEL_API_BASE_URL`, `SELCTEL_REFRESH_INTERVAL`, `SELCTEL_ROUTER_ID`, …
|
||||||
|
|
||||||
|
## Локальный кэш и история
|
||||||
|
|
||||||
|
Данные сохраняются в SQLite-базу (`cache.db`) в каталоге данных платформы
|
||||||
|
(Linux: `~/.local/share/selectel-ml-tui`, macOS:
|
||||||
|
`~/Library/Application Support/selectel-ml-tui`) при каждом успешном обновлении:
|
||||||
|
- `consumption_snapshots` — снимки потребления (сумма, токены)
|
||||||
|
- `metrics_snapshots` — снимки общих метрик
|
||||||
|
- `model_metrics` — метрики по моделям
|
||||||
|
- `history` — точки истории по периодам (upsert, без дублей)
|
||||||
|
|
||||||
|
При недоступности API TUI показывает «офлайн» и последние данные из кэша.
|
||||||
|
Старые записи удаляются автоматически (TTL 180 дней).
|
||||||
|
|
||||||
|
Экспорт истории: `selectel-ml-tui export --format json|csv -o <файл>`.
|
||||||
|
|
||||||
|
## Платформы (Ubuntu и macOS)
|
||||||
|
|
||||||
|
Диагностика окружения: `selectel-ml-tui doctor` — проверяет Python (>=3.10),
|
||||||
|
`TERM`, `LANG`, кодировку UTF-8, выводит пути к конфигурации и данным.
|
||||||
|
|
||||||
|
Отличия платформ:
|
||||||
|
|
||||||
|
| | Ubuntu 22.04+/24.04 | macOS 12+ |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | python3.10+ (apt: `python3 python3-venv python3-pip`) | Homebrew `python@3.11`+ |
|
||||||
|
| Каталог конфигурации | `~/.config/selectel-ml-tui` | `~/Library/Application Support/selectel-ml-tui` |
|
||||||
|
| Каталог данных | `~/.local/share/selectel-ml-tui` | `~/Library/Application Support/selectel-ml-tui` |
|
||||||
|
| Права доступа | 0700/0600 (по умолчанию) | то же; доступ на чтение к `Application Support` |
|
||||||
|
| Терминалы | GNOME Terminal, Konsole, tmux | Terminal.app, iTerm2 |
|
||||||
|
| Клавиши | — | hotkeys через Ctrl/символы (r/h/s/q); Option/Command зарезервированы системой |
|
||||||
|
|
||||||
|
Требования к окружению терминала:
|
||||||
|
- `TERM` должен указывать на цветной терминал (`xterm-256color`, `tmux-256color`).
|
||||||
|
В `tmux`/`screen` задаётся автоматически; `scripts/run.sh` подставляет
|
||||||
|
`xterm-256color`, если переменная не задана.
|
||||||
|
- `LANG`/`locale` должны быть UTF-8 (`ru_RU.UTF-8`, `en_US.UTF-8`), иначе
|
||||||
|
возможны сбои отображения русского текста и граничных символов (▌▀█).
|
||||||
|
|
||||||
|
CI: GitHub Actions (`ubuntu-latest` + `macos-latest`, Python 3.11/3.12) — ruff,
|
||||||
|
mypy, pytest+coverage, doctor.
|
||||||
|
|
||||||
|
## Упаковка (однофайловый исполняемый файл)
|
||||||
|
|
||||||
|
Опционально: сборка автономного бинарника через PyInstaller.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build # или ./scripts/build_ubuntu.sh / build_macos.sh
|
||||||
|
./dist/selectel-ml-tui doctor # проверка
|
||||||
|
```
|
||||||
|
|
||||||
|
Артефакт не зависит от установленного Python и venv (собирается на целевой ОС).
|
||||||
|
|
||||||
|
История версий: [CHANGELOG.md](CHANGELOG.md). Финальный чек-лист тестирования:
|
||||||
|
[docs/FINAL_CHECKLIST.md](docs/FINAL_CHECKLIST.md).
|
||||||
|
|
||||||
|
## Разработка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test # pytest + coverage (порог 80%)
|
||||||
|
make lint # ruff (flake8/isort/format)
|
||||||
|
make typecheck # mypy (strict)
|
||||||
|
make format # ruff format
|
||||||
|
```
|
||||||
|
|
||||||
|
- Unit-тесты: config (приоритет env), storage, models (парсинг/форматирование),
|
||||||
|
API-клиент (httpx.MockTransport: успех, 401, 429, 500, timeout, сетевые ошибки)
|
||||||
|
- Интеграционный smoke-тест TUI: headless-запуск приложения через `App.run_test()`
|
||||||
|
- Статический анализ настроен в `pyproject.toml` (`[tool.ruff]`, `[tool.mypy]`,
|
||||||
|
`fail_under = 80`).
|
||||||
|
|
||||||
|
## FAQ и troubleshooting
|
||||||
|
|
||||||
|
**«Учётные данные не настроены» при запуске**
|
||||||
|
Выполните `selectel-ml-tui config` — мастер настройки запросит токен
|
||||||
|
(и опционально сервисного пользователя для метрик моделей). Проверка:
|
||||||
|
`selectel-ml-tui doctor` → `[OK] token`.
|
||||||
|
|
||||||
|
**Ошибки авторизации (401 / 403)**
|
||||||
|
- Статический токен истёк или неверен — получите новый в панели Selectel
|
||||||
|
(профиль → API-токены) и обновите через `selectel-ml-tui config`.
|
||||||
|
- IAM-доступ: сервисный пользователь должен иметь роль *reader* на нужном
|
||||||
|
ML-проекте; проверьте `project_id` и `domain_id` (аккаунт). У IAM-токена
|
||||||
|
TTL 24 ч — приложение обновляет его автоматически (за 5 минут до истечения).
|
||||||
|
|
||||||
|
**В дашборде нет метрик по моделям (Input/Output/Cache отсутствуют)**
|
||||||
|
Gateway-данные (токены по моделям, каталог моделей) требуют IAM-токена
|
||||||
|
сервисного пользователя. Если сервисный пользователь не создан, доступна
|
||||||
|
только стоимость (billing) — на дашборде выводится пояснение
|
||||||
|
«Токены и модели — только через IAM». Создать сервисного пользователя:
|
||||||
|
my.selectel.ru → IAM → Сервисные пользователи (с областью доступа на нужный
|
||||||
|
проект), затем `selectel-ml-tui config`.
|
||||||
|
|
||||||
|
**PermissionError при запуске (`credentials.json` не читается)**
|
||||||
|
Файлы конфигурации должны принадлежать текущему пользователю (права 0600).
|
||||||
|
Если запускать приложение от `root`/`sudo`, файлы создаются с владельцем root,
|
||||||
|
и обычный запуск падает. Исправление (macOS/Linux):
|
||||||
|
`sudo chown -R $USER ~/Library/Application\ Support/selectel-ml-tui`
|
||||||
|
(на Linux путь `~/.config/selectel-ml-tui`). Не запускайте приложение от root.
|
||||||
|
|
||||||
|
**Ошибка 422 при запросе данных**
|
||||||
|
API принимает только полные ISO-таймстампы (`YYYY-MM-DDTHH:MM:SS.000`).
|
||||||
|
Приложение формирует их самостоятельно; если ошибка повторяется — проверьте
|
||||||
|
часовой пояс (`doctor` → `LANG`/`locale`).
|
||||||
|
|
||||||
|
**«Краказябры»/битые символы в терминале**
|
||||||
|
`LANG`/`locale` должны быть UTF-8 (`ru_RU.UTF-8`, `en_US.UTF-8`), `TERM` —
|
||||||
|
цветной (`xterm-256color`). Запуск через `./scripts/run.sh run` подставит
|
||||||
|
значения автоматически (полезно в tmux/ssh).
|
||||||
|
|
||||||
|
**Офлайн-режим**
|
||||||
|
При недоступности API в заголовке появляется `offline`, а дашборд показывает
|
||||||
|
последние снимки из SQLite-кэша. Данные обновятся автоматически при
|
||||||
|
восстановлении сети (клавиша `r` — вручную).
|
||||||
|
|
||||||
|
**«Нет данных для графика» в истории**
|
||||||
|
Кэш пуст — данные появляются после первого успешного обновления (каждая
|
||||||
|
загрузка сохраняет точку за день). Очистить кэш можно в экране «Настройки»
|
||||||
|
или через `export` (не очищает).
|
||||||
Reference in New Issue
Block a user