Files
wiki/tasks/orchestrator/DEV_TASK_ORCH41_AGENT_MODELS.md
2026-06-05 19:10:01 +03:00

8.9 KiB
Raw Permalink Blame History

DEV TASK — ORCH-41: Конфигурируемые модели LLM per-agent + per-project

Контекст / корень

Сейчас модель агентов зашита в коде src/agents/launcher.py (AGENT_CONFIGS):

  • architect, reviewer → "model": "opus"
  • analyst, developer, tester, deployer → модели НЕТ (CLI берёт дефолт)
  • Алиас opus в CLI 2.1.142 резолвится в opus-4-7 (подтверждено логами runs/102,103).

Слава хочет: модель выбирается в настройках, под каждого агента, с возможностью задать per-project. Это первый шаг к мультипровайдерности (ORCH-13). НЕ хардкодить версию — вынести в конфиг.

Расширено (решение Славы 05.06): 4.7 и 4.8 стоят одинаково → дефолт = claude-opus-4-8. Дополнительно конфигурируем режим работы модели --effort (low/medium/high/xhigh/max) — это рычаг «качество vs стоимость/время», per-agent + per-project, тем же резолвингом. Опционально: --fallback-model (авто-фолбэк при overloaded, работает с --print).

Репозиторий / ветка

  • Репо: orchestrator, база main (HEAD 8da571d)
  • Ветка: feat/ORCH-41-agent-models, PR в main, НЕ мержить.
  • Сервер: sshpass -p 'motoZ@yaz2010' ssh slin@82.22.50.71, контейнер orchestrator.

Архитектура (изучено лично — используй эти точки)

  • src/config.pyclass Settings(BaseSettings) (pydantic-settings, env-driven, префикс ORCH_). Паттерн уже есть: plane_bot_analyst..deployer. Делай модели по аналогии.
  • src/projects.py@dataclass(frozen=True) class ProjectConfig (поля: plane_project_id, repo, work_item_prefix), парсится из settings.projects_json. Сюда добавляем per-project модели.
  • src/agents/launcher.pyAGENT_CONFIGS (dict по агентам) + сборка model_flag (строки ~88,99,207-208):
    model = config.get("model", "")
    model_flag = f"--model {model} " if model else ""
    

Что сделать

1. Глобальные дефолты модели per-agent — в Settings (src/config.py)

Добавить поля (env ORCH_AGENT_MODEL_<AGENT> и ORCH_AGENT_EFFORT_<AGENT>). Дефолт модели = claude-opus-4-8 (цена 4.7==4.8, решение Славы).

# Per-agent LLM model (ORCH-41). Empty -> agent_model_default. Resolution order:
# project-override > ORCH_AGENT_MODEL_<AGENT> > agent_model_default > CLI default.
agent_model_default: str = "claude-opus-4-8"
agent_model_analyst: str = ""
agent_model_architect: str = ""
agent_model_developer: str = ""
agent_model_reviewer: str = ""
agent_model_tester: str = ""
agent_model_deployer: str = ""

# Per-agent effort / reasoning level (ORCH-41): low|medium|high|xhigh|max.
# Empty -> agent_effort_default. Same resolution order as model.
# Раскладка по умолчанию: думающие агенты — high, механические — medium.
agent_effort_default: str = "high"
agent_effort_analyst: str = "high"
agent_effort_architect: str = "high"
agent_effort_developer: str = "high"
agent_effort_reviewer: str = "high"
agent_effort_tester: str = "medium"
agent_effort_deployer: str = "medium"

# Optional per-agent fallback model when primary is overloaded (--fallback-model).
agent_fallback_model: str = ""

2. Per-project override — в ProjectConfig (src/projects.py)

Добавить опциональные поля agent_models: dict[str,str] И agent_efforts: dict[str,str] (агент→модель / агент→effort), парсить из projects_json. Пример записи реестра:

{"plane_project_id":"...","repo":"orchestrator","work_item_prefix":"ORCH",
 "agent_models":{"developer":"claude-opus-4-8","reviewer":"claude-sonnet-4-6"},
 "agent_efforts":{"developer":"xhigh","tester":"low"}}

Оба поля опциональны → старые записи работают (default = {}). ВНИМАНИЕ: dataclass frozen=True + mutable default → используй field(default_factory=dict).

3. Резолвинг — helper(ы) (где удобнее: launcher или projects)

resolve_agent_model(agent, project_id) -> str с приоритетом:

  1. ProjectConfig.agent_models[agent] (per-project override)
  2. settings.agent_model_<agent> (глобальный per-agent env, если непусто)
  3. settings.agent_model_default
  4. (пусто) → без --model, CLI-дефолт

Аналогично resolve_agent_effort(agent, project_id) -> str (тот же приоритет, через agent_efforts / agent_effort_<agent> / agent_effort_default). Валидировать значение по множеству {low,medium,high,xhigh,max}; невалидное → лог-warning + опустить флаг. Желательно общий приватный резолвер, чтобы не дублировать логику приоритета.

4. Применить в launcher.py

  • Убрать хардкод "model": "opus" из AGENT_CONFIGS (architect, reviewer) — модель теперь резолвится.
  • При сборке команды:
    model = resolve_agent_model(agent, project_id)
    effort = resolve_agent_effort(agent, project_id)
    model_flag  = f"--model {model} " if model else ""
    effort_flag = f"--effort {effort} " if effort else ""
    fb = settings.agent_fallback_model
    fb_flag = f"--fallback-model {fb} " if fb else ""
    
    и подставить {model_flag}{effort_flag}{fb_flag} в cmd.
  • project_id уже доступен в потоке запуска (передаётся в launch — проверь сигнатуру, протяни если надо).

5. Тесты (tests/)

  • test_resolve_agent_model.py: все 4 уровня приоритета (project > env > default > пусто), отсутствие проекта, неизвестный агент, frozen-dataclass с agent_models.
  • test_resolve_agent_effort.py: те же уровни + валидация значения (невалидное → опускается).
  • Проверить, что --model / --effort / --fallback-model корректно подставляются/опускаются в собранной команде (по флагу присутствия).

6. Документация

  • Обновить docs/ (конфиг-референс орка): новые env ORCH_AGENT_MODEL_*, ORCH_AGENT_EFFORT_*, ORCH_AGENT_FALLBACK_MODEL, поля agent_models/agent_efforts в projects_json.
  • Кратко описать значения effort (low|medium|high|xhigh|max) и дефолтную раскладку по агентам.
  • CHANGELOG.md.

Команды проверки (ОБЯЗАТЕЛЬНО до отчёта)

# из клона ветки в окружении прод-образа орка:
docker exec -w <clone> -e PYTHONPATH=<clone> orchestrator python3 -m pytest tests/ -q -p no:cacheprovider
# Ожидаемо: 0 failed (>=402 passed + новые)
# Проверь резолвинг руками:
python3 -c "from src.agents.launcher import resolve_agent_model; print(resolve_agent_model('developer','<orch_proj_id>'))"

Off-limits / грабли

  • НЕ менять логику гейтов, webhook, HMAC, очередь.
  • НЕ хардкодить версию модели в коде (вся суть задачи — конфигурируемость).
  • frozen dataclass + dict → field(default_factory=dict), иначе TypeError.
  • Тесты НЕ в docker-образе → гонять из клона репо.
  • После push: git log origin/main..origin/feat/ORCH-41-agent-models показывает коммит ДО отчёта.
  • Не регистрировать раннеров, не nohup.
  • ⚠️ Бюджет (ORCH-38): дефолт 4-8 может быть дороже 4-7. НЕ менять дефолт на проде сам — только в коде как default; реальное переключение прода/env делаю я после ОК Славы.

Результат

PR feat/ORCH-41-agent-models → main. Модель агентов конфигурируема: глобально (env per-agent), с per-project override в projects_json. 0 failed. Отчёт: tasks/orchestrator/reports/dev-2026-06-05-orch41-agent-models.md + краткое резюме мне (что добавил, вывод pytest, ссылка на PR, пример конфига).