Маршрутизація запитів між LLM-провайдерами: LLM Router

Вступ: реальна проблема переплати за LLM

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1006

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

Ми розбиваємо роботу на етапи:

  1. Аналіз профілю запитів. Збираємо логи вашого застосунку, визначаємо частки типів завдань.
  2. Проектування роутера. Обираємо стратегію: rule-based, семантичний або гібрид. Визначаємо порогові значення та приклади.
  3. Реалізація. Пишемо ядро роутера (як у прикладах вище) з інтеграцією під ваших провайдерів.
  4. A/B-тестування. Порівнюємо роботу роутера з мономоделлю на реальному трафіку.
  5. Моніторинг та доналаштування. Розгортаємо дашборди (latency, cost, fallback rate).

Наш досвід каже, що критична частина — коректний fallback: якщо роутер помилився, запит має безпечно піти на резервну модель, не втрачаючи якість.

Що входить у роботу при замовленні?

При замовленні впровадження LLM Router ви отримуєте:

  • Архітектурна документація — схема роутингу, правила, потоки даних.
  • Код роутера (rule-based та/або семантичний) — з інтеграцією під ваші API-ключі.
  • Налаштування моніторингу — метрики вартості, latency, частот правил.
  • Звіт A/B-тесту — оцінка економії та впливу на користувацький досвід.
  • Навчання команди — як додавати нові правила або приклади.

Ми гарантуємо прозорість: ви завжди бачите, який провайдер і модель обробили запит.

Зв'яжіться з нами для консультації — ми оцінимо ваш профіль запитів і запропонуємо оптимальне рішення. Замовте впровадження LLM Router і знизьте витрати на LLM до 5× без втрати якості.