LiteLLM: как подружить Claude, OpenAI-совместимый провайдер и один API-слой
Если у вас в проекте уже больше одной LLM — поздравляю, у вас уже зоопарк. Один скрипт ходит в Anthropic SDK, второй — в openai через base_url какого-нибудь облачного провайдера, третий написан на curl потому что «быстро надо было, потом перепишу». Знакомо? И каждый раз, когда меняется ключ, тариф или модель, приходится править все три места (а ещё забыть про четвёртое, которое крутится в кроне раз в неделю).
LiteLLM — это попытка свести этот зоопарк к одной точке входа. В этом посте разберём, что такое LiteLLM, чем он принципиально отличается от обычного SDK, как его поднять локально и в Docker, как подключить к нему Claude и OpenAI-совместимого провайдера одновременно, и зачем это вообще нужно практикующему инженеру, а не только команде с ML-платформой на сто человек.
Что такое LiteLLM простыми словами
LiteLLM — открытая прослойка над провайдерами LLM (Anthropic, OpenAI, Google, Bedrock, Azure, локальные Ollama и десятки других), которая выставляет наружу единый OpenAI-совместимый HTTP API.
Можно использовать LiteLLM в двух режимах:
- SDK-режим (
litellmкак Python-библиотека). Вы импортируетеlitellm.completion(...)и под капотом он ходит в нужный провайдер. Удобно для скриптов, но слабо помогает, если у вас не Python. - Proxy-режим (LiteLLM Proxy Server). Поднимается отдельный сервис — обычно в Docker, — который принимает запросы по адресу
https://your-llm.example.com/v1/chat/completions, а внутри сам решает, кому реально их отправить. Любой клиент, умеющий говорить с OpenAI, теперь умеет говорить с чем угодно.
Если очень грубо — LiteLLM Proxy это API Gateway, но специально заточенный под LLM-трафик: он знает про токены контекста, про tool calling, про streaming, про разные форматы сообщений у Anthropic и OpenAI.
Чем LiteLLM не является
- Не модель. Своих весов у него нет, считать он ничего не умеет. Это маршрутизатор и адаптер форматов.
- Не кеш по умолчанию. Кеш есть, но его нужно явно включить и подключить Redis, иначе платите за каждый запрос.
- Не замена Anthropic SDK для тонкой работы. Если вам нужны экзотические фичи Claude вроде Model Context Protocol или специфичных полей prompt caching, иногда проще ходить в Anthropic напрямую, а через LiteLLM пускать массовый «обычный» трафик.
Зачем нужен LiteLLM: какие проблемы он решает
Без прокси у вас типичный набор боли:
- Привязка к одному провайдеру. Менять Anthropic на OpenAI = переписывать половину кода. С LiteLLM меняется одна строка в конфиге.
- Размазанные ключи. API-ключи лежат в env-переменных каждого сервиса, ротация — это квест на полдня.
- Нет единого учёта. Сколько в этом месяце реально потратили на LLM по проектам? Без прокси — никто не знает (и финдир делает грустное лицо).
- Нет лимитов на пользователя. Любой скрипт может случайно запулить 50к токенов в цикле и съесть бюджет за выходные.
- Несовместимые форматы. У Claude
systemэто отдельный параметр, у OpenAI — это сообщение с рольюsystemв массиве. LiteLLM это разруливает.
Всё это в одиночку решаемо, но каждое решение — это код, который вы пишете и поддерживаете сами. Прокси берёт это на себя.
Архитектура: как устроен LiteLLM Proxy
Тут важна не картинка ради картинки, а понимание, где что происходит и что может пойти не так на каждом шаге.
На диаграмме три зоны. Синяя — клиенты, которым всё равно, какая модель за стенкой: они говорят на одном диалекте OpenAI Chat Completions и не знают про существование Anthropic. Зелёная — сам прокси, разделённый на модули: аутентификация по virtual keys, бюджет и лимиты, маршрутизатор с fallback, адаптер форматов, кеш и логирование. Жёлтая — реальные провайдеры моделей. Фиолетовая — состояние: Postgres хранит ключи, пользователей и spend, Redis — кеш и счётчики rate limit.
Поток одного запроса
- Клиент шлёт
POST /v1/chat/completionsс заголовкомAuthorization: Bearer sk-virtual-...— это виртуальный ключ, выписанный администратором прокси. - Прокси валидирует ключ, поднимает связанный с ним лимит (например, $50 в месяц на проект).
- Роутер по
model: "claude-sonnet"смотрит в конфиг и решает: первый кандидат — Anthropic напрямую, fallback — Bedrock, ещё fallback — OpenAI совместимый GPT-аналог. Если Anthropic вернул 529 или таймаут — автоматически следующий. - Адаптер собирает payload в формате выбранного провайдера. Для Anthropic это значит вытащить
systemиз массива сообщений и положить его в отдельное поле. - Если включён кеш — считается хеш промпта, проверяется Redis. Hit — отдаём из кеша, miss — идём в провайдера.
- Ответ нормализуется обратно в OpenAI-формат и отдаётся клиенту. Параллельно в Postgres пишется spend, в логи —
request_id.
Если прокси и REST API в целом для вас новая тема — здесь полезно знать про разницу stateless и stateful. LiteLLM Proxy сам по себе stateless (состояние — в Postgres/Redis), и это ровно то, почему его легко масштабировать горизонтально.
Как поднять LiteLLM Proxy: минимальный пример
Самый быстрый способ — Docker. Создайте config.yaml:
model_list: - model_name: claude-sonnet litellm_params: model: anthropic/claude-sonnet-4-5 api_key: os.environ/ANTHROPIC_API_KEY
- model_name: gpt-fallback litellm_params: model: openai/gpt-4o-mini api_base: https://your-openai-compat.example.com/v1 api_key: os.environ/OPENAI_COMPAT_KEY
router_settings: fallbacks: - claude-sonnet: ["gpt-fallback"]
litellm_settings: drop_params: true cache: true cache_params: type: redis host: redis port: 6379Здесь:
model_name— это псевдоним, по которому клиент будет запрашивать модель. Внутри он может указывать на что угодно.litellm_params.model— реальный провайдер и модель. Префикс (anthropic/,openai/,bedrock/,ollama/) подсказывает прокси, какой адаптер использовать.fallbacks— если первая модель упала, пробуем следующую. Удобно, когда у Anthropic очередной 529.drop_params: true— молча выкидывать параметры, которые провайдер не понимает, а не падать с 400. Спорная штука, но в проде живётся легче.
Поднимаем:
docker run -d --name litellm \ -e ANTHROPIC_API_KEY=sk-ant-... \ -e OPENAI_COMPAT_KEY=sk-... \ -e LITELLM_MASTER_KEY=sk-master-secret \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ ghcr.io/berriai/litellm:main-stable \ --config /app/config.yamlИ проверяем:
curl http://localhost:4000/v1/chat/completions \ -H "Authorization: Bearer sk-master-secret" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet", "messages": [{"role": "user", "content": "Привет"}] }'Если ответ пришёл — всё, у вас теперь единый OpenAI-совместимый слой над Claude. Любой клиент, умеющий OpenAI (и таких — почти все), теперь работает с Claude без единой строчки кода-адаптера.
Сравнение подходов: прямой SDK vs LiteLLM Proxy
| Аспект | Прямой Anthropic / OpenAI SDK | LiteLLM Proxy |
|---|---|---|
| Смена провайдера | Переписать код | Изменить config.yaml |
| Управление ключами | В env каждого сервиса | Virtual keys в одном месте |
| Учёт расходов | Через дашборд провайдера | Сквозной spend по проектам |
| Rate limiting | Сам пишешь | Из коробки, по ключу/команде |
| Fallback при сбое | Свой код с try/except | Декларативно в конфиге |
| Кеширование | Сам делаешь | Redis в одну строчку |
| Поддержка специфичных фич | Полная | Иногда отстаёт от провайдера |
| Latency | Минимум | +1 hop (обычно 5–20 мс) |
| Ещё одна точка отказа | Нет | Да — прокси нужно держать в HA |
Последние две строки — это плата за удобство. Если прокси упал — встанут все клиенты сразу. Поэтому в проде LiteLLM поднимают минимум в двух репликах за балансировщиком, с health-check’ами и алертами на p99 latency.
Подключаем Claude Code через LiteLLM
Один из самых полезных сценариев в моей практике — пускать Claude Code CLI не напрямую в Anthropic, а через свой прокси. Зачем:
- Лимиты и учёт. Видно, кто из команды сколько токенов сжёг.
- Кеширование общих промптов. Если у вас десять сессий начинаются с одного и того же длинного системного промпта, Redis-кеш экономит реальные деньги.
- Единый аудит. Все запросы логируются в одном месте, а не в личных кабинетах разных провайдеров.
Технически Claude Code умеет ходить в Anthropic-совместимый эндпоинт. LiteLLM умеет принимать запросы и в OpenAI-формате (/v1/chat/completions), и в нативном Anthropic-формате (/v1/messages) — на этом и строится трюк. Указываем CLI базовый URL прокси и virtual key, дальше всё работает как обычно, только трафик идёт через вашу инфраструктуру. Подробности подключения зависят от версии — смотрите доку, она меняется.
Важно. Не заворачивайте через прокси то, что использует фичи, которых LiteLLM ещё не поддерживает (например, экспериментальные режимы тулюзинга). Сначала протестируйте на dev-ключе, потом переводите прод.
Антипаттерны: на чём обжигаются с LiteLLM
Прокси без HA
Поднимают один контейнер на старом дроплете и забывают. Через месяц он ловит OOM посреди ночи — и весь продукт теряет LLM-фичи. Решение скучное: минимум две реплики, health-check, алерт на 5xx, мониторинг p95.
Кеш без понимания инвалидации
Включили cache: true — обрадовались экономии — потом обнаружили, что юзеры получают ответы вчерашнего дня на сегодняшние данные. Кешировать стоит только запросы, где это реально безопасно: системные промпты, справочные ответы, эмбеддинги. Динамический контент — нет.
Master key вместо virtual keys
Раздают всем разработчикам LITELLM_MASTER_KEY («ну так быстрее»). Через полгода ключ утекает в публичный репозиторий, ротация — это смена master-ключа и переподключение всего парка. Virtual keys выписываются по одному на сервис/человека и отзываются индивидуально.
Fallback на принципиально другую модель
В конфиге пишут: «если упал Claude — пускай OpenAI». Звучит логично, но качество ответов у разных моделей разное, и пользователь это заметит. Fallback’и должны быть максимально близкими: Anthropic Claude → Bedrock Claude — да; Claude Sonnet → GPT-4o-mini — почти всегда нет.
Игнорирование разницы в tool calling
У OpenAI и Anthropic разные форматы инструментов. LiteLLM их транслирует, но не магически: какие-то экзотические поля могут потеряться. Если у вас сложный tool use — тестируйте сквозным интеграционным тестом, не верьте на слово.
Когда LiteLLM не нужен
Это не серебряная пуля. Если у вас:
- один проект, одна модель, один провайдер;
- нет команды и нет необходимости в учёте расходов по людям;
- очень специфичные фичи модели, которые прокси может не докинуть;
— то прямой SDK будет проще и быстрее. Прокси — это инструмент для тех, у кого LLM-трафик стал инфраструктурой, а не разовой интеграцией.
Заключение
LiteLLM решает скучную, но дорогую проблему: чем больше у вас LLM-интеграций, тем дороже их поддерживать поодиночке. Один прокси, один формат, один учёт, одна точка ротации ключей — и внезапно у вас есть рычаг управления, которого раньше не было.
PS. Как только вы поднимете прокси и начнёте видеть spend по проектам — приготовьтесь к неприятному открытию. Окажется, что один забытый скрипт в кроне жрёт половину бюджета. Это не баг прокси, это фича прозрачности (которую раньше вы себе позволить не могли).