docs(task): A25 — разведка выполнена, задание построено на фактах с сервера
Владелец дал доступ по ключу. На 192.168.1.81 работают два сервера llama.cpp, оба OpenAI-совместимые, проверено запросами: 8081 Qwen3.8-27B-Q4_K_M reasoning on, контекст 65536, -ngl 99 8082 Qwen3-4B-Instruct reasoning off, «compressor» GET /v1/models и POST /v1/chat/completions отвечают 200 на обоих. Видеокарта Tesla V100-32GB, занято 28.7 из 32.7 ГБ. Три следствия внесены в задание как определяющие реализацию: - оба слушают только 127.0.0.1, снаружи недоступны; варианты решения предложены владельцу, выбор за ним; - у обоих --parallel 1, то есть один запрос за раз: лизы Hub обязаны ограничивать локального провайдера, иначе роли заблокируют друг друга; - памяти видеокарты на третью модель нет, слотов ровно два. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
992d0c574c
commit
bad24ff6aa
1 changed files with 36 additions and 13 deletions
|
|
@ -43,24 +43,45 @@ git push -u origin antigravity/local-llm-provider
|
|||
- **`deepseek_adapter.py`** — готовый образец OpenAI-совместимого адаптера: берёт `profile.custom_base_url`, зовёт `{base_url}/chat/completions`. Локальные серверы (Ollama, vLLM, LM Studio, llama.cpp) выставляют тот же интерфейс;
|
||||
- у владельца в Hermes уже настроен профиль `deepseek` через `provider: custom, endpoint: https://limitdeckai.ru/v1` — то есть путь проверен на практике.
|
||||
|
||||
## P0-1. Разведка — сначала выяснить, что за сервер
|
||||
## P0-1. Разведка выполнена — вот что на сервере
|
||||
|
||||
**Не угадывайте.** Прежде чем писать адаптер, определите, что именно слушает на 192.168.1.81 и по какому интерфейсу.
|
||||
Владелец дал доступ по ключу, ревьюер зашёл и всё выяснил. **Заново не выясняйте.**
|
||||
|
||||
Ревьюер проверил снаружи: **пинг проходит, открыты порты 22 и 3000**. Порт 3000 — это Rocket.Chat, к моделям отношения не имеет. Порт Ollama по умолчанию (11434) **закрыт снаружи** — значит сервер слушает только localhost либо использует другой порт.
|
||||
На `192.168.1.81` работают **два сервера llama.cpp**, оба OpenAI-совместимые:
|
||||
|
||||
Попросите владельца выполнить **на сервере** и приложите вывод в отчёт:
|
||||
| Порт | Модель | Настройки |
|
||||
|---|---|---|
|
||||
| **8081** | `Qwen3.8-27B-Q4_K_M.gguf` | `-ngl 99`, контекст 65536, flash-attn, KV-кэш q8_0, **reasoning on** (бюджет 4096, формат deepseek), temp 0.2, top-p 0.9 |
|
||||
| **8082** | `Qwen3-4B-Instruct-2507-Q4_K_M.gguf` | то же, но **reasoning off**; в имени каталога — «compressor» |
|
||||
|
||||
Проверено запросами:
|
||||
|
||||
```
|
||||
ss -tlnp | grep -E '11434|8000|8080|1234|5000|5001'
|
||||
curl -s localhost:11434/api/tags | head -20
|
||||
curl -s localhost:8000/v1/models | head -20
|
||||
docker ps --format '{{.Names}}\t{{.Ports}}\t{{.Image}}'
|
||||
GET /v1/models -> список моделей, формат llama.cpp
|
||||
POST /v1/chat/completions -> 200 (на обоих портах)
|
||||
```
|
||||
|
||||
От результата зависит: адрес, порт, наличие `/v1/models`, нужен ли ключ, и слушает ли сервис только localhost — в последнем случае Hub с другой машины до него не достучится без правки конфигурации сервера.
|
||||
Видеокарта: **Tesla V100-PCIE-32GB, занято 28.7 ГБ из 32.7**.
|
||||
|
||||
Ревьюер не имеет доступа по SSH (вход по ключу не настроен, пароли не используются), поэтому эту часть выполняет владелец.
|
||||
### Три следствия, которые определяют реализацию
|
||||
|
||||
1. **Оба сервера слушают только `127.0.0.1`.** Снаружи, в том числе с машины владельца под Windows, они недоступны. Пока это не решено, провайдер работать не будет. Решение выбирает владелец, вариант в отчёт:
|
||||
- перезапустить llama.cpp с `--host 0.0.0.0` — модель станет доступна всем в домашней сети;
|
||||
- держать Hub на самом сервере — там уже стоят Hermes и Hub, и `127.0.0.1` доступен напрямую;
|
||||
- проброс по SSH — не годится для службы, туннель придётся держать поднятым.
|
||||
|
||||
2. **У обоих серверов `--parallel 1`.** Это значит **один запрос за раз**. Второй встанет в очередь и будет ждать. Для маршрутизации это принципиально: лизы Hub обязаны ограничивать локального провайдера одним одновременным вызовом, иначе роли начнут блокировать друг друга и таймауты пойдут лавиной.
|
||||
|
||||
3. **Память видеокарты почти исчерпана** — 28.7 из 32.7 ГБ. Третью модель не поднять, и это не проблема Hub, а факт, который надо учитывать: локальный провайдер даёт ровно две модели.
|
||||
|
||||
### Что это значит для ролей
|
||||
|
||||
Набор напрашивается сам:
|
||||
|
||||
- **27B с reasoning** — тяжёлые роли: `reviewer`, `coder-secondary`. Модель рассуждающая, с большим контекстом;
|
||||
- **4B** — `fast`: быстрые вспомогательные вызовы, ради чего она и поднята.
|
||||
|
||||
Предложить владельцу, не менять цепочки молча.
|
||||
|
||||
## P0-2. Провайдер локальных моделей
|
||||
|
||||
|
|
@ -69,7 +90,7 @@ docker ps --format '{{.Names}}\t{{.Ports}}\t{{.Image}}'
|
|||
1. **Адаптер**: OpenAI-совместимый `POST {base_url}/chat/completions`. Ключ необязателен: локальные серверы обычно его не требуют. Если ключа нет — не выдумывать заголовок авторизации.
|
||||
2. **Обнаружение моделей**: `GET {base_url}/models`. Это штатный способ, и он избавляет от той боли, что была с `agy models`. Список кладётся в тот же `ModelDiscoveryService`.
|
||||
3. **`health_check`**: запрос к `{base_url}/models` с коротким таймаутом. Локальная сеть быстрая, но сервер может быть выключен — отказ должен быть быстрым и внятным, а не висеть.
|
||||
4. **Профили и слоты**: добавить `local-1`, `local-2`, `local-3` во встроенные умолчания, чтобы миграция из A9 довела их до существующих конфигураций. Проверить, что `find_free_slot("local")` возвращает существующий профиль.
|
||||
4. **Профили и слоты**: добавить `local-1` и `local-2` во встроенные умолчания — ровно по числу поднятых моделей; третью на этой видеокарте не запустить, чтобы миграция из A9 довела их до существующих конфигураций. Проверить, что `find_free_slot("local")` возвращает существующий профиль.
|
||||
|
||||
## P0-3. Квоты: у локальной модели их нет, и это надо сказать прямо
|
||||
|
||||
|
|
@ -83,7 +104,7 @@ docker ps --format '{{.Names}}\t{{.Ports}}\t{{.Image}}'
|
|||
|
||||
## P0-4. Мастер подключения
|
||||
|
||||
Добавить локального провайдера в мастер. Поля: **адрес сервера** (например `http://192.168.1.81:11434/v1`), необязательный ключ, кнопка проверки.
|
||||
Добавить локального провайдера в мастер. Поля: **адрес сервера** (у владельца это `http://192.168.1.81:8081/v1` и `:8082/v1`), необязательный ключ, кнопка проверки.
|
||||
|
||||
Проверка должна быть настоящей: запрос к `/models`, показ найденных моделей. Не «сохранено», а «сервер ответил, доступно N моделей» с их перечислением.
|
||||
|
||||
|
|
@ -91,7 +112,9 @@ docker ps --format '{{.Names}}\t{{.Ports}}\t{{.Image}}'
|
|||
|
||||
## P0-5. Роль по умолчанию
|
||||
|
||||
Предложить владельцу, куда поставить локальную модель в цепочках, и обосновать. Разумно — последним резервом у `fast` и `research`: она бесплатна и не исчерпывается, значит подходит как последняя линия, когда платные квоты кончились.
|
||||
Предложить владельцу, куда поставить обе модели, и обосновать. Разумно исходить из их назначения: 27B с включённым reasoning — последним резервом у `reviewer` и `coder-secondary`, 4B — у `fast`. Обе бесплатны и не исчерпываются, значит годятся как последняя линия, когда платные квоты кончились.
|
||||
|
||||
Помнить про `--parallel 1`: ставить одну и ту же локальную модель резервом сразу нескольким ролям опасно — при одновременной нагрузке они выстроятся в очередь друг за другом.
|
||||
|
||||
**Не менять цепочки владельца молча.** Предложить в отчёте, решение за ним.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue