Каскад моделей LLM: дешёвая модель сначала, сильная — по эскалации
Как устроить каскад: дешёвая модель отвечает первой, сложные случаи уходят сильной. Код на Python, калибровка порога и расчёт стоимости по формуле.
5 мин · · разработка · экономия
Каскад моделей LLM — приём для потоков однотипных запросов: классификации обращений, извлечения полей из документов, модерации. Большую часть запросов обрабатывает дешёвая модель, а к сильной уходят только те, где ответ не прошёл проверку или модель не уверена. Ниже — как устроить такую схему на Python через один ключ Zukko, как подобрать порог и как посчитать стоимость по формуле, а не на глаз.
Как работает каскад моделей LLM
Схема из трёх частей:
- Первая попытка — дешёвая модель. Например,
deepseek-v4.1-flash($0.013 за 1M входа, $0.038 за 1M выхода). - Проверка ответа. Код решает, принять ответ или эскалировать. Сигналы для эскалации:
- ответ не разбирается как JSON или не соответствует схеме;
- значение вне допустимого набора (метка, которой нет в списке);
- нарушено бизнес-правило (сумма позиций не равна итогу, дата в будущем);
- самооценка уверенности ниже порога.
- Вторая попытка — сильная модель. Например,
claude-opus-5-5($0.4 / $2 за 1M). Если и её ответ не прошёл проверку, запрос уходит на ручной разбор.
Про самооценку уверенности стоит сказать честно: число, которое модель пишет о себе, — слабый сигнал, и откалибровано оно может быть плохо. Поэтому порог нельзя выбирать наугад, его нужно подобрать на размеченной выборке (ниже показано как). Формальные проверки — схема, допустимые значения, бизнес-правила — надёжнее, их стоит ставить первыми.
Обе модели доступны по одному ключу и одному адресу: Zukko сам направляет запрос нужному провайдеру, менять клиент не нужно.
Код на Python
Пример: классификация обращений в поддержку по четырём темам.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_...")
CHEAP = "deepseek-v4.1-flash"
STRONG = "claude-opus-5-5"
LABELS = {"billing", "bug", "feature_request", "other"}
SYSTEM = (
"Определи тему обращения клиента. Ответь только JSON без пояснений: "
'{"label": "billing" | "bug" | "feature_request" | "other", '
'"confidence": число от 0 до 1}'
)Что здесь важно:
- Обе модели вызываются через OpenAI SDK с base URL
https://api.zukko.pro/v1; шлюз сам конвертирует запрос к Claude. - Сильная модель получает тот же вход, что и дешёвая. Можно передать ей и ответ первой модели, но тогда вход станет больше — учтите это в расчёте.
- Для Claude в OpenAI-формате весь вход оплачивается по цене входа, кэш не учитывается. Для коротких запросов, как здесь, это неважно. Если у сильной модели длинный общий системный промпт, вызывайте её через Anthropic SDK (
Anthropic(base_url="https://api.zukko.pro", ...)): в Anthropic-формате чтение кэша оплачивается по своей, более низкой цене.
Подробнее о клиенте на Python — в документации.
Как подобрать порог
Порог уверенности определяет долю эскалаций и долю ошибок среди принятых ответов дешёвой модели. Подберите его на 200–500 обращениях с известной правильной меткой:
def calibrate(samples: list[tuple[str, str]], thresholds=(0.5, 0.6, 0.7, 0.8, 0.9)):
answers = [(ask(CHEAP, text), gold) for text, gold in samples]
for t in thresholds:
accepted = [(a, gold) for a, gold in answers if is_valid(a) and a["confidence"] >= t]
r = 1 - len(accepted) / len(answers)
errors = sum(a["label"] != gold for a, gold in accepted)
err_rate = errors / len(accepted) if accepted else 0.0
print(f"порог {t}: эскалаций {r:.0%}, ошибок среди принятых {err_rate:.1%}")Выберите самый низкий порог, при котором доля ошибок среди принятых ответов вас устраивает. Получившаяся доля эскалаций r — это и есть число, которое нужно для расчёта стоимости. Через пару недель работы повторите калибровку на свежих данных: поток запросов меняется.
Сколько стоит каскад: формула
Обозначения:
- C₁ — средняя стоимость запроса к дешёвой модели;
- C₂ — средняя стоимость запроса к сильной модели;
- r — доля запросов, ушедших на эскалацию (от 0 до 1).
Эскалированный запрос оплачивается дважды: сначала дешёвая попытка, потом сильная. Поэтому:
стоимость каскада на запрос = C₁ + r × C₂
всё на сильной модели = C₂
каскад дешевле, если r < 1 − C₁ / C₂
Пример на условном потоке
100 000 обращений, в каждом в среднем 800 токенов на входе (системный промпт плюс текст) и 150 на выходе.
- C₁ (
deepseek-v4.1-flash) = 800 × $0.013 / 1 000 000 + 150 × $0.038 / 1 000 000 = $0.0000104 + $0.0000057 = $0.0000161 - C₂ (
claude-opus-5-5) = 800 × $0.4 / 1 000 000 + 150 × $2 / 1 000 000 = $0.00032 + $0.0003 = $0.00062
На 100 000 запросов: дешёвая модель — $1.61, сильная — $62.00. Стоимость каскада = $1.61 + r × $62.00:
| Доля эскалаций r | Каскад | Всё на Opus 5.5 | Разница |
|---|---|---|---|
| 10% | $1.61 + $6.20 = $7.81 | $62.00 | $54.19 |
| 30% | $1.61 + $18.60 = $20.21 | $62.00 | $41.79 |
| 50% | $1.61 + $31.00 = $32.61 | $62.00 | $29.39 |
Точка безубыточности: r = 1 − 0.0000161 / 0.00062 ≈ 0.974. Пока эскалируется меньше 97.4% запросов, каскад дешевле, чем отправлять всё на Opus 5.5. Значения r в таблице — примеры для подстановки, а не обещание. Свою долю вы получите из калибровки.
Обратная сторона: если всё отправлять на дешёвую модель, поток стоит $1.61, но тогда неудачные ответы никто не перехватит. Каскад — это доплата за то, чтобы сложные случаи обрабатывала сильная модель.
Три ступени
Между дешёвой и сильной моделью можно поставить среднюю, например claude-sonnet-5. Формула расширяется так:
стоимость на запрос = C₁ + r₁ × C₂ + r₂ × C₃
где r₁ — доля запросов, дошедших до второй ступени, r₂ — до третьей. Третья ступень имеет смысл, только если на калибровке видно, что средняя модель закрывает заметную часть эскалаций.
Что проверить перед запуском
- Качество принятых ответов. Ответы дешёвой модели, прошедшие порог, никто не перепроверяет. Раз в неделю берите случайную выборку из 50–100 принятых ответов и сверяйте вручную или с сильной моделью.
- Фактическую стоимость. Сверьте C₁ и C₂ с реальными списаниями в кабинете, раздел «Использование», или через API истории списаний: фактический размер ответов может отличаться от оценки.
- Ограничения ключа. Для пайплайна удобно завести отдельный ключ с разрешёнными моделями (только две модели каскада) и дневным лимитом в долларах. Создать ключ можно в кабинете.
- Актуальность моделей. Набор и цены меняются: актуальный список —
GET https://api.zukko.pro/v1/modelsили страница «Модели» в кабинете.
Похожая, но другая схема — маршрутизация, когда модель выбирается заранее по типу запроса, а не после проверки ответа. О ней — в статье о стратегии мультимодельной маршрутизации.
Частые вопросы
Чем каскад отличается от маршрутизации?
Маршрутизатор выбирает модель до запроса, по его признакам. Каскад сначала пробует дешёвую модель и решает по её ответу. Их можно совмещать.
Можно ли доверять полю confidence?
Только после калибровки на размеченных данных. Формальные проверки — схема ответа, допустимые значения, бизнес-правила — надёжнее и должны идти первыми.
Какую дешёвую модель взять?
Из самых недорогих в каталоге — deepseek-v4.1-flash и gemini-3.8-flash. Какая лучше подходит вашей задаче, покажет та же калибровка: сравните долю эскалаций и ошибок у обеих. Цены и расчёты по всем дешёвым моделям — в статье о самых дешёвых моделях для массовых задач.
Сколько я сэкономлю?
Это зависит от доли эскалаций r. Посчитайте по формуле C₁ + r × C₂ со своими C₁, C₂ и r, измеренным на калибровке.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Память чат-бота: как хранить историю диалога и не платить за неё дваждыМодель не помнит предыдущих реплик: историю отправляете вы при каждом запросе. Разбираем, как растёт цена диалога и чем её сдерживать.
- LangChain text splitters: как резать текст на чанки правильноКак подобрать размер чанка и перекрытие в RecursiveCharacterTextSplitter, почему считать нужно в токенах и как сверить подсчёт с точным количеством от шлюза.
- LangChain RAG: рабочий пример с моделью через шлюзСтроим простой RAG на LangChain: документы, чанки, векторный поиск и ответ модели через шлюз. Считаем, из чего складывается цена вопроса, и режем лишние токены.
- Агенты opencode: как настроить роли, модели и инструментыСвой агент в opencode — это роль, модель и список разрешений. Показываем конфиг и пример, где рутину делает дешёвая модель, а код правит сильная.