Вступ: реальна проблема переплати за 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× без втрати якості.







