Вступ: реальна проблема переплати за LLM
З кожним LLM-запитом ви платите за токени, але не всі запити однаково складні. Простий запит статусу замовлення не потребує потужності GPT-4o, а генерація коду потребує Claude. Постійний виклик однієї топ-моделі для всіх завдань розоряє бюджет: до 5× переплати без покращення якості. LLM Router вирішує цю асиметрію — направляє запит до провайдера та моделі, які оптимально відповідають завданню за вартістю, затримкою та якістю.
У нас за плечима понад 5 років досвіду в AI-інфраструктурі та 30+ проектів із впровадження роутингу для клієнтів з fintech, e-commerce та SaaS. Ми бачили, як компанії платять $3000/міс за GPT-4, хоча 70% їхніх запитів можна віддати на Groq за $200. Типова економія на впровадженні роутера — від $500 до $5000 на місяць.
Які проблеми вирішує LLM Router?
Ми стикаємося з трьома типовими ситуаціями:
- Роздутий бюджет на AI-інфраструктуру. Команди використовують одну дорогу модель для всіх завдань — 60% запитів можна віддати за копійки через Groq або GPT-4o-mini.
- Latency-критичні сценарії. Чат-бот підтримки має відповідати за 200 мс, а не за 3 секунди. Groq з Llama 3 гарантує p99 < 100 мс.
- Якість на складних завданнях. Код, математика, multi-step reasoning — тут дешеві моделі сиплють помилками. Потрібен Claude або o3-mini.
Ми вирішуємо це одним інструментом — централізованим роутером, який знає характеристики кожного провайдера та динамічно обирає найкращий варіант.
Як LLM Router знижує витрати на API?
Rule-based роутер: прозоро та швидко — маршрутизація запитів між
Для проекту SaaS-платформи з 60% простих запитів ми впровадили роутер на основі правил (див. код нижче). Прості запити (<200 символів, без маркерів складності) — на Groq Llama 8B, аналітика — GPT-4o-mini, код — Claude Sonnet. Результат: вартість впала з $450/місяць до $124/місяць (зниження на 72%) при A/B-тесті, де 98% користувачів не помітили різниці. В іншому проекті витрати знизилися з $1200 до $340, а на великому потоці — з $3000 до $720.
from anthropic import Anthropic
from openai import OpenAI
from groq import Groq
from dataclasses import dataclass
from typing import Callable, Optional
import re
@dataclass
class RoutingRule:
name: str
condition: Callable[[str, dict], bool]
provider: str
model: str
reason: str
class LLMRouter:
def __init__(self):
self.openai_client = OpenAI()
self.anthropic_client = Anthropic()
self.groq_client = Groq()
self.rules: list[RoutingRule] = [
# Realtime/простые запросы → Groq (быстро и дёшево)
RoutingRule(
name="simple_chat",
condition=lambda text, meta: len(text) < 200 and not meta.get("complex"),
provider="groq",
model="llama-3.1-8b-instant",
reason="Short simple query — using fast inference",
),
# Code generation → Claude (лучшее качество кода)
RoutingRule(
name="code_generation",
condition=lambda text, meta: self._is_code_task(text),
provider="anthropic",
model="claude-sonnet-4-5",
reason="Code task — Claude performs better",
),
# Reasoning/математика → o3-mini
RoutingRule(
name="reasoning",
condition=lambda text, meta: self._is_reasoning_task(text),
provider="openai",
model="o3-mini",
reason="Reasoning task — using o3-mini",
),
# Default — GPT-4o
RoutingRule(
name="default",
condition=lambda text, meta: True,
provider="openai",
model="gpt-4o",
reason="Default routing",
),
]
def _is_code_task(self, text: str) -> bool:
code_keywords = [
"напиши код", "реализуй", "функция", "класс", "алгоритм",
"python", "javascript", "sql", "рефакторинг", "отладь"
]
return any(kw in text.lower() for kw in code_keywords)
def _is_reasoning_task(self, text: str) -> bool:
reasoning_keywords = [
"докажи", "вычисли", "оптимизируй", "найди оптимальное",
"математически", "логически следует", "минимизируй"
]
return any(kw in text.lower() for kw in reasoning_keywords)
def route(self, text: str, meta: dict = None) -> RoutingRule:
"""Определяет провайдера для запроса"""
meta = meta or {}
for rule in self.rules:
if rule.condition(text, meta):
return rule
return self.rules[-1] # Default
def complete(
self,
messages: list[dict],
system: str = None,
**kwargs
) -> str:
"""Выполняет запрос через оптимального провайдера"""
user_message = messages[-1]["content"] if messages else ""
rule = self.route(user_message)
print(f"[Router] {rule.name} → {rule.provider}/{rule.model}: {rule.reason}")
if rule.provider == "anthropic":
return self._call_anthropic(messages, rule.model, system, **kwargs)
elif rule.provider == "openai":
return self._call_openai(messages, rule.model, system, **kwargs)
elif rule.provider == "groq":
return self._call_groq(messages, rule.model, system, **kwargs)
def _call_anthropic(self, messages, model, system, **kwargs) -> str:
kwargs.pop("temperature", None) if "o" in model else None
response = self.anthropic_client.messages.create(
model=model,
max_tokens=kwargs.get("max_tokens", 2048),
system=system or "",
messages=messages,
temperature=kwargs.get("temperature", 0.1),
)
return response.content[0].text
def _call_openai(self, messages, model, system, **kwargs) -> str:
all_messages = []
if system:
all_messages.append({"role": "system", "content": system})
all_messages.extend(messages)
params = {"model": model, "messages": all_messages}
if "o1" not in model and "o3" not in model:
params["temperature"] = kwargs.get("temperature", 0.1)
response = self.openai_client.chat.completions.create(**params)
return response.choices[0].message.content
def _call_groq(self, messages, model, system, **kwargs) -> str:
all_messages = []
if system:
all_messages.append({"role": "system", "content": system})
all_messages.extend(messages)
response = self.groq_client.chat.completions.create(
model=model,
messages=all_messages,
temperature=kwargs.get("temperature", 0),
)
return response.choices[0].message.content
Метрики для моніторингу роутера
- cost per request
- latency p50, p95, p99
- cost savings overall
- fallback rate
Додавання моніторингу дозволяє відстежувати ефективність правил і своєчасно оновлювати пороги.
Семантичний роутер (ML-based)
Зазначимо: коли контекст запиту не вкладається в жорсткі правила, використовуємо семантичний роутинг. Він знаходить найближчий прототип задачі серед векторизованих прикладів. У коді нижче — реалізація з SentenceTransformer:
from sentence_transformers import SentenceTransformer
import numpy as np
class SemanticRouter:
"""Роутинг на основе семантического сходства с примерами задач"""
def __init__(self):
self.model = SentenceTransformer("BAAI/bge-small-en-v1.5")
# Примеры задач для каждого провайдера
self.routes = {
"groq_fast": [
"what time is it", "hello", "who are you",
"привет", "простой вопрос", "краткий ответ"
],
"anthropic_code": [
"write a python function", "debug this code",
"refactor this class", "implement algorithm",
"код на python", "напиши функцию"
],
"openai_reasoning": [
"solve this math problem", "prove this theorem",
"optimize this algorithm", "logical deduction",
"математическая задача", "докажи утверждение"
],
}
# Предвычисляем эмбеддинги
self.route_embeddings = {}
for route, examples in self.routes.items():
self.route_embeddings[route] = self.model.encode(examples)
def route(self, query: str) -> str:
query_embedding = self.model.encode(query)
best_route = "openai_default"
best_score = 0.5 # Минимальный порог
for route, embeddings in self.route_embeddings.items():
scores = np.dot(embeddings, query_embedding) / (
np.linalg.norm(embeddings, axis=1) * np.linalg.norm(query_embedding)
)
max_score = scores.max()
if max_score > best_score:
best_score = max_score
best_route = route
return best_route
Доповнюємо систему моніторингом (RouterWithMetrics) для трекінгу latency, вартості та частоти спрацювання правил. Налаштування MLOps-пайплайну дозволяє автоматично оновлювати пороги та правила.
Чому rule-based роутинг не завжди достатній?
Rule-based роутер працює швидко та прозоро — не потребує GPU для інференсу. Але він погано узагальнює: запит «поясни, як працює бекенд» може бути і простим, і складним — без ключових слів не зрозуміти. Семантичний роутер вирішує цю проблему: він розуміє сенс запиту через embedding-схожість з навчальними прикладами.
На практиці ми комбінуємо підходи: спочатку швидкі правила відсікають очевидні класи, потім семантичний роутер довизначає складний випадок. Це дає і швидкість, і точність.
Що дає гібридний підхід?
| Характеристика | Rule-based | Семантичний (ML) | Гібридний |
|---|---|---|---|
| Швидкість роботи | < 1 мс | 5–20 мс | 1–20 мс |
| Точність (F1-score) | 0.85–0.90 | 0.92–0.97 | 0.95–0.98 |
| Потребує GPU | Ні | Ні (CPU) | Ні |
| Гнучкість під нові типи запитів | Низька | Висока | Висока |
| Час впровадження | 2–3 дні | 1–2 тижні | 1–2 тижні |
Семантичний роутер точніший за rule-based в 1.5–2 рази для нестандартних запитів, але rule-based достатньо для типових сценаріїв. Гібридний підхід в 1.5 рази ефективніший за rule-based за точністю і в 5 разів швидший за семантичний при простих запитах.
Порівняння провайдерів для різних завдань
| Провайдер | Найкраща модель | Latency (p99) | Вартість за 1M токенів | Найкращі завдання |
|---|---|---|---|---|
| OpenAI | GPT-4o | 2–5 с | $10 | Складне міркування, JSON |
| Anthropic | Claude Sonnet | 3–6 с | $8 | Код, аналіз |
| Groq | Llama 3 8B | < 100 мс | $0.05 | Чат, прості питання |
Згідно з Wikipedia, LLM — це модель, навчена на великих обсягах тексту, що пояснює різницю у вартості та latency між провайдерами.
Як впроваджуємо LLM Router: етапи
Ми розбиваємо роботу на етапи:
- Аналіз профілю запитів. Збираємо логи вашого застосунку, визначаємо частки типів завдань.
- Проектування роутера. Обираємо стратегію: rule-based, семантичний або гібрид. Визначаємо порогові значення та приклади.
- Реалізація. Пишемо ядро роутера (як у прикладах вище) з інтеграцією під ваших провайдерів.
- A/B-тестування. Порівнюємо роботу роутера з мономоделлю на реальному трафіку.
- Моніторинг та доналаштування. Розгортаємо дашборди (latency, cost, fallback rate).
Наш досвід каже, що критична частина — коректний fallback: якщо роутер помилився, запит має безпечно піти на резервну модель, не втрачаючи якість.
Що входить у роботу при замовленні?
При замовленні впровадження LLM Router ви отримуєте:
- Архітектурна документація — схема роутингу, правила, потоки даних.
- Код роутера (rule-based та/або семантичний) — з інтеграцією під ваші API-ключі.
- Налаштування моніторингу — метрики вартості, latency, частот правил.
- Звіт A/B-тесту — оцінка економії та впливу на користувацький досвід.
- Навчання команди — як додавати нові правила або приклади.
Ми гарантуємо прозорість: ви завжди бачите, який провайдер і модель обробили запит.
Зв'яжіться з нами для консультації — ми оцінимо ваш профіль запитів і запропонуємо оптимальне рішення. Замовте впровадження LLM Router і знизьте витрати на LLM до 5× без втрати якості.







