Учебный гайд: Приложение D. Калибровка порогов

Урок 3 из 5 в модуле «Приложение D. Калибровка порогов»
Вы просматриваете урок без входа. Войдите, чтобы сохранять прогресс и проходить тесты.

Тема: Приложение D. Калибровка порогов

Уровень сложности: Средний

Расчётное время изучения: 6-8 часов (теория: 3 часа, практика: 3-5 часов)

Предварительные требования: Прохождение глав 5, 6, 9, 10 и 11 курса AgentClinic

Базовое знание YAML и работы с командной строкой

Понимание концепций мутационного тестирования, теневых спецификаций и ярусных бюджетов

Опыт работы с метриками SLA и CI/CD-процессами

Знакомство с эффектом Гудхарта и его проявлениями в инженерных системах

Цели обучения: Настраивать и калибровать пороги мутационного тестирования (strict_reject_rate, depth_of_diagnostics, recovery_time_p95) с учётом специфики проекта и фиксировать обоснование в validation.md

Пересчитывать веса и пороги отбора теневых спецификаций (keep-threshold, reject-threshold, budget-tokens) при изменении цены ложной эскалации и бюджета образцов-подсказок

Проектировать ярусные бюджеты токенов с корректным разбиением local/frontier и проверять целостность через compile.py

Выявлять симптомы эффекта Гудхарта в сети защитных метрик и корректировать пороги только парными сдвигами с сохранением инвариантов

Определять production-готовность системы с учётом типа действий (stateless/stateful) и независимых блокирующих инвариантов

Обзор: Приложение D — справочный материал для переноса процесса AgentClinic-production в собственный проект. Оно систематизирует все таблицы порогов «Низкий / По умолчанию / Высокий» для пяти ключевых областей: мутационное тестирование, отбор теневых спецификаций, ярусные бюджеты, защита метрик от Гудхарта и production-готовность. Центральный принцип: пороги имеют смысл только в паре. Сдвиг одного значения без пересчёта связанного — это не калибровка, а демонтаж контура управления. Руководство содержит практические упражнения на реальных скриптах, сигналы для пересмотра порогов и предупреждения о рисках некорректной калибровки.

Ключевые концепции: Парная калибровка: Фундаментальный принцип приложения D: любой порог существует в связке с другими параметрами. Например, strict_reject_rate и depth_of_diagnostics двигаются только вместе. Если strict_reject_rate растёт, а depth_of_diagnostics падает — это симптом Гудхарта, а не улучшение качества. Аналогично: штраф false_escalation и вес mttr_gain, silent_p0 и manual_review_rate, edge_drift и audit_trace_coverage.

Значения по умолчанию agentclinic: Базовая линия для production-системы со средним потоком инцидентов (200/день), зрелым SDD-процессом (6+ месяцев) и смешанным типом действий. Все отклонения от этой линии требуют обоснования в validation.md.

Сигналы пересмотра порогов: Конкретные триггеры, указывающие на необходимость калибровки: отсутствие блокировок за квартал (порог избыточно низкий), концентрация регрессий по одному mutation_id (порог недостаточен), падение recovery_time_p95 к нулю при росте strict_reject_rate (Гудхарт), рост manual_review_rate при росте mttr_gain (подмена цели).

Эффект гудхарта в метриках: Когда метрика становится целью, она перестаёт быть хорошей метрикой. В контексте AgentClinic: рост strict_reject_rate без реального улучшения диагностики, сокращение MTTR за счёт игнорирования сложных кейсов, рост mttr_gain при параллельном росте false_escalation — все эти паттерны требуют парной коррекции.

Независимые блокирующие инварианты: Метрики, которые не входят в суммарный порог, но блокируют слияние независимо. Например, audit_trace_coverage = 1.0 — обязательное условие для production-готовности; при audit_trace_coverage = 0.7 готовность 22/25 или даже 25/25 не допускает auto-переключение.

Ротация зерна мутаций: Практика периодической смены seed в мутационном тестировании для предотвращения переобучения валидатора на фиксированный набор mutation_id. Одно зерно, повторяющееся пять спринтов подряд — сигнал к ротации.

Ярусное разбиение бюджета: Архитектура распределения токенов между local-ярусом (9M из 10M) и frontier-ярусом (1M). Пропорции связаны с SLA по фазам: изменение daily_budget_tokens без обновления budget_plan_phases нарушает целостность и приводит к ошибке в compile.py.

Профили риска для теневых спецификаций: Конфигурация весов в формуле отбора: консервативный профиль (0.3, 0.4, 0.2, 0.8) сильнее штрафует ложную эскалацию и меньше награждает MTTR, чем стандартный (0.5, 0.3, 0.2, -0.4).

Режимы эксплуатации: Иерархия допусков: auto ≥23/25 — полностью автоматический режим; полуручной 20–22 — остановка после implement с явным подтверждением; canary — постепенное развёртывание. Снижение ниже 23/25 — это изменение режима, а не «мягче порог».

Сеть зависимостей метрик: Полная модель взаимосвязей: silent_p0 и escalation_rate положительно влияют на MTTR; manual_review_rate и audit_trace_coverage отрицательно влияют на MTTR и escalation_rate; postmortem_regression положительно связана с audit_trace_coverage и отрицательно — с manual_review_rate.

Практические упражнения: Название: Упражнение D.1: Калибровка depth_of_diagnostics

Проблема: В проекте с графом маршрутов из 80 рёбер (multi-tenant) требуется проверить, как изменение порога depth_of_diagnostics_min с 3 на 5 повлияет на immunity_score. Используйте скрипты из book2/examples/stress-mutator.

Решение: 1. Перейдите в директорию: cd book2/examples/stress-mutator

  1. Создайте выходную директорию: mkdir -p out
  2. Скопируйте и модифицируйте ожидаемый результат: cp expected/expected_failures.json out/expected_failures_depth5.json; sed -i 's/"depth_of_diagnostics_min": 3/"depth_of_diagnostics_min": 5/' out/expected_failures_depth5.json
  3. Запустите базовый расчёт: python3 scripts/immunity_score.py --validator-results out/validator_results.json --expected expected/expected_failures.json --out out/immunity_default.json — должен пройти (средняя глубина 4 > 3)
  4. Запустите ужесточённый расчёт: python3 scripts/immunity_score.py --validator-results out/validator_results.json --expected out/expected_failures_depth5.json --out out/immunity_depth5.json — должен завершиться кодом 1
  5. Сравните дельту: это не новый дефект, а цена ужесточения порога. Зафиксируйте обоснование в validation.md: «Граф расширен до 80 рёбер, multi-tenant; depth_of_diagnostics_min повышен до 5, strict_reject_rate пересчитан до ≥0.995».

Сложность: intermediate

Название: Упражнение D.2: Консервативный профиль теневого аукциона

Проблема: Команда здравоохранения требует снизить ложные эскалации. Сформируйте консервативный профиль весов и проанализируйте, какие кандидаты изменят статус.

Решение: 1. Перейдите в директорию: cd book2/examples/shadow-auction

  1. Запустите аукцион с консервативными весами: python3 scripts/score.py --candidates candidates/candidates.yaml --incidents data/incidents.jsonl --weights "0.3,0.4,0.2,0.8" --out out/scorebook.json
  2. Примените пороги с увеличенным бюджетом: python3 scripts/decide.py --scorebook out/scorebook.json --budget-tokens 2000 --keep-threshold 0.70 --reject-threshold 0.40 --out-auction out/auction.json --out-quarantine out/quarantine.json
  3. Проанализируйте изменения: shadow.p0.voice_handoff переходит из winner в disputed (высокий риск ложной эскалации), shadow.alert.red_color_urgency остаётся в rejected
  4. Зафиксируйте в validation.md: «Цена ложной эскалации повышена до 0.8, keep-threshold снижен до 0.70, budget-tokens увеличен до 2000 для компенсации консервативности».

Сложность: intermediate

Название: Упражнение D.3: Проверка целостности ярусного бюджета

Проблема: Проект с потоком 50 инцидентов/день требует бюджет 5M токенов. Проверьте, что compile.py отклонит некорректную спецификацию с изменённым daily_budget_tokens без пересчёта фазовых квот.

Решение: 1. Перейдите в директорию: cd book2/examples/budget-keeper

  1. Скомпилируйте корректный план: python3 scripts/compile.py --budget-spec specs/budget_network_5m.yaml --out out/budget_plan_5m.json
  2. Проверьте сохранение пропорций: local = 4.5M, frontier = 0.5M (90/10)
  3. Смоделируйте отказ локального яруса: python3 scripts/simulate.py --plan out/budget_plan_5m.json --scenario scenarios/fail_local_45m.json --out out/fail_result_5m.json
  4. Проверьте здоровье: python3 scripts/inspect.py --result out/fail_result_5m.json --query "failover_to_frontier==2 && degraded_queue==18 && token_health_min>=0.5"
  5. Создайте некорректную спецификацию: скопируйте budget_network_5m.yaml, измените только daily_budget_tokens на 3M, оставив фазовые квоты
  6. Убедитесь, что compile.py падает с ошибкой суммы — это защита от демонтажа контура.

Сложность: intermediate

Название: Упражнение D.4: Демонстрация опасности раздельной калибровки guard-метрик

Проблема: Покажите, почему ослабление двух независимых защит одновременно пропускает плохой релиз, тогда как ослабление одной — нет.

Решение: 1. Перейдите в директорию: cd book2/examples/goodhart-validator; mkdir -p out

  1. Первый сценарий — ослабление silent_p0_cap: cp specs/validation.yaml out/validation_loose.yaml; sed -i 's/threshold: 0.05/threshold: 0.08/' out/validation_loose.yaml; python3 scripts/run_validation.py --validation out/validation_loose.yaml --metrics fixtures/new_metrics_bad.json — результат: FAILED (silent_p0=0.18 > 0.08)
  2. Второй сценарий — опасное двойное ослабление: cp specs/validation.yaml out/validation_unsafe.yaml; sed -i 's/threshold: 0.15/threshold: 0.10/' out/validation_unsafe.yaml; sed -i 's/threshold: 0.05/threshold: 0.20/' out/validation_unsafe.yaml; python3 scripts/run_validation.py --validation out/validation_unsafe.yaml --metrics fixtures/new_metrics_bad.json — результат: PASSED (ложноположительный)
  3. Сделайте вывод: guard-метрики образуют единый контракт риска, ослаблять их по отдельности нельзя. Зафиксируйте в validation.md запрет на однострочные изменения YAML.

Сложность: advanced

Название: Упражнение D.5: Проверка независимости audit_trace_coverage

Проблема: Покажите, что audit_trace_coverage — независимый блокирующий инвариант, не входящий в сумму 25/25 для production-готовности.

Решение: 1. Перейдите в директорию: cd book2/examples/real-api; mkdir -p out

  1. Скопируйте и модифицируйте скрипт: cp scripts/check_readiness.py out/check_readiness_t22.py; sed -i 's/THRESHOLD = 23/THRESHOLD = 22/' out/check_readiness_t22.py
  2. Запустите с readiness_block_audit.json: python3 out/check_readiness_t22.py --readiness fixtures/readiness_block_audit.json
  3. Результат: BLOCKED из-за audit_trace_coverage=0.7 < 1.0, несмотря на сумму 22/25 (или даже потенциальные 25/25)
  4. Проанализируйте: это демонстрирует, что Security=0 или audit_trace_coverage<<1.0 — абсолютные блокираторы. Снижение THRESHOLD до 22 — это переход в полуручной режим, а не «мягче допуск». Зафиксируйте в validation.md: «audit_trace_coverage=1.0 — регуляторный инвариант, не подлежит калибровке».

Сложность: intermediate

Кейсы: Название: Кейс: Перекалибровка порогов при выходе на рынок здравоохранения

Сценарий: Команда AgentClinic-production, работавшая с внутренними инструментами (strict_reject_rate ≥ 0.98, depth_of_diagnostics ≥ 3), получила контракт на обработку инцидентов медицинской информационной системы. Регуляторные требования: пропуск P0-критичного инцидента влечёт штраф до 2% годового оборота и уголовную ответственность руководства.

Задача: Стандартные пороги AgentClinic недостаточны для здравоохранения. Команда столкнулась с необходимостью одновременного повышения strict_reject_rate до ≥0.995, depth_of_diagnostics до ≥5 (граф маршрутов расширен до 120 рёбер, multi-tenant с изоляцией пациентов), снижения recovery_time_p95 до ≤1500 мс при >500 PR/день. Риск: изолированное повышение strict_reject_rate без depth_of_diagnostics приведёт к эффекту Гудхарта — валидатор будет отклонять всё подряд, включая корректные фиксы.

Решение: Команда провела парную калибровку по методологии Приложения D: 1) Зафиксировала обоснование в validation.md: «Регуляторный контракт §12.3, цена пропуска P0: штраф 2% + уголовная ответственность»; 2) Повысила strict_reject_rate до 0.995 и одновременно depth_of_diagnostics до 5; 3) Увеличила число мутантов на класс до 5+ с ротацией зерна каждые 2 спринта; 4) Провела стресс-тестирование через immunity_score.py с искусственно ужесточённым порогом depth_of_diagnostics_min=5; 5) Убедилась, что recovery_time_p95 не падает к нулю при росте strict_reject_rate — отсутствие симптома Гудхарта.

Результат: Система прошла аудит регулятора с нулевыми пропусками P0 за 6 месяцев эксплуатации. MTTR вырос на 12% из-за углублённой диагностики, но это было принято как необходимая цена соответствия. Ротация зерна выявила 3 переобучения валидатора до их попадания в production.

Извлечённые уроки: Регуляторные требования требуют не «максимальных» порогов, а обоснованных парных сдвигов с документированием цены решения

Ротация зерна — не опциональная практика, а обязательная при повышении числа мутантов, иначе валидатор переобучается на фиксированные паттерны

Рост MTTR на 12% при увеличении depth_of_diagnostics — ожидаемый trade-off, который нужно закладывать в SLA с заказчиком заранее

Отсутствие симптома Гудхарта (recovery_time_p95 → 0) — более важный индикатор здоровья, чем абсолютное значение strict_reject_rate

Связанные концепции: Парная калибровка

Сигналы пересмотра порогов

Эффект Гудхарта в метриках

Ротация зерна мутаций

Название: Кейс: Демонтаж контура при некорректном сжатии бюджета

Сценарий: Финтех-стартап, переживавший кризис ликвидности, решил сократить расходы на LLM-инфраструктуру на 50%. Технический директор изменил только daily_budget_tokens в спецификации с 10M до 5M, не пересчитав фазовые квоты.

Задача: Скрипт compile.py упал с ошибкой суммы — это защитный механизм, предусмотренный в Приложении D. Однако директор, не разобравшись, закомментировал проверку целостности в локальной копии и собрал бюджет вручную. Результат: local-ярус получил 4M вместо 4.5M, frontier — 0.2M вместо 0.5M, а остаток 0.8M был «распределён по усмотрению» без связи с SLA фаз.

Решение: Проблема была выявлена через 3 недели, когда при отказе local-coder система не смогла переключиться на frontier: шлюз оказался слишком жёстким из-за недостатка токенов во frontier-ярусе. Команда восстановила исходный механизм compile.py, провела корректную компиляцию с пропорциями 90/10 (4.5M/0.5M), смоделировала отказ через simulate.py и убедилась в работоспособности failover_to_frontier.

Результат: Простой системы составил 47 минут, 12 инцидентов ушли в manual_queue с превышением SLA. Финансовые потери превысили экономию от сжатия бюджета в 8 раз. Технический директор был отстранён от принятия инфраструктурных решений.

Извлечённые уроки: compile.py — не бюрократическое препятствие, а защита контура управления; обход проверок — это демонтаж, а не оптимизация

Пропорции 90/10 связаны с SLA по фазам; их изменение требует пересчёта budget_plan_phases, а не только daily_budget_tokens

Экономия на инфраструктурных guard-метриках имеет отрицательную ROI: потери от одного простоя превышают годовую экономию

Методология Приложения D требует, чтобы любое изменение бюджета проходило через полный цикл: compile → simulate → inspect → документирование в validation.md

Связанные концепции: Ярусное разбиение бюджета

Парная калибровка

Сигналы пересмотра порогов

Название: Кейс: Ложноположительный проход при раздельной калибровке guard-метрик

Сценарий: Команда платёжной системы, работавшая под давлением бизнеса «ускорить релизы», решила «оптимизировать» guard-метрики. Вместо парной калибровки silent_p0 и manual_review_rate, они независимо ослабили оба порога: silent_p0_cap с 0.05 до 0.20 и manual_review_rate с 0.15 до 0.10.

Задача: По отдельности каждое изменение казалось обоснованным: «у нас редкие P0» и «ручных рецензентов мало». Одновременное ослабление создало ложноположительный проход: плохой релиз с silent_p0=0.18 и manual_review_rate=0.08 прошёл валидацию, хотя оба показателя были критически низкими. Это прямое проявление принципа Приложения D: guard-метрики образуют единый контракт риска.

Решение: Инцидент с утечкой платёжных данных (последствия: 340K затронутых транзакций, регуляторный штраф $2.4M) привёл к аудиту. Аудиторы воспроизвели упражнение D.4: ослабление только silent_p0_cap до 0.08 всё ещё блокировало плохой релиз, тогда как двойное ослабление — пропускало. Команда внедрила жёсткое правило: любое изменение validation.yaml требует review с проверкой на «независимые ослабления» и автоматический прогон через goodhart-validator.

Результат: Система восстановлена, регуляторные требования выполнены через экстренное повышение manual_review_rate до 0.25 и введение подписанной трассировки audit_trace_coverage. Время на релиз выросло на 40%, но нулевой уровень пропущенных P0 восстановлен.

Извлечённые уроки: Guard-метрики — это не набор независимых рубильников, а единый контракт риска; ослабление одного в отрыве от остальных — демонтаж защиты

Ложноположительный проход хуже ложноотрицательного блока: пропущенный дефект в production стоит на порядки дороже задержки релиза

Автоматизация проверки «независимых ослаблений» через goodhart-validator должна быть обязательной, не опциональной

Давление бизнеса «ускорить» не оправдывает обход методологии; нужен механизм эскалации, а не тихий компромисс

Связанные концепции: Независимые блокирующие инварианты

Эффект Гудхарта в метриках

Сеть зависимостей метрик

Парная калибровка

Советы по изучению: Проходите материал последовательно по разделам D.1–D.5, не пропуская упражнения — каждое упражнение демонстрирует конкретный риск некорректной калибровки

Ведите собственный validation.md параллельно с изучением: фиксируйте гипотетические обоснования для своего проекта, даже если это учебная симуляция

Используйте подход «предскажи, потом проверь»: перед запуском скрипта запишите ожидаемый результат, затем сравните с фактическим — это развивает интуицию о поведении порогов

Создавайте таблицу соответствия «мой проект → параметры AgentClinic → отклонения → обоснование» — это шаблон для реального переноса

Для визуального стиля: перерисуйте mermaid-схему сети зависимостей метрик на бумаге, отмечая положительные и отрицательные связи разными цветами — это помогает запомнить, какие метрики двигаются парно

Практикуйте выявление симптомов Гудхарта: придумывайте сценарии «что если» и проверяйте, есть ли в Приложении D соответствующий сигнал пересмотра

Группируйте изучение по принципу «один день — одна система риска»: D.1+D.4 (мутации и Гудхарт), D.2+D.5 (теневые спецификации и готовность), D.3 (бюджеты) — так лучше прослеживаются связи между разделами

Для аудиального стиля: диктуйте вслух обоснования калибровки в формате «Если [параметр проекта], то [порог], потому что [риск]» — это готовит к реальным дискуссиям с stakeholders

Тестируйте граничные случаи: что произойдёт, если установить все пороги в «Низкий» или «Высокий» одновременно? Почему это неработоспособно?

Дополнительные ресурсы: Исходные материалы курса agentclinic: Главы 5, 6, 9, 10, 11 — теоретическая база, на которую опирается Приложение D

Репозиторий book2/examples: Практические скрипты для всех упражнений: stress-mutator, shadow-auction, budget-keeper, goodhart-validator, real-api

Шаблон validation.md: Формат документирования обоснований калибровки; создайте собственную копию для проекта

Документация по mermaid: Для самостоятельного редактирования и расширения схем сети зависимостей метрик

Статья «goodhart's law and machine learning» (varoquaux): Теоретическое обоснование парной калибровки и сетевой структуры guard-метрик

Google sre book, chapter 4 (service level objectives): Параллели между error budgets и ярусными бюджетами токенов в AgentClinic

Чек-лист переноса agentclinic в production: Самостоятельно составьте на основе таблиц D.1–D.5 с колонками «Параметр проекта», «Наше значение», «Отклонение от умолчания», «Обоснование», «Дата пересмотра»

Резюме: Приложение D — практический справочник по калибровке порогов AgentClinic-production для переноса в собственные проекты. Ключевые принципы: (1) пороги имеют смысл только в паре, сдвиг одного без пересчёта связанного — демонтаж контура; (2) любое отклонение от значений по умолчанию требует обоснования в validation.md; (3) guard-метрики образуют единый контракт риска, а не набор независимых рубильников; (4) симптомы Гудхарта (рост целевой метрики без реального улучшения, падение связанных показателей) — главный сигнал для парной коррекции; (5) независимые блокирующие инварианты (audit_trace_coverage = 1.0, Security = 0) не подлежат калибровке вообще. Пять разделов покрывают мутационное тестирование, теневые спецификации, ярусные бюджеты, защиту от Гудхарта и production-готовность — каждый с таблицами порогов, практическими упражнениями на реальных скриптах, сигналами пересмотра и предупреждениями о рисках. Методология требует документирования, автоматической проверки целостности и регулярной ротации параметров для предотвращения переобучения.

Мои заметки
0 / 10000

Заметки сохраняются в этом браузере. На другом устройстве они не появятся.

Меню курса

Курс

Production SDD для Qwen Code CLI. Часть 2
Прогресс 0 / 100