Маршрутизация запросов между 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× без потери качества.