Routing DSL: составьте панель моделей, которая мыслит как Fable 5
В течение двух лет стратегия «больше интеллекта» сводилась к «жди следующую модель». Мы считаем, что это неправильная единица прогресса. Граница — это не единая контрольная точка, а панель. Дайте трём хорошим моделям одну и ту же сложную задачу, позвольте им не соглашаться друг с другом, выступите арбитром между ответами — и панель победит любого из своих членов. Часто она побеждает следующую модель по ценовой шкале.
Routing DSL — это то, как вы строите эту панель. Это программируемая стратегия маршрутизации — YAML + CEL — которая превращает вашу конечную точку OrcaRouter в граф вывода: маршрутизация по сложности, маршрутизация по задаче, разветвление на несколько моделей одновременно, оценка или голосование по их результатам, откат при низкой уверенности и настройка всего этого под стоимость, задержку или качество. Вы пишете правила; шлюз компилирует и выполняет их на каждом запросе за ~5 мс.
Этот пост — инженерный обзор: грамматика, переменные, по которым можно ветвиться, четыре арбитра, каскад и полный набор производственных правил в конце.
Сначала результат
Два иллюстративных эталона. (Числа иллюстративны — они призваны показать форму эффекта, а не цитироваться как официальные оценки.)
Сравнение фронтиров — сложно-маршрутизированная DSL-конечная точка против одиночного фронтира:

Панели Fusion против одиночных моделей — оценено на 93 из 100 задач (от OpenRouter):

Три вещи, на которые стоит смотреть:
Каждая объединённая панель превосходит каждого из своих собственных участников. Opus 4.8 + GPT-5.5 (~67.5%) превосходит как Opus solo (~58.5%), так и GPT-5.5 solo (~60%) на 7–9 пунктов. Разногласие — это сигнал; арбитраж его использует.
Fusion достигает следующего уровня. Три разные панели пересекают Fable 5 solo (~65.5%) используя только модели ниже его.
Вам не нужны дорогие подписки.Opus + Opus-самослияние (~65,5%) соответствует Fable 5 с одной моделью и сэмплером. Набор дешёвых моделей — Gemini 3 Flash + Kimi K2.6 + DeepSeek V4 Pro (~64,5%) — немного уступает Fable 5 при значительно меньшей стоимости за токен. В этом и заключается суть: покупать интеллект с помощью топологии, а не за счёт следующего ценового уровня.
Маршрутизирующий DSL — это поверхность управления, которая позволяет тратить эту топологию только там, где это оправдано: дешёвые модели на лёгкие 80%, фьюжн-панель на сложный хвост.
Грамматика за 30 секунд
Набор правил — это версия, список правил и обязательное значение по умолчанию. Правила вычисляются сверху вниз; первый when: который истинен, выигрывает. Нет when: означает "всегда совпадает."
версия: 1
rules:
- id: only_rule
use: { model: "claude-sonnet-4-6" }
default:
delegate: balancedПараметр when: — это CEL булево выражение — изолированное, допускающее только регулярные выражения RE2, без циклов, без ввода-вывода, вычисляемое за микросекунды, с единым сроком выполнения в 5 мс, общим для всего набора правил. Параметр use: — это эффект: он определяет, куда направляется запрос и как он настраивается. Ограничения намеренно малы (≤30 правил, ≤16 КиБ исходного кода, ≤200 символов на параметр when:), чтобы набор правил оставался проверяемым.
Примитив 1 — маршрут по сложности и заданию
Дистрибьютор классифицирует каждый запрос перед маршрутизацией и предоставляет возможности CEL. Вы можете выполнять ветвление непосредственно по ним:
версия: 1
rules:
- id: hard_reasoning
when: difficulty > 0.8
use:
model: "claude-opus-4-8"
reasoning_effort: "high"
thinking_budget_tokens: 32000
- id: code_path
when: task_class == "code" && code_keyword_density > 0.5
use: { model: "gpt-5.5" }
- id: cheap_chat
when: difficulty < 0.3
use: { model: "gemini-3-flash" }
default:
delegate: balancedПеременные, которые вы можете прочитать в when: (сокращённо — см. полную документацию):
Примеры групп
Форма запроса
request.input_tokens, request.output_max_tokens, request.stream, request.vision, request.message_count, request.has_toolsКлассификация
task_class (chat/code/agent/vision/audio/rag/creative), difficulty (0.0–1.0), code_keyword_density, reasoning_cue_count, log_prompt_tokens, tool_countСессия
agent_state.turn, agent_state.tools_used, agent_state.has_edited, agent_state.last_test_failed, agent_state.consecutive_errors, agent_state.models_triedКонтекст
headers["x-…"], user.group, token.name, time.hour, workspace.id
…plus six macros for the things regex-over-payload is good at: system_prompt_matches(re), user_message_matches(re), tool_definitions_include(name), tool_calls_present_any([…]), tool_results_from_any([…]), header_matches(name, re).Любая конечная точка может иметь параметры для каждого вызова, которые переводятся в нативные параметры каждого провайдера адаптером-ретранслятором: reasoning_effort (низкий/средний/высокий), thinking_budget_tokens (1024–64000), samples (1–16), temperature (0.0–2.0), а также защищенные дени-листом param_override / header_override. Этого уже достаточно, чтобы построить конечную точку с маршрутизацией по сложности из Таблицы A: дешевая модель для легких задач, Opus с бюджетом на размышления для сложных.
Примитив 2 — развёртка на панель (слияние)
Это источник прироста производительности бенчмарка. Параллельный эффект отправляет запрос к 2–5 ветвей одновременно, затем арбитр решает, что в итоге видит клиент:
- id: hard_tail_panel
when: difficulty > 0.7 && task_class == "agent"
use:
parallel:
- { model: "anthropic/claude-opus-4-8", reasoning_effort: "high" }
- { model: "openai/gpt-5.5", thinking_budget_tokens: 16000 }
- { model: "google/gemini-3.1-pro", temperature: 0.3 }
arbiter:
strategy: best_of_n
model: "anthropic/claude-sonnet-4-6" # the judge
template: judge_code
max_latency_ms: 120000
on_disagreement: # majority-only escape hatch
model: "anthropic/claude-opus-4-8"
reasoning_effort: "high"Четыре стратегии арбитра, каждая из которых дает разный ответ на вопрос "чей вывод побеждает?":
первый — разгоняйте ноги, обслуживайте первый успех, отменяйте проигравших. Оптимизирует задержку (вы получаете самый быстрый из N).
большинство — структурированное голосование по выходам ветвей, без дополнительного вызова модели. Когда ветви расходятся без строгого большинства, опциональная ветка on_disagreement: повторно отправляет свежую, более сильную попытку вместо того, чтобы служить разрешением равенства. Оптимизирует устойчивость для задач с каноническим ответом.
best_of_n — это LLM судья читает все кандидаты и ранжирует их. Это конфигурация «Opus + GPT-5.5 → judge» из таблицы B. Оптимизирует качество в открытых задачах; при ошибке судьи использует запасной вариант first-successful.
тесты_пройдены — основанный_на_выполнении: предоставлять кандидата, чей патч действительно заставляет набор тестов проходить. Без догадок судьи — решение принимает тестовая среда. Это самый сильный арбитр для работы с кодом/агентом. Верификатор находится за пределами шлюза (подключен через VerifierProvider); если ни один не подключен, он понижается до первого успешного.
max_latency_ms (1000–600000, по умолчанию 120000) ограничивает разветвление, чтобы один медленный участок не мог задержать ответ — отстающие отбрасываются. Вложение parallel внутрь parallel отклоняется на этапе lint; панель намеренно имеет один уровень глубины.
Примечание о доступности: N-way fan-out рантайм ограничен серверным флагом ROUTING_DSL_ENSEMBLE_RUNTIME в то время как per-leg billing закалено на staging — поэтому fusion находится в статусе preview, not GA. При выключенном флаге правило parallel: чисто обслуживает свой первый leg, так что вы можете создавать и shadow свои панели уже сегодня и включать их, когда fusion появится в вашем регионе.
Примитив 3 — запасные варианты и каскады уверенности
Разветвление тратит N× заранее. Один каскад тратит дополнительно только когда первый ответ кажется неверным. После ответа, on_low_confidence: оценивает сигналы и, если один срабатывает, повторно отправляет к более сильному назначению:
- id: agent_with_safety_net
when: task_class == "agent"
use:
pool: "@pool:fast"
on_low_confidence:
signals: [patch_invalid, self_doubt, next_turn_test_failed]
threshold: { low_logprob: -1.5 }
use:
model: "claude-opus-4-8"
reasoning_effort: "high"Сигналы: patch_invalid (diff не проходит проверку git apply --check), self_doubt (набор регулярных выражений для уклончивых фраз), low_logprob (средний логпроб токена ниже порога, если провайдер его раскрывает), и next_turn_test_failed (перекрестная защелка — промпт этого витка содержит форму тестов, провалившихся на прошлом витке). Каскады по замыслу имеют глубину 1. Сочетайте их с agent_state.models_tried, чтобы получить разнообразие при повторной попытке — никогда не отправляйте исправление модели, которая только что ошиблась.
Настройка параметров: стоимость, задержка, качество
Один и тот же DSL выражает все три цели; вы выбираете по правилу:
Стоимость — делегировать: самый дешевый, оставляйте дешевую модель на легком хвосте, а разветвление (fan-out) резервируйте для сложности > 0.7. Дешевая панель Table B (~64.5% ≈ Fable 5 solo) является доказательством существования: объединение маленьких моделей может заменить передовую модель за долю стоимости за токен. Будьте трезвы, однако — объединение использует "выставлять счет за каждую ногу" модель: трехногая панель best_of_n выставляет счета трем кандидатам плюс судье. Экономика работает, потому что вы (a) разветвляетесь только на сложном меньшинстве запросов и (b) объединяете более дешёвых членов, чем передовая модель, которую вы заменяете.
Задержка — арбитр: { strategy: first } с жестким ограничением max_latency_ms дает вам самый быстрый из N с жестким потолком.
Качество — best_of_n для задач открытого типа, tests_pass когда есть набор тестов для опоры. samples и thinking_budget_tokens дают больше в рамках одного шага.
Эксплуатация без нарушения работы продакшена
Изменения маршрутизации пугают, поэтому DSL поставляется с предохранительными рельсами, которые ожидает SRE:
Линтинг при каждом сохранении — схема, проверка типов CEL (каждое when: должно вычисляться в bool), разрешение ссылок, диапазоны ручек, списки запрета заголовков/параметров. Ошибки возвращаются как {line, column, message, rule} и отображаются в виде значков на полях в редакторе.
Пробный прогон — отправляет синтетический запрос (task_class, difficulty, agent_state, …) и возвращает соответствующее правило, определенный эффект и время оценки до того, как что-либо будет отправлено.
Теневой режим — в течение 24 ч после первого сохранения DSL оценивается, но не используется; теневой журнал записывает предполагаемые выборки, а консоль показывает разницу (процент измененных маршрутов, прогнозируемое изменение дневной стоимости, счетчики срабатываний по каждому правилу).
Canary — ползунок трафика от 0 до 100. Увеличивайте с 5 → 25 → 50 → 100, наблюдая за метриками каждого среза; откатите, переместив ползунок на 0.
Аудит + откат — каждое сохранение/откат записывает строку аудита в той же транзакции; конкурентные правки получают 409 с текущей версией, так что вы повторяете попытку на основе свежего состояния.
Тестовые примеры, повтор трассировки и представление AI "объяснить этот набор правил" дополняют его. Вы найдете это в панели управления в разделе маршрутизация → стратегия → DSL.
Полный набор правил
Дешево на легком, средне на среднем, оценочная фьюжн-панель на сложном агентном хвосте, с каскадом уверенности внизу:
версия: 1
rules:
- id: trivial
when: difficulty < 0.3 && !has_tools
use: { model: "gemini-3-flash" }
- id: standard
when: difficulty < 0.7
use:
model: "gpt-5.5"
on_low_confidence:
signals: [self_doubt, low_logprob]
use: { model: "claude-opus-4-8", reasoning_effort: "high" }
- id: hard_agent_panel
when: difficulty >= 0.7 && task_class == "agent"
use:
parallel:
- { model: "anthropic/claude-opus-4-8", reasoning_effort: "high" }
- { model: "openai/gpt-5.5", thinking_budget_tokens: 16000 }
- { model: "google/gemini-3.1-pro" }
arbiter:
strategy: tests_pass # execution-grounded; judged fallback if no harness
max_latency_ms: 180000
on_disagreement:
model: "claude-opus-4-8"
reasoning_effort: "high"
default:
delegate: balancedЭто та конечная точка, которая находится на вершине Таблицы A — не потому, что она нашла лучшую модель, а потому, что она расходует правильную модель на правильный запрос и объединяет панель именно там, где панель выигрывает.
Начать написание
Следующий скачок в возможностях не должен ждать следующей контрольной точки. Это граф, который вы можете написать сегодня днем: маршрутизация по сложности, разветвление на сложном хвосте, оценка или тестирование результатов, каскадирование при падении уверенности.
Документация: https://docs.orcarouter.ai/routing/routing-dsl
ПИ: маршрутизация → Создать роутер -> Стратегия маршрутизации → DSL (эксперт)
Фронтир — это панель. Собери свою.
