Files
cortiq-gateway/docs/ROUTING.ru.md
T
infosave2007andClaude Opus 4.8 51487e6329 feat: universal LLM gateway with embedded multilingual admin console
- OpenAI-compatible gateway with intelligent routing via cortiq-router (allaigate)
- Embedded build-free admin SPA at /admin: 7 languages (en/ru/de/fr/es/zh/tr),
  light/dark themes, hot config reload (no restart)
- Admin API, per-request statistics + Prometheus /metrics, secret store, playground
- English documentation (primary) with Russian translations (*.ru.md)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 10:51:37 +03:00

163 lines
7.8 KiB
Markdown

*Read this in [English](ROUTING.md).*
# Маршрутизация и стоимость
Как Cortiq Gateway превращает решение роутера (`task_label` + `complexity.tier`) в
выбор конкретной модели из вашего пула — и как сделать это **cost-aware**:
дешёвое локально, дорогое в облаке.
---
## 1. Базовая модель: полоса сложности → пул моделей
cortiq-router возвращает полосу сложности (`low` / `medium` / `high`, настраивается
в роутере). Таблица `[routing]` сопоставляет полосе **упорядоченный список** моделей —
это одновременно приоритет и цепочка fallback.
```toml
[routing]
low = ["local-qwen"] # простое → только локально (бесплатно)
medium = ["gpt-4o-mini", "local-qwen"] # средне → дешёвый хост, откат на локальное
high = ["claude-opus", "gpt-4o-mini"] # сложно → дорогая модель, откат на средн.
default = "gpt-4o-mini" # если роутер недоступен
```
Алгоритм выбора:
```
1. tier := router.complexity.tier (или default-полоса, если роутер недоступен)
2. candidates := routing[tier] (упорядоченный список model_id)
3. для каждого model_id по порядку:
если модель healthy И поддерживает нужные возможности (tools/vision):
выбрать её → выход
4. если все недоступны: следующая полоса вниз/вверх по политике, либо ошибка 503
```
---
## 2. Универсальный пул: локальные дешёвые + хостовые дорогие
Главный сценарий для разработчика: смешать **бесплатную локальную** модель и
**платный облачный** API, и пусть шлюз сам решает, что куда.
```toml
# Локальная модель на vLLM / llama.cpp / Ollama (OpenAI-совместимый endpoint)
[[models]]
id = "local-qwen"
provider = "openai"
base_url = "http://localhost:8000/v1"
model = "qwen2.5-7b-instruct"
cost_tier = "cheap"
price_in = 0.0 # локально → 0
price_out = 0.0
caps = ["tools"] # что умеет (для проверки на этапе выбора)
# Дешёвый облачный
[[models]]
id = "gpt-4o-mini"
provider = "openai"
base_url = "https://api.openai.com/v1"
model = "gpt-4o-mini"
api_key_env = "OPENAI_API_KEY"
cost_tier = "mid"
price_in = 0.15 # $/1M входных токенов
price_out = 0.60
# Дорогой облачный для сложного
[[models]]
id = "claude-opus"
provider = "anthropic"
base_url = "https://api.anthropic.com"
model = "claude-opus-4"
api_key_env = "ANTHROPIC_API_KEY"
cost_tier = "expensive"
price_in = 15.0
price_out = 75.0
caps = ["tools", "vision"]
```
Поскольку `local-qwen` и `gpt-4o-mini` оба `provider = "openai"`, шлюзу не важно,
где модель физически — **локальные серверы уже говорят на OpenAI API**. Это и делает
прокси универсальным.
---
## 3. Cost-aware режим (опционально)
Вместо жёсткой таблицы можно включить выбор по **бюджету/цене** (v0.2):
```toml
[routing.policy]
mode = "cost_aware" # fixed_table | cost_aware
# при cost_aware шлюз для каждой полосы берёт самую дешёвую модель,
# удовлетворяющую минимальному «классу качества» полосы:
min_class = { low = "cheap", medium = "mid", high = "expensive" }
# верхняя граница цены за запрос (страховка от дорогих вызовов)
max_cost_usd_per_request = 0.50
```
Логика: среди моделей не ниже `min_class[tier]` и не дороже лимита выбирается самая
дешёвая доступная. Это даёт «минимально достаточную» модель под сложность задачи.
---
## 4. Pinning и passthrough
- **Passthrough.** `model = "local-qwen"` (реальный id) — без обращения к роутеру,
прямой вызов. Полезно, когда клиент сам знает, что хочет.
- **Pinning профиля.** `model = "cortiq-auto:cost-saver"` — роутинг с конкретным
policy-профилем роутера (реже эскалирует → дешевле).
- **Pinning версии роутера** (v0.4). Чтобы поведение не «плыло» из-за самообучения
роутера, можно зафиксировать `model_version` — агент получает воспроизводимый роутинг.
---
## 5. Извлечение текста для маршрутизации (мультитёрн)
Агентский запрос — это не одна строка, а system + история + tools. Что слать роутеру
на классификацию, настраивается:
```toml
[route]
text_strategy = "last_user" # last_user | concat_all | last_user_plus_system
max_chars = 4000 # усечение длинного контекста (стоимость/DoS)
cache_ttl = "60s" # кэш решения по хэшу текста
profile = "balanced" # дефолтный policy-профиль
```
| Стратегия | Что классифицируем | Когда |
|---|---|---|
| `last_user` | последнее сообщение пользователя | по умолчанию; дёшево и точно для большинства агентов |
| `last_user_plus_system` | system + последнее user | когда роль задаётся системным промптом |
| `concat_all` | весь диалог (усечённый) | мультитёрн со смыслом, размазанным по истории |
---
## 6. Failover и circuit breaker
- **Failover.** При 5xx/таймауте/`overloaded` от провайдера — следующая модель списка.
- **Circuit breaker.** После `breaker.threshold` ошибок подряд модель помечается
«открытой» на `breaker.cooldown`, запросы её минуют. Полупроброс — один пробный
запрос после кулдауна.
- **Router down.** Берётся `routing.default`, запрос не падает (мягкая деградация).
```toml
[breaker]
threshold = 5
cooldown = "30s"
```
---
## 7. Петля обратной связи (опционально, v0.4)
Если включено, шлюз после успешного выполнения может отправить в роутер
`/v1/feedback` сигнал (например, по результату валидации ответа агентом) — роутер
дообучит маску задачи. Так маршрутизация со временем точнее ложится на ваш пул.
```toml
[feedback]
enabled = false
# источник истины задаёт интегратор (например, заголовок X-Cortiq-Correct-Label)
```