SurfCap-α — алгоритм, которым наш LLM-шлюз выбирает модель, когда клиент присылает model=auto. Простые запросы он отправляет на дешёвую модель за 0.7 мс в среднем, а запросы с персональными или конфиденциальными данными не выпускает за контур: за 19 часов работы текущего процесса шлюза так на резидентных моделях остались 176 из 230 самых рискованных запросов. Решение принимают детерминированные правила, а ML-слои могут только повысить класс модели, но не понизить его.
Если коротко — для бизнеса
- Дешёвые вопросы — дешёвой модели. Больше половины запросов (56.9%) ушли на дешёвый класс вместо привычного «всё на самую сильную».
- Данные не уходят наружу. Запросы с персональными или конфиденциальными данными остаются на моделях внутри контура, и никакая оптимизация стоимости это правило не отменяет.
- Каждое решение объяснимо одной строкой. По заголовку ответа видно, почему выбрана именно эта модель.
- Честная оговорка: сравнения качества и стоимости с режимами «всегда сильная» и «всегда дешёвая» пока нет — для него ещё не накоплена разметка.
О цикле «LLM-шлюз»
Две статьи о собственном LLM-шлюзе компании. «Мы» — это автор и AI-агенты, которым он делегировал часть исследований и правок. Компания обезличена, цифры настоящие.
- SurfCap-α: как семантический роутер выбирает модель ← вы здесь
- Guardrails в LLM-шлюзе: почему Shieldstral
Термины за минуту
- LLM-шлюз — единая точка входа между клиентами (чатами, агентами, интеграциями) и языковыми моделями: маршрутизация, проверки, учёт, трассировка.
model=auto— клиент не выбирает модель сам, а поручает выбор шлюзу.- Класс модели и тир — класс описывает, какая модель нужна (дешёвая, кодовая, с длинным контекстом, «умная», самая сильная, мультимодальная, резидентная). Тир T0–T3 — уровень требований запроса, из которого выводится класс.
- Резидентная модель — модель, развёрнутая внутри контура компании. Данные к ней не покидают периметр.
- ПДн — персональные данные.
- Routing и cascading — routing решает, какую модель вызвать, до генерации; cascading сначала спрашивает дешёвую модель и при неудачном ответе идёт к дорогой.
- α-порог — порог на вероятность того, что сильная модель ответит лучше слабой. Выше α — дешевле и рискованнее.
- Capability-головы — лёгкие классификаторы, оценивающие, нужны ли запросу рассуждение, код, отладка или инструменты.
- Circuit breaker — предохранитель: сбойный провайдер временно выводится из ротации.
- Fallback — переключение на запасной вариант при ошибке.
- p50 — медиана, например задержки.
Задача и исходные условия
Кому особенно полезен раздел:Бизнес и продуктАрхитекторы
SurfCap-α — алгоритм автоматического выбора модели в собственном LLM-шлюзе: клиент присылает model=auto, а шлюз за доли миллисекунды решает, какой класс модели нужен этому запросу. Название — аббревиатура слоёв: Surface heuristics → Capability heads → α-preference, плюс исполнение с перескоками и каскад как страховка.
Исходные условия были типичными для корпоративного шлюза:
- Пул из нескольких классов моделей: дешёвая быстрая, кодовая, с длинным контекстом, «умная», самая сильная, мультимодальная — плюс резидентные модели, развёрнутые внутри контура.
- Часть запросов содержит персональные данные или конфиденциальную информацию. Такие запросы нельзя отправлять внешним провайдерам ни при каких оптимизациях.
- До шлюза каждый клиент сам выбирал модель. Типичный сбой — «всё на самую сильную»: дорого и медленно на простых вопросах.
- Первая версия маршрутизации жила на готовом прокси, и его автоматический fallback однажды увёл трафик на дорогой класс. Это стало аргументом за собственный шлюз с явной, объяснимой логикой выбора.
Требования к роутеру сформулировали так:
- решение до первого HTTP-вызова — меньше 1 мс;
- каждое решение объяснимо одной строкой;
- дорогие ML-компоненты опциональны и могут только повышать класс, но не понижать.
Что говорит литература
Кому особенно полезен раздел:ML и исследователиАрхитекторы
Маршрутизация между LLM делится на два семейства: решение до генерации (routing) и решение после неё (cascading). Эта таксономия и каталог дешёвых признаков запроса хорошо изложены в двух обзорах [7] [8].
Routing до генерации. Hybrid LLM [2] обучает лёгкий энкодер предсказывать разрыв качества между малой и большой моделью. RouteLLM [1] сводит задачу к одной величине — вероятности того, что сильная модель ответит лучше слабой, — и порогу α над ней:
Ручка α напрямую задаёт компромисс: выше α — дешевле и рискованнее, ниже α — ближе к «всегда сильная». HyDRA [6] идёт дальше двух моделей: четыре сигмоидные «головы способностей» (reasoning, code, debug, tools) поверх ModernBERT сопоставляются с профилями моделей в гетерогенном пуле; медиана на CPU — 86 мс.
Cascading после генерации. FrugalGPT [3] спрашивает дешёвую модель, оценивает ответ и при неудаче идёт к дорогой. AutoMix [4] заменяет внешний оценщик самопроверкой модели. Унифицирующая работа [5] показывает, что каскад выигрывает только тогда, когда оценщик качества достаточно точен.
ML-исследователю
Вывод [5] стал ключевым для нашего дизайна: без откалиброванного оценщика каскад лишь удваивает стоимость плохих ответов. Поэтому каскад у нас — страховка, выключенная по умолчанию, а не первый шаг.
Из обзора вытекал и главный инженерный вопрос: все обучаемые роутеры требуют размеченных пар «запрос → какая модель ответила лучше» на своём трафике. На старте таких данных нет, а решать нужно с первого дня.
Устройство SurfCap-α
Кому особенно полезен раздел:АрхитекторыИнженеры
Решение принимается последовательными слоями, и каждый следующий слой может только поднять тир, но не опустить его. Единственное исключение — мягкий бюджет, и даже он не может нарушить инвариант резидентности.
Верхний ряд выбирает тир и может только поднимать его. Нижний ряд ограничивает и исполняет решение: провайдер выбирается внутри класса, сбойный уходит на паузу (circuit breaker, ~30 с), а каскад срабатывает как страховка уже после ответа.
Слой 1. Surface — поверхностные признаки
Кому особенно полезен раздел:ИнженерыАрхитекторы
Из текста и полей запроса извлекаются дешёвые признаки: длина в токенах, маркеры кода, математики, отладки, вызова инструментов, мультимодальности, «мешки намерений» и флаги риска (юридический, медицинский, персональные данные, безопасность, конфиденциальность). Регулярные выражения двуязычные и включают отраслевой словарь и ссылки на профильные законы. Из структуры запроса берутся признак «несколько намерений сразу» и глубина цепочки вызовов инструментов.
Правила проверяются сверху вниз, и побеждает первое совпадение (first match, highest tier). Скоры не суммируются: правило либо сработало, либо нет, поэтому решение всегда объяснимо.
| Тир | Условие | Класс модели |
|---|---|---|
| T3 | есть флаг риска | самая сильная; при ПДн или конфиденциальных данных — резидентная (с файлом — резидентная мультимодальная) |
| T2 | отладка, инструменты, несколько намерений или ≥ 1200 токенов | «умная»; если сработала только длина — с длинным контекстом |
| T1 | маркеры кода или математики | кодовая |
| T0 | всё остальное | дешёвая |
Мультимодальный вход на любом тире переключает класс на vision-модель, но сам по себе тир не поднимает.
Слой 2. Capability — головы способностей
Кому особенно полезен раздел:ML и исследователиИнженеры
Слой перенят из HyDRA [6]: если оценка головы превышает порог, тир поднимается до минимального тира профиля. Профили заданы в YAML: code ≥ 0.5 → T1; debug ≥ 0.5, tools ≥ 0.5, reasoning ≥ 0.7 → T2. Понижение запрещено на уровне кода, а не соглашения:
Слой 3. α-preference
Кому особенно полезен раздел:ML и исследователиАрхитекторы
Порог RouteLLM [1] применяется только на одной границе — между T1 и T2. Именно там эвристики неувереннее всего: код ли это на пару строк или архитектурный вопрос. T0 и T3 α не трогает: простые запросы дешевле не сделать, а рискованные нельзя удешевлять. По умолчанию α = 0.5.
Инвариант резидентности
Кому особенно полезен раздел:Бизнес и продуктАрхитекторы
Если в запросе есть персональные или конфиденциальные данные, ни capability, ни α, ни бюджет не могут увести его с резидентной модели. В причину решения дописывается residency:guard.
Архитектору
Инвариант резидентности перекрывает любую оптимизацию. В литературе по маршрутизации такого ограничения нет: там оптимизируется пара «качество — стоимость», а не место обработки данных. В корпоративном шлюзе это третья ось, и её нельзя выражать весом в общей функции потерь — только жёстким правилом поверх неё.
Слой 4. Мягкий бюджет
Кому особенно полезен раздел:Бизнес и продуктИнженеры
Каждый класс стоит условные единицы: дешёвая — 1, кодовая — 2, длинный контекст — 4, «умная» и vision — 5, самая сильная и резидентные — 6. При превышении мягкого лимита запрос понижается до дешёвого класса ещё до первого вызова.
Исполнение и каскад
Кому особенно полезен раздел:ИнженерыАрхитекторы
Класс модели и конкретный провайдер — разные слои. При ошибках 400, 429 и 5xx шлюз перескакивает на другого провайдера того же класса, а сбойный провайдер уходит на паузу примерно на 30 с. Так сбой не меняет ни качество, ни стоимость ответа. Каскад в духе FrugalGPT и AutoMix реализован, но выключен по умолчанию — именно по аргументу [5] о точности оценщика.
Каждое решение записывается одной строкой в заголовке ответа и в трассировке:
heuristic:T1;capability:debug→T2;preference:p=0.80>=α=0.50;budget:degrade_to=cheap;cascade
Реализация
Кому особенно полезен раздел:Инженеры
Шлюз написан с нуля на FastAPI, без готового прокси. Правила тиров, регулярные выражения, профили голов и α живут в YAML, поэтому политику маршрутизации можно менять без релиза. Движок правил знает четыре предиката (равенство, «не меньше», «не пусто», пересечение множеств) и их комбинации any_of / all_of.
Путь запроса:
- Детектор секретов проверяет вход. В режиме наблюдения он добавляет флаги риска, которые дальше влияют на тир.
- SurfCap-α выбирает класс: признаки → правила → capability → α → резидентность.
- Бюджет при необходимости понижает класс.
- Параллельно запускается проверка guardrails (о ней — вторая статья цикла); её результат нужен только перед вызовом провайдера.
- Выбор провайдера внутри класса, исполнение с перескоками, пассивный circuit breaker и активные health-пробы.
- Причина решения уходит в заголовок
X-Route-Decision, в структурный лог и в дерево трассировки.
Бюджет задержки заложен на этапе проектирования: признаки и правила — меньше 1 мс до первого HTTP-вызова; capability-головы на CPU — 50–100 мс (ориентир — 86 мс у HyDRA), α-оценщик — ещё 10–30 мс. Именно поэтому ML-слои опциональны: они стоят на два порядка дороже эвристик и оправданы только там, где эвристики ошибаются.
Данные для калибровки. Здесь проходит граница между планом и боем. Интерфейсы capability и α реализованы и покрыты тестами с подставными оценщиками, но весов моделей в бою нет: для обучения нужна собственная разметка. Оценщик качества для каскада пока тоже заглушка. Источник разметки уже есть: каждое решение с причиной пишется в журнал запросов, а скрипт офлайн-оценки умеет сравнивать режимы «всегда дешёвая», «всегда сильная», «только эвристики», «+capability», «+α» и «+каскад».
Что сейчас работает в бою
Решение принимают эвристики, бюджет и инвариант резидентности. Capability-головы, α-оценщик и каскад реализованы, но выключены, пока не накопится разметка. Поскольку головы и α могут только повышать тир, их включение не может ухудшить качество — только стоимость.
Результаты и ограничения
Кому особенно полезен раздел:Бизнес и продуктML и исследователи
За 19 часов работы текущего процесса через model=auto прошло 826 запросов. Почти половина из них ушла не на дешёвую модель, а больше четверти — в T3 из-за флагов риска. Цифры — из Prometheus-счётчиков шлюза; задержка — среднее время всей стадии маршрута (детектор секретов, признаки, правила, бюджет) без подсчёта токенов и вызова модели.
| Тир | Запросов | Доля | Выбор маршрута, мс (среднее) |
|---|---|---|---|
| T0 — дешёвая | 470 | 56.9% | 0.7 |
| T1 — кодовая | 2 | 0.2% | 7.7 |
| T2 — «умная» / длинный контекст | 124 | 15.0% | 34.2 |
| T3 — самая сильная / резидентные | 230 | 27.8% | 55.5 |
Из этого следуют три вывода.
- Резидентность — самый заметный эффект. 176 из 230 запросов T3 ушли на резидентные модели. Без инварианта они бы ушли во внешнюю сильную модель.
- Дешёвый путь укладывается в бюджет. Для T0 выбор маршрута занимает в среднем 0.7 мс при цели меньше 1 мс. У сложных классов задержка в десятки раз выше, и это ожидаемо: туда попадают длинные документы, а регулярные выражения проходят весь текст. Разложить эти десятки миллисекунд по стадиям ещё предстоит. На фоне секунд генерации они незаметны.
- Граница T1↔T2 почти не встречается. В T1 попало всего 2 запроса: правила T2 стоят выше, и кодовые запросы с отладкой или длинным контекстом сразу уходят в T2. Значит, для нашего трафика α на этой границе даст мало. Перспективнее вернуть часть T2 в более дешёвый класс.
Ограничения
- Офлайн-сравнения с режимами «всегда сильная» и «всегда дешёвая» по качеству и стоимости пока нет: нет размеченного набора.
- Эвристики проверены только синтетическим набором из 30 кейсов на флаги риска (все 30 проходят) и смоук-тестом из 8 сценариев по тирам.
- Регулярные выражения улавливают только то, что в них заложено, поэтому флаги риска скорее избыточны, чем недостаточны. Для резидентности это правильный перекос, для стоимости — нет.
Что здесь собственное, а что заимствовано
Кому особенно полезен раздел:ML и исследователиАрхитекторы
Отдельные техники взяты из литературы: α-порог, головы способностей, каскад с самопроверкой, каталог признаков. Собственный вклад — в том, как они скомпонованы:
- детерминированные правила идут первыми, ML может только поднять тир, а каскад служит страховкой, а не первым шагом;
- α применяется только на одной границе тиров;
- класс модели отделён от провайдера, перескоки идут строго внутри класса;
- мягкий бюджет считается в условных единицах;
- инвариант резидентности перекрывает любую оптимизацию;
- каждое решение объясняется одной строкой.
Дальше по циклу — guardrails: проверка входа, которая идёт параллельно с выбором маршрута.
Литература
Кому особенно полезен раздел:ML и исследователи
- Ong I. et al. RouteLLM: Learning to Route LLMs with Preference Data. arXiv:2406.18665.
- Ding D. et al. Hybrid LLM: Cost-Efficient and Quality-Aware Query Routing. arXiv:2404.14618.
- Chen L., Zaharia M., Zou J. FrugalGPT: How to Use Large Language Models While Reducing Cost and Improving Performance. arXiv:2305.05176.
- Aggarwal P. et al. AutoMix: Automatically Mixing Language Models. arXiv:2310.12963.
- Dekoninck J. et al. A Unified Approach to Routing and Cascading for LLMs. arXiv:2410.10347.
- Garg A. et al. HyDRA: Hybrid Dynamic Routing Architecture for Heterogeneous LLM Pools. arXiv:2605.17106.
- Varangot-Reille C. et al. Doing More with Less: A Survey on Routing Strategies for Resource Optimisation in Large Language Model-Based Systems. arXiv:2502.00409.
- Moslem Y. et al. Dynamic Model Routing and Cascading for Efficient LLM Inference: A Survey. arXiv:2603.04445.
Названия и первые авторы сверены с arXiv API 25 октября 2026.