Files
vidconf/docs/deploy/llm-setup.md
Max Ronzhin 693db6e774 install.sh, docs: pass --env-file explicitly to docker compose
docker compose определяет .env для подстановки ${VAR} по каталогу
compose-файла (deploy/), а не по текущей директории — repo-root .env,
который использует install.sh и вся документация, молча не подхватывался.
Это и была причина "WARN: LIVEKIT_API_KEY not set" на боевом сервере:
секреты были в .env, но compose их не видел и подставлял небезопасные
дефолты (см. таблицу разведки сервера).

Теперь ставшие обязательными ${VAR:?} в docker-compose.yml (см. предыдущий
коммит) без этого немедленно проваливали бы конфиг на любой из
документированных команд. Добавлен `--env-file .env`/"$ENV_FILE" ко всем
вызовам docker compose в install.sh и в командах из README/docs.

install.sh дополнительно: ensure_default (аналог ensure_secret без генерации
секрета) для новых не-секретных параметров nginx/coturn/livekit
(NGINX_SERVER_NAMES, NGINX_CERT_NAME, LIVEKIT_USE_EXTERNAL_IP,
LIVEKIT_NODE_IP, TURN_EXTERNAL_IP) — дефолты только для локальной
разработки, не перезаписывают значения, заданные вручную на боевом
сервере. Плюс вызов deploy/render-templates.sh перед сборкой/подъёмом
стека.
2026-07-25 21:58:03 +03:00

7.7 KiB
Raw Permalink Blame History

Настройка локального LLM-сервера (Qwen3.5, профили compose llm/llm-gpu)

Плагин суммаризации qwen_local (backend/core/plugins/qwen_local.py) обращается к OpenAI-совместимому серверу llama.cpp. Модель и параметры — единый источник истины ADR-004 (docs/architecture/adr/004-ai-tier-matrix.md) и константная матрица backend/services/ai_tiers.py. В обычной установке всё описанное ниже делает install.sh (см. docs/deploy/dev-setup.md) — этот раздел актуален для ручного/точечного запуска профиля без инсталлятора.

1. Компоненты

Сервис Образ Профиль Назначение
llm-models-init busybox llm/llm-gpu фиксирует владельца тома llm-models (обходит дефект прав доступа)
llm-model-init curlimages/curl llm/llm-gpu однократное скачивание GGUF-модели и tokenizer.json уровня AI
llm ghcr.io/ggml-org/llama.cpp:server-b<build> llm CPU-инференс (/v1/chat/completions), уровни min/medium
llm-gpu ghcr.io/ggml-org/llama.cpp:server-cuda-b<build> llm-gpu GPU-инференс, уровень max (ADR-004: GPU обязателен)

Файлы:

  • deploy/llm/download-model.sh — генерализованный скрипт скачивания (параметризован LLM_MODEL_FILE/LLM_MODEL_URL/LLM_MODEL_MIN_SIZE/ LLM_TOKENIZER_FILE/LLM_TOKENIZER_URL; их пишет install.sh по выбранному пресету — см. install.sh --help).
  • deploy/docker-compose.yml — сервисы llm-models-init/llm-model-init/ llm/llm-gpu, volume llm-models, монтирование llm-models:/models/qwen:ro в сервис worker (там же считаются токены чанкером — QwenTokenCounter).

2. Модели по уровням AI (ADR-004)

Уровень Модель Квант Файл (LLM_MODEL_FILE) Источник GGUF (LLM_MODEL_URL)
min (пресет 3) Qwen3.5-4B-Instruct Q4_K_M ≈ 2,6 ГиБ qwen3.5-4b-instruct-q4_k_m.gguf unsloth/Qwen3.5-4B-GGUF
medium (пресет 4) Qwen3.5-9B-Instruct Q4_K_M ≈ 5,3 ГиБ qwen3.5-9b-instruct-q4_k_m.gguf unsloth/Qwen3.5-9B-GGUF
max (пресет 5) Qwen3.5-35B-A3B-Instruct (MoE) Q4_K_M ≈ 20,5 ГиБ qwen3.5-35b-a3b-instruct-q4_k_m.gguf unsloth/Qwen3.5-35B-A3B-GGUF

tokenizer.json (переименован под LLM_TOKENIZER_FILE — нужен QwenTokenCounter, backend/core/summarization/tokens.py) берётся из официальных репозиториев Qwen/Qwen3.5-<размер> (публичные, без gate; GGUF-репозитории Qwen/…-GGUF — gated, поэтому источник GGUF — публичное зеркало unsloth/…-GGUF, файлы идентичны по содержимому квантизации).

Имена файлов на диске (LLM_MODEL_FILE/LLM_TOKENIZER_FILE) — КОНТРАКТ с детектом доступности уровня AI (backend/services/ai_levels.py через backend/services/ai_tiers.py::TIERS[level].model_files): именно эти пути проверяются на «модель скачана» в админке.

Скачивание идемпотентно (проверка по наличию и минимальному размеру файла, LLM_MODEL_MIN_SIZE) — повторный запуск на уже заполненном томе ничего не перекачивает. Ручной запуск (прогреть volume заранее):

LLM_MODEL_FILE=qwen3.5-4b-instruct-q4_k_m.gguf \
LLM_MODEL_URL=https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/Qwen3.5-4B-Q4_K_M.gguf \
LLM_TOKENIZER_FILE=qwen3.5-4b-instruct.tokenizer.json \
LLM_TOKENIZER_URL=https://huggingface.co/Qwen/Qwen3.5-4B/resolve/main/tokenizer.json \
docker compose -f deploy/docker-compose.yml --env-file .env --profile llm run --rm llm-model-init

3. Запуск профиля

CPU (уровни min/medium, пресеты 3/4):

docker compose -f deploy/docker-compose.yml --env-file .env \
  --profile media --profile transcribe --profile llm up -d

GPU (уровень max, пресет 5 — GPU обязателен):

docker compose -f deploy/docker-compose.yml --env-file .env \
  --profile media --profile transcribe-gpu --profile llm-gpu up -d

Проверка готовности (порт 8080llm, 8081llm-gpu на хосте; внутри docker-сети оба доступны как llm:8080/llm-gpu:8080, llm-gpu также отвечает под алиасом llm — см. комментарий в deploy/monitoring/prometheus.yml):

curl http://localhost:8080/health
# пока модель грузится:  {"error":{"code":503,"message":"Loading model",...}}
# сервер готов:          {"status":"ok"}

4. Включение провайдера qwen_local

Дефолт репозитория в config/plugins.yamlsummarizer.provider: "null" (безопасно для dev-окружений без LLM-сервера). Уровень min включается по образцу закомментированного примера в config/plugins.yaml; уровни medium/max собираются автоматически из TIERS (backend/services/ai_tiers.py) при выборе уровня AI в админке — руками их прописывать не нужно (см. backend/services/instance_settings.py::_apply_tier_overrides).

После правки config/plugins.yaml (уровень min, ручной dev-сценарий) перезапустить worker:

docker compose -f deploy/docker-compose.yml --env-file .env up -d --force-recreate worker

5. Проверка вручную

  1. Поднять профиль llm/llm-gpu, дождаться docker compose ps → healthy.
  2. curl http://localhost:8080/health{"status":"ok"}.
  3. Включить уровень AI в админке (или qwen_local в config/plugins.yaml для ручного dev-сценария уровня min).
  4. Прогнать пайплайн на тестовом сеансе (см. docs/plugins/summarizer.md) и убедиться, что conference_sessions.summary_data заполняется.

6. Ресурсы, thinking-режим и мониторинг

  • Требования CPU/RAM/GPU по пресетам — docs/architecture/adr/004-ai-tier-matrix.md.
  • LLAMA_ARG_CTX_SIZE=16384с запасом на чанк до 8000 токенов + промпт + вывод (per-tier max_tokens_map/max_tokens_reduce, ADR-004).
  • Thinking-режим (семейство Qwen3.5) отключается флагом LLAMA_ARG_REASONING=off (актуальная замена --chat-template-kwargs '{"enable_thinking":false}' из ADR-004 — та же семантика, но без деприкейшен-варнинга в логе на каждый запуск, проверено через find-docs по common/arg.cpp проекта llama.cpp).
  • /metrics (LLAMA_ARG_ENDPOINT_METRICS=1) собирает Prometheus, профиль compose monitoringdeploy/monitoring/prometheus.yml, job llm.