# CLI и конфигурация Имя команды: `gpu-rent`. Лаунчеры: `gpu-rent.bat` / `.\gpu-rent.ps1` / `./gpu-rent.sh` (создают `.venv` и вызывают `python -m gpu_rent`). Без аргументов CLI показывает **help**. Поднять GPU с двойного клика: в `gpu-rent.vars` → `GPU_RENT_DEFAULT_ARGS=up --yes`. --- ## Типичные сценарии ### Первый раз ```text gpu-rent doctor gpu-rent up --yes # … работа … gpu-rent stop ``` Подготовка ключей: [setup.md](setup.md). ### Обычная сессия ```text gpu-rent up --yes # Ctrl+C / Ctrl+D → stop GPU (диски остаются) gpu-rent tunnel --open gpu-rent hold gpu-rent stop ``` ### Только облако (туннель позже) ```text gpu-rent up --yes --no-tunnel gpu-rent tunnel --open ``` ### LLM рядом со SwarmUI ```text gpu-rent setup # или gpu-rent up --yes --ollama ``` Подробности: [llm.md](llm.md). --- ## Команды | Команда | Поведение | | --- | --- | | `gpu-rent version` | Версия пакета (`0.2.0`) | | `gpu-rent setup` | Wizard: манифесты (в т.ч. ollama-models), `LLM_RUNTIME` (нумерованное меню), пресет, опционально local-watchdog | | `gpu-rent doctor` | Preflight **без** create. Exit ≠ 0 → сессию начинать нельзя | | `gpu-rent flavors` | Скан `SCAN_POOLS` по сегментам a/b/c × `FLAVOR_PREFERENCE` × `FLAVOR_SIZE_PRESET`, список в текущем регионе | | `gpu-rent dry-run` | План без mutating-вызовов | | `gpu-rent up` | Без `--yes`: меню LLM (если runtime none) → пресет → **Selectel**: flavor # / data GB / preemptible → confirm → create → туннель. Цветной лог (ошибки/warn/ok) | | `gpu-rent up --yes` | Без вопросов; flavor из `FLAVOR_PREFERENCE` / `DEFAULT_FLAVOR_ID` | | `up --keep-on-fail` | Не гасить GPU при ошибке install (по умолчанию `UP_STOP_ON_FAIL=true` → `stop`) | | `gpu-rent up -v` / `--verbose` | Полная таблица doctor на `up` (по умолчанию кратко) | | `gpu-rent up --ollama` / `--llm ollama` | Ollama рядом со SwarmUI | | `gpu-rent up --no-swarm` / `--llm-only` | Только Ollama (нужен `--ollama` / `LLM_RUNTIME=ollama`); без clone SwarmUI | | `gpu-rent up --no-update` | Без `git pull` SwarmUI/extensions (только недостающие clone) | | `gpu-rent up --update` | Форс `git pull` SwarmUI + extensions (перекрывает `UPDATE_GIT=false`) | | `gpu-rent up --no-tunnel` | Только облако | | `gpu-rent up --no-spot` | Не preemptible | | `gpu-rent up --flavor ID --yes` | Явный flavor; без `--flavor` + `--yes` — первый доступный из `FLAVOR_PREFERENCE` | | `gpu-rent tunnel` / `tunnel --open` | Повторный проброс; `--open` сразу браузер. **Ctrl+C / Ctrl+D** вызывают `stop` | | `gpu-rent open` / `open --llm` | Браузер на SwarmUI / LLM-порт (туннель уже должен слушать) | | `gpu-rent status` | State, Nova, диск, killer/hold, LLM, local-watchdog | | `gpu-rent diag` | SwarmUI/Comfy diagnostics с VM (API + journal + paths) | | `gpu-rent debug` | Локальный read-only Debug API (`:17821`) — для агента после `--no-tunnel` / без активного `up` | | `gpu-rent hold` / `--minutes N` / `--until ISO` / `--clear` | Пауза idle-killer (нужны живая VM + SSH) | | `gpu-rent stop` / `stop --no-pull` | Удалить compute (+ FIP), диски оставить; optional pull Output | | `gpu-rent destroy --i-understand-data-loss` | `stop` + диски | | `gpu-rent logs` / `logs -u UNIT` | journalctl на VM; `-u swarm\|ollama\|killer\|cloud-init` (алиас `ollama` → юнит `gpu-rent-ollama`) | | `gpu-rent ssh` | Оболочка на VM | | `gpu-rent seed-models` | Докачать новые строки Civitai-манифеста на живой диск | | `gpu-rent seed-extensions` | Доклонировать/обновить git-репы; restart swarmui | | `gpu-rent seed-personas` | Пуш `assistent-extensions/` → `Assistent/extensions/` (+ `_base`); также `search.jsonl` → FTS, если есть | | `gpu-rent push` / `push-models` | Локальные деревья → VM | | `gpu-rent pull-output` | VM `Output/` → `./Output` | | `gpu-rent capture` / `capture all` | Инвентарь VM → merge **ссылок** в `models.yaml` + `extensions.yaml` (веса не качать) | | `gpu-rent capture models` / `--kind lora` | Только модели (фильтр по типу) | | `gpu-rent capture wanted` | Очередь Assistent Cards → `models.yaml` | | `gpu-rent capture extensions` | Только git Extensions / DLNodes | | `gpu-rent capture --dry-run` | Отчёт без записи файлов | | `gpu-rent resize-data --gb 400` | Data volume **только вверх** | | `gpu-rent watchdog install` / `uninstall` / `status` / `tick` | Локальный safety-net (см. ниже) | Второй `up` при живой VM: не создаёт второй GPU; autocomplete-check + push локальных папок; при `PULL_OUTPUT` — подтянуть Output. `--adopt` — подхватить тег без state. Нет команды `generate`. Локальный SwarmUI целиком не зеркалируем — только папки приложения ([local-folders.md](local-folders.md)). ### Отдельный CLI: `civitai-dataset` (не Typer) Лаунчеры `civitai-dataset.bat` / `.ps1` / `.sh` → `python -m gpu_rent.civitai_dataset`. По умолчанию `all`. Подробности и пути: [datasets/README.md](../datasets/README.md). | Команда | Поведение | | --- | --- | | `discover` | Топ Krea2 checkpoints/LoRAs → `catalog/models.json` | | `scrape` | Галереи (метаданные, **без** картинок); `--target`, `--per-version`, `--min-score` | | `split` | `by_kind/` / `by_rating/` / `train.jsonl` / `search.jsonl` | | `all` | discover + scrape + split | Нужен `CIVITAI_API_TOKEN` (лучше `CIVITAI_API_HOST=civitai.red`). На `up` / `seed-personas` файл `datasets/civitai/search.jsonl` пушится на VM как `Assistent/civitai-examples.jsonl` (если есть). --- ## `doctor` Не создаёт сервер и не тратит GPU. Нужен до первого `up` и когда «вчера работало». Проверки (все печатаются в отчёт): 1. Читается `.env`, обязательные `OS_*` 2. Keystone выдаёт токен 3. Квота GPU > 0 (иначе текст про поддержку Selectel) 4. В сегменте есть flavor из `FLAVOR_PREFERENCE` / `DEFAULT_FLAVOR_ID` 5. Volume type / место под data ~100 GB 6. SSH-ключ есть или будет создан в `.gpu-rent/` 7. Живой сервер с тегом `gpu-rent` (info) и boot snapshot `gpu-rent-boot-ok` (info) 8. Если есть `CIVITAI_API_TOKEN` — доступ к API-хосту; манифест парсится 9. `extensions.yaml` парсится, если есть; при `LLM_RUNTIME=ollama` — `ollama-models.yaml` + строка Assistent ext 10. Предупреждения по огромным локальным `Models/` Exit 0 → можно `up`. Exit 1 → причина в таблице / кратком списке на `up`. --- ## `status` и `hold` **status** — без туннеля. При SSH: ещё `df` диска и состояние killer; иначе только OpenStack + локальный state. **hold** пишет на VM `/mnt/swarm_data/.gpu-rent-hold-until`. Killer не удаляет compute, пока `now < ts`. Без живой VM — ошибка (не «запомню на потом»). После unshelve hold на диске сохраняется. --- ## Debug API (localhost) На `gpu-rent up` и `gpu-rent tunnel` CLI поднимает **read-only** HTTP sidecar на `127.0.0.1:17821` (`DEBUG_LOCAL_PORT`). Ссылка печатается сразу и на access card. Агент: `GET /openapi.json` → `GET /snapshot` → точечные пути (`/progress`, `/events?since=`, `/checks`, `/logs`, `/diag`, `/gpu`, `/swarm`, `/ollama`, `/assistent`). Пока SSH нет — VM-эндпоинты отвечают `ssh_unavailable`; прогресс установщика всё равно виден в `/progress` и `/events`. ### Assistent (глубокая отладка) | Путь | Зачем | | --- | --- | | `/assistent` | Сводка: extension + overlay + roles + memory + live API + hints + playbook | | `/assistent/diagnose` | То же + journal по умолчанию + session store meta | | `/assistent/extension` | DLL, Sqlite deps, Tab/Assets, git HEAD | | `/assistent/overlay` | personas/packs на VM vs локальный `assistent-extensions/` | | `/assistent/roles` | `ollama-roles.json` ↔ `/api/tags` (`default_chat`) | | `/assistent/memory` | `assistent.sqlite` + counts | | `/assistent/api` | `AssistentListPersonas/Models/Memory/Chats` через туннель (или SSH) | | `/assistent/api?chat_smoke=1` | + 1-token Ollama `/api/chat` (кратко грузит модель) | | `/assistent/wanted` | **GET** — очередь wanted-моделей на data volume | | `/assistent/logs` | journalctl swarmui: build/load/Sqlite | | `/assistent?logs=1` | Сводка + journal | | `/assistent/session` | **POST** — multi-turn debug chat (in-memory, TTL ~45m) | | `/assistent/session/{id}/chat` | **POST** — ход + объект `trace` | | `/assistent/session/{id}` | **GET** / **DELETE** — состояние / сброс | | `/assistent/chat-eval` | One-shot: session + один chat + delete | Симптомы → куда смотреть: поле `playbook` в `/assistent`. **Session / chat-eval** не входят в `/snapshot`. Могут грузить VRAM, писать sqlite chat, тратить биллинг GPU. `compactContext` / Exact merge в Assistent HTTP API **нет** — sidecar реконструирует best-effort (`trace.gaps`). #### Agent playbook (curl) ```bash BASE=http://127.0.0.1:17821 # Static+live health (no chat) curl -sS "$BASE/assistent/diagnose" | jq '{ok,hints,playbook,session_store}' # Multi-turn conversational diagnostics SID=$(curl -sS -X POST "$BASE/assistent/session" \ -H 'Content-Type: application/json' \ -d '{"persona":"neutral","pack":"ordinary","context":{"krea_profile":"turbo","checkpoint":"krea-turbo"}}' \ | jq -r .debug_session_id) curl -sS -X POST "$BASE/assistent/session/$SID/chat" \ -H 'Content-Type: application/json' \ -d '{"message":"какой checkpoint и какие steps/cfg должны быть"}' \ | jq '{ok,reply,trace:{timings_ms,patch,exact_merge,compact_context,system_layers,gaps}}' curl -sS -X POST "$BASE/assistent/session/$SID/chat" \ -H 'Content-Type: application/json' \ -d '{"message":"сделай generate с этими params"}' \ | jq '{ok, trace:{patch,exact_merge}}' curl -sS "$BASE/assistent/session/$SID" | jq .session curl -sS -X DELETE "$BASE/assistent/session/$SID" # One-shot convenience (session + one chat + delete) curl -sS -X POST "$BASE/assistent/chat-eval" \ -H 'Content-Type: application/json' \ -d '{"message":"какие steps/cfg для turbo?","persona":"neutral","timeout":120}' \ | jq '{ok,reply,patch,trace}' ``` Ответ chat: `ok`, `reply`, `trace` (`timings_ms`, `patch`, `exact_merge`, `compact_context`, `system_chars` / `system_layers`, `skills`, `hops`, `gaps`, `errors`/`warnings`/`hints`). Sqlite SaveChat fail — soft error, если текст ответа есть. После `up --no-tunnel` процесс завершается и sidecar гаснет — держи отдельно: ```text gpu-rent debug ``` Мутаций конфига/GPU нет (restart/hold/stop — как раньше через CLI). `chat_smoke` только пингует Ollama; session/chat-eval — полноценный AssistentChat (opt-in). --- ## Local watchdog (опционально) Основной авто-stop — **idle-killer на VM** (ноут можно закрыть). Local watchdog — если хочешь гасить GPU при «убили окно / ребут» без `stop`. 1. `gpu-rent watchdog install` (раз на машине, из корня репо) 2. Пока крутится `up`/`tunnel`, пишется heartbeat `.gpu-rent/local-lease.json` 3. **Ctrl+C / Ctrl+D** → `stop` (как `gpu-rent stop`) 4. Процесс умер / ребут → через `LOCAL_WATCHDOG_GRACE_MINUTES` (дефолт 10) → `stop` 5. `gpu-rent stop` чистит lease сам Без `install` поведение прежнее. При `up --no-tunnel` lease не вооружается. --- ## Конфигурация | Файл | Назначение | | --- | --- | | `.env` | Секреты и OpenStack (`OS_*`, токены). Не в git | | `gpu-rent.vars` | Несекретные дефолты; читают лаунчеры и CLI. Пример: `gpu-rent.vars.example` | | `models.yaml` / `extensions.yaml` / `ollama-models.yaml` | Манифесты (gitignore; из `*.example.yaml`) | ### Лаунчер (`gpu-rent.vars`) ```env # Двойной клик / запуск без аргументов у .ps1/.bat/.sh: GPU_RENT_DEFAULT_ARGS=up --yes # Дописать ко всем вызовам: # GPU_RENT_EXTRA_ARGS=--no-update UPDATE_GIT=true LLM_RUNTIME=none # DATA_VOLUME_SIZE_GB=100 # DEFAULT_FLAVOR_ID= # DEFAULT_SPOT=true ``` ### Основные переменные (`.env` / vars) ```env OS_AUTH_URL=https://cloud.api.selcloud.ru/identity/v3 OS_USER_DOMAIN_NAME= OS_USERNAME= OS_PASSWORD= OS_PROJECT_ID= OS_REGION_NAME=ru-7 GPU_RENT_AZ=ru-7a SSH_PRIVATE_KEY_PATH= SSH_USER=ubuntu # Пусто = авто /32 твоего IP. Для spike/WARP иногда 0.0.0.0/0: GPU_RENT_SSH_CIDR= BOOT_VOLUME_ID= DATA_VOLUME_ID= DATA_VOLUME_SIZE_GB=100 BOOT_SNAPSHOT_NAME=gpu-rent-boot-ok CIVITAI_API_TOKEN= CIVITAI_API_HOST=civitai.red # HF для download/capture (любой из двух): # HF_TOKEN= # HUGGING_FACE_HUB_TOKEN= MODELS_MANIFEST= LOCAL_MODELS_DIR= LOCAL_WILDCARDS_DIR= LOCAL_WORKFLOWS_DIR= LOCAL_OUTPUT_DIR= EXTENSIONS_MANIFEST= GIT_TOKEN= AUTOCOMPLETE_ENABLED=true SWARMUI_LOCAL_PORT=17801 LLM_RUNTIME=none OLLAMA_LOCAL_PORT=17811 DEBUG_LOCAL_PORT=17821 # ENABLE_SWARMUI=false / WORKLOAD=llm — только LLM (см. llm.md) UPDATE_GIT=true DEFAULT_FLAVOR_ID= FLAVOR_PREFERENCE=4090-24,4090-48,a5000,a100-40 FLAVOR_FALLBACK=true FLAVOR_SIZE_PRESET=cheap SCAN_POOLS=ru-6,ru-7 DEFAULT_SPOT=true KEEP_FLOATING_IP=false IDLE_MINUTES=30 IDLE_GRACE_MINUTES=45 # LOCAL_WATCHDOG_GRACE_MINUTES=10 PULL_OUTPUT=false NOTIFY_READY=true # Баланс ₽ (X-Token панели, не OS_*). Нужен watchdog install: # SELECTEL_API_TOKEN= # BALANCE_NOTIFY_STEP_RUB=200 # BALANCE_NOTIFY_LOW_RUB= ``` Flavor uuid в git не хардкодить. `FLAVOR_FALLBACK=false` — только `DEFAULT_FLAVOR_ID` / `--flavor`. Application credential для idle-killer CLI создаёт на `up` (узко: DELETE/GET **этого** server) и отзывает на `stop`. В `.env` ноутбука дублировать не нужно. Пути локальных папок по умолчанию: `Models/`, `Wildcards/`, `CustomWorkflows/`, `Output/` в корне репо. Полный шаблон: [`env.example`](../env.example). --- ## State `/.gpu-rent/state.json` — ids, фаза, timestamps (окно preempt 24 ч). Без паролей. Lockfile рядом — два `up` не создадут два сервера. --- ## Ожидание готовности Ориентир: **~20–40 мин** первый bootstrap, **~5–10 мин** unshelve. Порядок готовности: 1. Nova `ACTIVE` 2. TCP 22 / SSH 3. First-install Comfy (InstallConfirmWS, если backend был empty) → backend **ready (`running`)** → toast (если `NOTIFY_READY`) 4. На VM: HTTP сервисов стека (SwarmUI `:7801` / Ollama `:11434`) — `verify_stack_on_vm` 5. На VM: **nvidia-smi / CUDA** (fail-fast) + **torch+cuda** в Comfy venv при SwarmUI (ждём) — `verify_gpu_env` 6. В логе: строка **`тайминг up:`** (SSH / bootstrap / Idle / verify / …) 7. Туннель + проверка **localhost** тех же сервисов → access-card (красная рамка, если killer failed) → **дайджест journal** поднятых юнитов (~20 строк, без cloud-init) `gpu-rent logs --unit swarm|ollama|killer` — полный journalctl (и cloud-init при `--unit all` / по умолчанию). `gpu-rent status` — killer/hold, последний стек/GPU-env, тайминг up. Локальный порт UI: **17801** (на VM по-прежнему 7801 на loopback). --- ## Windows / notify `NOTIFY_READY`: toast + системный звук, когда backend ready (`running`). Если toast недоступен — только звук и лог, без падения CLI. ### Баланс Selectel (шаг 200 ₽) Нужны: 1. `SELECTEL_API_TOKEN` в `.env` — **статический ключ панели** (`X-Token`), не OpenStack password ([баланс API](https://docs.selectel.ru/api/balance/)). 2. `gpu-rent watchdog install` — тот же локальный тикер, что и аварийный stop. На `up` запоминается baseline баланса. Каждый tick watchdog: если с `up` ушло ещё ~200 ₽ (`BALANCE_NOTIFY_STEP_RUB`) — toast «Списано ~N ₽…». Пополнение сбрасывает baseline. Опционально `BALANCE_NOTIFY_LOW_RUB=300` — разовое «баланс низкий».