local-llm · v1.0.0 · 2026-06-23 · sha256 90e6fb1909c12be4

local-llm v1.0.0B

Immutable. This exact content is served forever at /api/v1/blob/90e6fb1909c12be4.

---
name: local-llm
description: Локальный LLM-стек на Mac (Apple Silicon, MLX) под приватность и запасной режим. NL-вход к установке/запуску/переключению моделей + слой суждения для мониторинга новых моделей. Тонкая обёртка над скриптами РП404, не замена.
user_invocable: true
version: 1.0.0
layer: L1
status: active
triggers:
  slash: [/local-llm]
  phrases:
    - "поставь локальную модель"
    - "установи локальную модель"
    - "запусти локальную модель"
    - "покажи модели"
    - "какие модели есть"
    - "переключи модель"
    - "переключи на 14B"
    - "какие новые модели вышли"
    - "проверь новые модели"
routing:
  executor: script+judgment
  deterministic: false
  optimization_priority: 2
agents: single
interaction: multi-step
gates_required: []
gates_enforced: []
gates_rationale: "операционный скилл; WP Gate применим только при создании нового РП, не для операционных вызовов"
---

# Локальный LLM-стек (local-llm)

> **Scope:** NL-вход к локальному LLM-стеку (установка / запуск / статус / переключение модели) + слой суждения для оценки находок монитора новых моделей.
> **Not in scope:** механика (установка, состояния, переключение, архив) — она в детерминированных скриптах (различение «Скрипт ≠ Агент»). Скилл их **вызывает**, не дублирует логику. Источник истины статусов моделей — каталог + `model-lifecycle.py`.
> **JOB стека:** приватность (задачи с персональными данными, что нельзя слать в облако) + запасной режим (без сети / кончились токены облака). См. `ADR-001-local-llm-stack.md`.

## Расположение бандла

Управляющие скрипты — самодостаточный бандл (каждый работает из своей директории).
Путь резолвится через env, дефолт — `extensions/local-llm/` внутри IWE-установки:

```bash
BUNDLE="${IWE_LOCAL_LLM_DIR:-$HOME/IWE/extensions/local-llm}"
```

- venv стека: `~/.iwe-local-llm/.venv` (ставит установщик).
- Активная модель + состояние сервера: `~/.iwe-local-llm/` (`active-model`, `server.pid`, `server.log`).

## When to use

- «поставь / установи локальную модель» → установка под железо (Шаг 1).
- «покажи модели» / «какие модели есть» → список по состояниям (Шаг 2).
- «запусти / останови» / «статус» → управление сервером (Шаг 2).
- «переключи модель» / «переключи на 14B» → смена активной модели (Шаг 3).
- «какие новые модели вышли» / «проверь новые модели» → мониторинг + суждение об adopt (Шаг 4).

## Algorithm

### Шаг 1 — установка (механика → скрипт)

```bash
bash "$BUNDLE/install-local-llm.sh"          # рекомендованная модель под железо
bash "$BUNDLE/install-local-llm.sh" --max    # самая тяжёлая влезающая
```

Установщик идемпотентен: детект железа → выбор модели из каталога под память → venv + mlx-lm → скачивание → smoke. Показать пользователю итог (модель, что сервер поднялся).

### Шаг 2 — запуск / статус / список (механика → скрипт)

```bash
bash "$BUNDLE/iwe-local-llm.sh" start    # поднять сервер (OpenAI-совместимый, localhost:8080)
bash "$BUNDLE/iwe-local-llm.sh" status   # активная модель + состояние сервера
bash "$BUNDLE/iwe-local-llm.sh" models   # все модели по четырём состояниям + факт скачивания
bash "$BUNDLE/iwe-local-llm.sh" stop     # остановить сервер
bash "$BUNDLE/iwe-local-llm.sh" test     # проверка совместимого интерфейса (SHIM_OK)
```

Инструменты IWE подключаются к `http://127.0.0.1:8080/v1/chat/completions` тем же клиентом, что и к облаку.

### Шаг 3 — переключение модели (механика → скрипт)

```bash
bash "$BUNDLE/iwe-local-llm.sh" use <model-id>    # скачать + активировать + перезапуск
bash "$BUNDLE/iwe-local-llm.sh" pull <model-id>   # только скачать для тестирования (→ testing)
bash "$BUNDLE/iwe-local-llm.sh" archive <model-id># вывести в архив
```

`use` переводит прежнюю активную в `testing` (остаётся скачанной). Ровно одна активная. Не редактировать `model-catalog.yaml` руками — только через `iwe-local-llm.sh` / `model-lifecycle.py` (сохраняет комментарии, держит инвариант одной active).

### Шаг 4 — мониторинг новых моделей (суждение → LLM-работа)

```bash
python3 "$BUNDLE/model-monitor.py"    # дайджест трендовых моделей, которых нет в каталоге
```

Монитор только **находит** кандидатов. Решение об adopt — суждение агента (это и есть LLM-работа, ради которой скилл существует):

1. Сравнить кандидата с текущей активной по **качеству** (LMArena / бенчмарки, если пользователь даёт ссылку или просит свериться).
2. Проверить **соответствие JOB**: приватность (оффлайн, без телеметрии) + влезает в память Mac (`min_ram_gb` ≤ железо).
3. Дать рекомендацию: добавить в каталог (`model-lifecycle.py add`) + `pull` для сравнения, либо пропустить с причиной.
4. Решение о смене active — за пользователем; скилл предлагает, не переключает молча.

## Anti-patterns

- **Дублировать механику в скилле.** Состояния/переключение/архив — в скриптах. Скилл вызывает, не переписывает (OwnerIntegrity: каталог = источник истины).
- **Молча переключать активную модель** по находке монитора. Adopt — решение пользователя после сравнения качества.
- **Слать содержимое промптов в облако** при выборе локального стека под приватность — стек именно для того, чтобы этого не делать.
- **Править `model-catalog.yaml` руками** — ломает комментарии и инвариант одной active; только через lifecycle-команды.

<!-- USER-SPACE -->
<!-- /USER-SPACE -->