Маршрутизация с учётом стоимости
Когда доступно несколько моделей — Opus, Sonnet, Haiku или локальные модели за самостоятельно размещённым шлюзом odysseus — PRECC направляет каждую задачу той из них, которая минимизирует ожидаемую денежную стоимость, а не количество токенов. Токен дешёвой модели и токен дорогой модели стоят по-разному; маршрутизатор оптимизирует доллар при соблюдении измеренного минимального уровня успешности и порога возможностей для каждой категории.
Единицей стоимости является доллар, а не токен
Для задачи категории c среди подходящих по возможностям моделей-кандидатов m маршрутизатор минимизирует ожидаемую взвешенную по цене стоимость. E[$ | task, m] — это измеренная средняя стоимость модели в токенах для этой категории, умноженная на её цену за токен. Запуск Haiku, использующий больше токенов, чем Opus, всё равно может победить, поскольку Haiku в несколько раз дешевле за токен. Каждое число в целевой функции либо измерено (средние значения токенов из оракула, зафиксированная успешность, опубликованные цены моделей), либо является явно помеченным априорным предположением — никогда не сфабриковано.
choose argmin_m E[$ | task, m]
subject to P(success | task, m) >= min_success
capability(m) >= capability_floor(category)
Маршрутизация задачи
precc route "<task>" категоризирует задачу, применяет порог возможностей, ранжирует подходящие модели по ожидаемым долларам и выводит решение. С --execute он отправляет задачу выбранной модели через сессионный API odysseus. Каждое решение также заносится в оракул прогнозов, чтобы его реальную стоимость и результат можно было зафиксировать после выполнения задачи.
$ precc route "fix the broken parser"
category : fix (capability floor 0)
→ model : anthropic/claude-haiku-4-5 [Measured, confidence 0.60]
est. cost : $0.0096 (12000 tok)
reason : measured cheapest-capable for `fix` (by cost): claude-haiku-4-5
prediction : #42 (seeded; learner will auto-close after the task runs)
Денежная экономия
precc savings добавляет денежный раздел всякий раз, когда маршрутизированные задачи завершены. Для каждой маршрутизированной задачи он оценивает фактически потраченные токены по тарифу выбранной модели и сравнивает их с базовым уровнем модели по умолчанию — токены фиксированы, меняется только цена. Это представление «сокращай стоимость, а не только токены»; раздел остаётся скрытым, пока не появятся реальные данные о маршрутизации, поэтому он никогда не показывает сфабрикованных строк.
$ precc savings
Routing cost (USD) — baseline: always claude-opus-4-5
claude-haiku-4-5 : 1 task(s) $ 0.0096 chosen vs $ 0.0600 baseline
claude-sonnet-4-6 : 1 task(s) $ 0.1200 chosen vs $ 0.2000 baseline
total : 2 task(s) $ 0.1296 chosen vs $ 0.2600 baseline
→ saved $0.1304 (50.2% of baseline spend)
Цикл обратной связи
Маршрутизация совершенствует сама себя: route → execute → record → retrain. Каждое маршрутизированное решение заносится в оракул; фоновый демон precc-learner извлекает завершённое сообщение, фиксирует фактические токены, модель и успешность и закрывает строку. По мере заполнения таблицы для каждой (model, category) маршрутизатор переходит от априорных предположений «самый дешёвый из способных» к измеренным выборам, а предсказатель токенов получает измерение по каждой модели.
Исследование
Чтобы не эксплуатировать одну дешёвую модель бесконечно на устаревших данных, маршрутизатор может намеренно опробовать недостаточно исследованную ячейку (model, category) перед жадным выбором. Исследование включается по желанию, детерминировано (без случайности — хук должен быть воспроизводимым) и ограничено: оно никогда не пересекает порог возможностей или измеренной успешности, а предел сожаления по цене не даёт ему отклониться к гораздо более дорогой модели.
# ~/.config/precc/odysseus.toml
explore_n_min = 3 # sample each (model, category) cell ~3× before trusting it
explore_eps = 1.0 # allow up to 2× the cheapest price while exploring
Измерено, а не предположено
Модель исключается за несоответствие минимальному уровню успешности только при наличии измеренного доказательства этого — неизмеренная модель никогда не исключается по угаданному числу. При отсутствии данных для ячейки маршрутизатор возвращается к консервативному априорному предположению «самый дешёвый из способных» и помечает решение как холодный старт, так что вызывающая сторона всегда знает, опирается ли выбор на доказательства или на априорное предположение.