$npx -y skills add TserenTserenov/FMT-exocortex-template --skill local-llmЛокальный LLM-стек на Mac (Apple Silicon, MLX) под приватность и запасной режим. NL-вход к установке/запуску/переключению моделей + слой суждения для мониторинга новых моделей. Тонкая обёртка над скриптами РП404, не замена.
| 1 | # Локальный LLM-стек (local-llm) |
| 2 | |
| 3 | > **Scope:** NL-вход к локальному LLM-стеку (установка / запуск / статус / переключение модели) + слой суждения для оценки находок монитора новых моделей. |
| 4 | > **Not in scope:** механика (установка, состояния, переключение, архив) — она в детерминированных скриптах (различение «Скрипт ≠ Агент»). Скилл их **вызывает**, не дублирует логику. Источник истины статусов моделей — каталог + `model-lifecycle.py`. |
| 5 | > **JOB стека:** приватность (задачи с персональными данными, что нельзя слать в облако) + запасной режим (без сети / кончились токены облака). См. `ADR-001-local-llm-stack.md`. |
| 6 | |
| 7 | ## Расположение бандла |
| 8 | |
| 9 | Управляющие скрипты — самодостаточный бандл (каждый работает из своей директории). |
| 10 | Путь резолвится через env, дефолт — `extensions/local-llm/` внутри IWE-установки: |
| 11 | |
| 12 | ```bash |
| 13 | BUNDLE="${IWE_LOCAL_LLM_DIR:-$HOME/IWE/extensions/local-llm}" |
| 14 | ``` |
| 15 | |
| 16 | - venv стека: `~/.iwe-local-llm/.venv` (ставит установщик). |
| 17 | - Активная модель + состояние сервера: `~/.iwe-local-llm/` (`active-model`, `server.pid`, `server.log`). |
| 18 | |
| 19 | ## When to use |
| 20 | |
| 21 | - «поставь / установи локальную модель» → установка под железо (Шаг 1). |
| 22 | - «покажи модели» / «какие модели есть» → список по состояниям (Шаг 2). |
| 23 | - «запусти / останови» / «статус» → управление сервером (Шаг 2). |
| 24 | - «переключи модель» / «переключи на 14B» → смена активной модели (Шаг 3). |
| 25 | - «какие новые модели вышли» / «проверь новые модели» → мониторинг + суждение об adopt (Шаг 4). |
| 26 | |
| 27 | ## Algorithm |
| 28 | |
| 29 | ### Шаг 1 — установка (механика → скрипт) |
| 30 | |
| 31 | ```bash |
| 32 | bash "$BUNDLE/install-local-llm.sh" # рекомендованная модель под железо |
| 33 | bash "$BUNDLE/install-local-llm.sh" --max # самая тяжёлая влезающая |
| 34 | ``` |
| 35 | |
| 36 | Установщик идемпотентен: детект железа → выбор модели из каталога под память → venv + mlx-lm → скачивание → smoke. Показать пользователю итог (модель, что сервер поднялся). |
| 37 | |
| 38 | ### Шаг 2 — запуск / статус / список (механика → скрипт) |
| 39 | |
| 40 | ```bash |
| 41 | bash "$BUNDLE/iwe-local-llm.sh" start # поднять сервер (OpenAI-совместимый, localhost:8080) |
| 42 | bash "$BUNDLE/iwe-local-llm.sh" status # активная модель + состояние сервера |
| 43 | bash "$BUNDLE/iwe-local-llm.sh" models # все модели по четырём состояниям + факт скачивания |
| 44 | bash "$BUNDLE/iwe-local-llm.sh" stop # остановить сервер |
| 45 | bash "$BUNDLE/iwe-local-llm.sh" test # проверка совместимого интерфейса (SHIM_OK) |
| 46 | ``` |
| 47 | |
| 48 | Инструменты IWE подключаются к `http://127.0.0.1:8080/v1/chat/completions` тем же клиентом, что и к облаку. |
| 49 | |
| 50 | ### Шаг 3 — переключение модели (механика → скрипт) |
| 51 | |
| 52 | ```bash |
| 53 | bash "$BUNDLE/iwe-local-llm.sh" use <model-id> # скачать + активировать + перезапуск |
| 54 | bash "$BUNDLE/iwe-local-llm.sh" pull <model-id> # только скачать для тестирования (→ testing) |
| 55 | bash "$BUNDLE/iwe-local-llm.sh" archive <model-id># вывести в архив |
| 56 | ``` |
| 57 | |
| 58 | `use` переводит прежнюю активную в `testing` (остаётся скачанной). Ровно одна активная. Не редактировать `model-catalog.yaml` руками — только через `iwe-local-llm.sh` / `model-lifecycle.py` (сохраняет комментарии, держит инвариант одной active). |
| 59 | |
| 60 | ### Шаг 4 — мониторинг новых моделей (суждение → LLM-работа) |
| 61 | |
| 62 | ```bash |
| 63 | python3 "$BUNDLE/model-monitor.py" # дайджест трендовых моделей, которых нет в каталоге |
| 64 | ``` |
| 65 | |
| 66 | Монитор только **находит** кандидатов. Решение об adopt — суждение агента (это и есть LLM-работа, ради которой скилл существует): |
| 67 | |
| 68 | 1. Сравнить кандидата с текущей активной по **качеству** (LMArena / бенчмарки, если пользователь даёт ссылку или просит свериться). |
| 69 | 2. Проверить **соответствие JOB**: приватность (оффлайн, без телеметрии) + влезает в память Mac (`min_ram_gb` ≤ железо). |
| 70 | 3. Дать рекомендацию: добавить в каталог (`model-lifecycle.py add`) + `pull` для сравнения, либо пропустить с причиной. |
| 71 | 4. Решение о смене active — за пользователем; скилл предлагает, не переключает молча. |
| 72 | |
| 73 | ## Anti-patterns |
| 74 | |
| 75 | - **Дублировать механику в скилле.** Состояния/переключение/архив — в скриптах. Скилл вызывает, не переписывает (OwnerIntegrity: каталог = источник истины). |
| 76 | - **Молча переключать активную модель** по находке монитора. Adopt — решение пользователя после сравнения качества. |
| 77 | - **Слать содержимое промптов в облако** при |