Перейти к содержанию

Валидатор первым: метод работы

Главное организационное решение проекта. Всё остальное — следствия.

Почему

Режим работы — код пишут агенты, один человек ревьюит. В таком режиме единственный масштабируемый способ контроля — числовой:

Вы можете контролировать агентов только в том, что умеете проверить.

Читать весь код нереально. Доверять уверенным объяснениям нельзя — они правдоподобны ровно в той же мере, что и верные. Остаётся одно: независимая функция, которая берёт план и возвращает числа. Дальше агенты гоняют хоть сто итераций — ревьюер смотрит в таблицу метрик.

Эта задача выбрана именно потому, что в ней такая функция существует (60-decisions/01 (../60-decisions/01-why-task-5.md)). Не воспользоваться этим было бы странно.

Порядок работ

1. Схемы входа и выхода            ← без них нечего валидировать
2. Генератор тестовых сценариев    ← без них не на чем гонять
3. Валидатор метрик                ← без него нечем мерить
4. Наивный бейзлайн                ← без него метрики ни с чем не сравнить
─────────────────────── только теперь ───────────────────────
5. Геометрия съёмки
6. Покрытие
7. Распределение
8. Экспорт
9. Фронтенд

Шаги 1–4 — это полтора-два дня, и они окупаются немедленно: после них любое изменение в алгоритме немедленно выражается в дельте метрик.

Что считает валидатор

Скрипт берёт сценарий и план как данные и пересчитывает всё заново по геометрии.

Жёсткие проверки — любое ненулевое значение означает невалидный план

Метрика Условие
violations.nfz длина траектории внутри бесполётных зон = 0
violations.airspace длина траектории вне разрешённого ВП = 0
violations.endurance ни один вылет не превышает endurance · (1 − reserve)
violations.wind W ≤ wind_max для всех задействованных бортов; |W⊥| < V_a на каждом галсе
violations.payload тип съёмки каждого галса совместим с нагрузкой назначенного борта
violations.altitude высота в пределах потолков борта, не ниже точки старта
violations.turnaround интервал между вылетами борта ≥ времени оборота
unassigned список неназначенных галсов с причиной — пустой или объяснённый

Метрики качества — то, что оптимизируем

Метрика Смысл
coverage_fraction площадь объединения полос захвата ∩ полигон / площадь полигона
makespan_s R-OPT-1
total_flight_time_s R-OPT-2
transects_total, turns_total косвенно — качество выбора угла
turn_time_fraction доля времени на разворотах; показывает, насколько наивная оценка врёт
uavs_used, sorties_total загрузка парка
solve_time_s масштабируемость

Принцип независимости

Валидатор не импортирует ничего из coverage/ и routing/. Если он использует те же функции, что и решатель, он воспроизведёт ту же ошибку и промолчит.

Геометрию он считает сам: берёт координаты из плана, строит буферы полос захвата, пересекает с полигонами и зонами. Медленнее — и это нормально, он не в горячем пути.

Формат отчёта

Одна команда, одна таблица:

$ python -m validator run --scenarios scenarios/ --criteria makespan,total_time

scenario              crit       makespan  total_fl  cover   turns%  solve  viol
─────────────────────────────────────────────────────────────────────────────────
s01-single-simple     makespan     0:22:14   0:22:14  1.000    18%    0.4s    0
s01-single-simple     total_time   0:22:14   0:22:14  1.000    18%    0.3s    0
s02-nonconvex-nfz     makespan     0:41:07   1:58:22  0.998    24%    3.1s    0
s02-nonconvex-nfz     total_time   0:58:40   1:44:05  0.998    22%    2.8s    0
s03-mixed-payloads    makespan     1:28:00   3:51:12  0.996    21%   12.4s    0
...
─────────────────────────────────────────────────────────────────────────────────
БЕЙЗЛАЙН (равное деление)
s03-mixed-payloads    naive        2:14:30   4:02:55  0.994    29%    0.1s    0
                                   ↑ −34,5%   ↑ −4,8%

Три свойства, которые делают эту таблицу рабочим инструментом:

  1. Одна команда — никаких «запусти сервер, открой браузер, кликни».
  2. Бейзлайн в той же таблице — сразу виден процент улучшения.
  3. Колонка viol с нулями — первое, куда смотрит ревьюер. Ненулевое значение отменяет всё остальное.

Как это встраивается в цикл разработки

задача агенту → агент пишет → валидатор гоняет 10 сценариев → таблица
   ↑                                                              │
   └──────────── ревьюер смотрит дельту метрик ───────────────────┘

Правила ревью:

  • viol не ноль — отклонить не читая.
  • Метрики не изменились — рефакторинг безопасен, можно не вчитываться.
  • Метрики улучшились — проверить, что улучшение не за счёт нарушения (например, покрытие упало ниже порога, а makespan «улучшился»).
  • Метрики ухудшились — разбираться предметно.

Последний пункт — единственный случай, где нужно читать код. В остальных хватает таблицы.

Регрессионные тесты как страховка от отката

Отдельная категория тестов — те, что ловят возврат к наивным формулам:

Тест Что ловит
T_план ≥ L_total / V_g строго убрали учёт разворотов
площадь в проекции = геодезической ±0,1 % считают в градусах
центроид выгрузки внутри bbox входа перепутали lon/lat
в каждом LineString KML есть altitudeMode потеряли высоты
makespan монотонно не растёт с ростом числа бортов сломали SetGlobalSpanCostCoefficient
GSD на контрольных высотах совпадает с таблицей сломали геометрию съёмки
round-trip экспорт → импорт сохраняет геометрию сломали конвертер
при фиксированном seed результат воспроизводим потеряли детерминизм

Эти тесты стоят по несколько строк каждый и ловят ровно те ошибки, которые агент может внести «улучшая» код.

Валидатор как часть продукта

Ещё один аргумент за: валидатор можно выставить наружу как POST /validate. Тогда на защите звучит:

Вот наш план. Вот наш же валидатор — он считает метрики независимо от решателя. Загрузите любой другой план, хоть от конкурентов, он проверит и его.

Стоит 0,2 дня, а на критерий «обоснованность подхода» работает сильно.

Связь с автодизайном эвристик

Схема ReEvo/EoH (50-stack/02 (../50-stack/02-llm-and-ml.md)) требует ровно одного — функции оценки, возвращающей число по сгенерированному коду. Это тот же валидатор. То есть полтора дня, вложенные в него, открывают ИИ-слой бесплатно.

Порядок при этом не меняется: сначала валидатор, потому что без него ни оптимизатор, ни LLM-эволюция просто не с чем работать.