LiteLLM w Pythonie 2026 – jednolite API dla 100+ LLM, fallbacki i tracking kosztów

Praktyczny przewodnik po LiteLLM w Pythonie: jeden OpenAI-kompatybilny endpoint dla 100+ providerów, Router z fallbackami, virtual keys z budżetami i cost tracking w Postgresie.

LiteLLM w Pythonie 2026 – Router i koszty

Zaktualizowano: 11 czerwca 2026

LiteLLM to open-source'owa biblioteka i serwer proxy w Pythonie, która udostępnia jeden, zgodny z OpenAI interfejs do ponad 100 dostawców LLM (OpenAI, Anthropic, Google, Bedrock, Azure, Mistral, a także lokalnych modeli przez Ollamę czy vLLM) z wbudowanym routingiem, automatycznymi fallbackami, śledzeniem kosztów i twardymi limitami budżetu per zespół. W praktyce oznacza to jeden punkt integracji w kodzie, niezależnie czy w produkcji odpalasz GPT-4o, Claude 4 Opus, czy lokalnego Llamę. W tym przewodniku pokażę, jak ustawić Router w Pythonie, skonfigurować strategię fallbacków, włączyć cost tracking w Postgresie i czego unikać przy wdrożeniu produkcyjnym w 2026 roku.

  • LiteLLM dostarcza jeden OpenAI-kompatybilny endpoint dla 100+ dostawców LLM. Można go używać jako SDK w kodzie albo jako stand-alone proxy (AI gateway) dla całego zespołu.
  • Router obsługuje retry, fallbacki i load balancing. Przy 429 deployment trafia od razu na cooldown, a ruch przesuwa się do następnego model_name w kolejce fallbacks.
  • Postgres przechowuje wirtualne klucze, logi spendu i konfigurację providerów; Redis koordynuje rate limity i cache między replikami. Produkcyjny stack wymaga obu.
  • Per-team budgets pozwalają wydać każdej drużynie wirtualny klucz z miesięcznym capem; po przekroczeniu LiteLLM twardo blokuje requesty.
  • Narzut proxy to ok. 4 ms latencji HTTP i 2–3% przepustowości. W zamian dostajesz auth, fallbacki i centralną telemetrię.
  • Strategia simple-shuffle jest rekomendowanym defaultem w produkcji; latency-based-routing i cost-based-routing zarezerwuj na wąskie scenariusze.

Czym jest LiteLLM i kiedy go używać?

LiteLLM to projekt BerriAI (Python SDK plus opcjonalny serwer proxy nazywany "AI Gateway"), który tłumaczy wywołania w formacie OpenAI Chat Completions na natywne API dziesiątek dostawców. Z punktu widzenia Twojego kodu wszystko jest openai.ChatCompletion.create(...). Z punktu widzenia ruchu sieciowego LiteLLM negocjuje z Anthropic Messages, Vertex AI Predict, Bedrock Converse, Azure OpenAI czy Ollamą lokalnie. Według repozytorium BerriAI/litellm na GitHubie wspieranych jest dziś ponad 100 providerów, włącznie z VertexAI, Cohere, SageMaker, HuggingFace i NVIDIA NIM.

Kiedy ma to sens? W moim doświadczeniu projekt zarabia na siebie w trzech sytuacjach: (1) gdy w jednym workflow wołasz różne modele dla różnych etapów (taniego Haiku do klasyfikacji, drogiego Opusa do syntezy), (2) gdy chcesz produkcyjnego fallbacku między dostawcami bez pisania własnego retry-loop'a, (3) gdy musisz pokazać finansom rozbicie kosztów per zespół albo per feature. Jeżeli używasz tylko jednego providera i nie potrzebujesz centralnego billingu, narzut LiteLLM nie zwróci się i lepiej zostać przy oficjalnym SDK.

Z perspektywy architektury workflow myślę o LiteLLM jak o bramie warstwy modeli, czyli odpowiedniku API gateway, ale dedykowanym dla LLM-ów. Routing, retry, kwoty i logging są po tej samej stronie, którą wcześniej rozwiązywałabym osobnymi paczkami: tenacity do retry, prometheus_client do metryk, Redis do throttlingu. LiteLLM scala to w jeden komponent z konfiguracją YAML.

SDK czy Proxy? Jak wybrać tryb wdrożenia

LiteLLM ma dwa tryby i wybór nie jest kosmetyczny. Zmienia model deploymentu, koszt operacyjny i to, kto trzyma klucze API. Tryb SDK to biblioteka Pythonowa zaimportowana wprost do procesu aplikacji. Klucze providerów żyją w zmiennych środowiskowych Twojego workera, fallbacki działają tylko w obrębie tego procesu, a koszty śledzisz callbackiem. Tryb Proxy to osobny serwis (FastAPI plus uvicorn pod spodem), który stawiasz raz dla całej organizacji. Klienci dostają wirtualne klucze LiteLLM, a prawdziwe klucze providerów leżą zaszyfrowane w Postgresie po stronie proxy.

WymiarLiteLLM SDKLiteLLM Proxy
Model wdrożeniaImport w Pythonie, in-processStand-alone serwis HTTP (FastAPI)
Klucze providerówW env aplikacjiCentralnie w Postgres, zaszyfrowane
Wirtualne klucze per zespółBrakTak, z budżetami i TTL
Współdzielony cacheTylko lokalnyRedis, między replikami
Latency overhead~0 ms (import)~4 ms HTTP round-trip
Dostęp z innych językówTylko PythonKażdy klient OpenAI-kompatybilny
Złożoność operacyjnaNiskaPostgres + Redis + monitoring

Praktyczna reguła: jeżeli Twój zespół pisze wyłącznie w Pythonie i wszystko żyje w jednym serwisie, zacznij od SDK. W momencie, gdy do gry wchodzi drugi zespół, Node-owy frontend, albo CFO pyta "ile wydaliśmy w marcu na GPT", przepnij na Proxy. Migracja jest trywialna, bo kod aplikacji nadal mówi w OpenAI; zmienia się tylko OPENAI_BASE_URL.

Jak skonfigurować Router z fallbackami w Pythonie

Sercem LiteLLM jest klasa Router. Definiujesz model groups, czyli pod jedną nazwą logiczną (np. "prod-chat") podpinasz wiele konkretnych deploymentów (Azure eastus, Azure swedencentral, OpenAI direct), a do tego listę fallbacków na innych nazwach logicznych. Router sam zajmie się retry, cooldownem i przełączeniem na fallback, kiedy oryginał padnie. Zainstaluj zależności:

pip install "litellm[proxy]==1.74.0" redis psycopg2-binary

Minimalna konfiguracja Routera z dwoma regionami Azure jako primary i Claude jako fallback:

import os
from litellm import Router

router = Router(
    model_list=[
        {
            "model_name": "prod-chat",
            "litellm_params": {
                "model": "azure/gpt-4o-eastus",
                "api_base": os.environ["AZURE_EASTUS_BASE"],
                "api_key": os.environ["AZURE_EASTUS_KEY"],
                "rpm": 600,
            },
        },
        {
            "model_name": "prod-chat",
            "litellm_params": {
                "model": "azure/gpt-4o-sweden",
                "api_base": os.environ["AZURE_SWEDEN_BASE"],
                "api_key": os.environ["AZURE_SWEDEN_KEY"],
                "rpm": 600,
            },
        },
        {
            "model_name": "prod-chat-fallback",
            "litellm_params": {
                "model": "anthropic/claude-opus-4-7",
                "api_key": os.environ["ANTHROPIC_API_KEY"],
                "rpm": 300,
            },
        },
    ],
    fallbacks=[{"prod-chat": ["prod-chat-fallback"]}],
    num_retries=2,
    timeout=30,
    routing_strategy="simple-shuffle",
    enable_weighted_failover=True,
)

response = router.completion(
    model="prod-chat",
    messages=[{"role": "user", "content": "Streszcz: ..."}],
)
print(response.choices[0].message.content)

Co się dzieje przy błędzie? Jeśli Azure eastus zwróci 429, Router natychmiast wkłada ten deployment na cooldown (nie czeka backoffem). Z włączonym enable_weighted_failover kolejny request od razu trafia do Azure swedencentral, czyli drugiego deploymentu w tej samej grupie prod-chat. Dopiero jeśli oba Azure'y padną, ruch przeskakuje na grupę prod-chat-fallback, czyli Claude'a. Hit ten dokładny scenariusz na produkcji w zeszłym kwartale — eastus padł na 9 minut, a użytkownicy nie zauważyli, bo Sweden wziął obciążenie w pełni. Pełny opis algorytmu znajdziesz w dokumentacji Router Architecture.

Strategie load balancingu, czyli który tryb wybrać

Router obsługuje sześć strategii: simple-shuffle, least-busy, usage-based-routing, usage-based-routing-v2, latency-based-routing oraz cost-based-routing. Brzmi efektownie, ale w praktyce wybór jest mniej istotny niż dobrze ustawione rpm i tpm per deployment. Zespół BerriAI wprost rekomenduje simple-shuffle jako default produkcyjny. Losowy wybór z wag (RPM jako waga) zachowuje się stabilnie pod każdym profilem ruchu i nie wymaga Redisa.

Kiedy odchodzić od defaultu? usage-based-routing-v2 ma sens, jeśli jeden z deploymentów ma znacznie wyższy limit kwotowy i nie chcesz go marnować. Router liczy zużycie w Redisie i kieruje ruch tam, gdzie zostało najwięcej budżetu RPM/TPM. latency-based-routing bywa kuszący, ale w testach, które robiłam dla klientów na Bedrocku, dawał gorsze p99 niż simple-shuffle, bo "najszybszy" deployment wciąga cały ruch i wpada w lokalny korek. cost-based-routing używaj tylko wtedy, gdy w jednej grupie modeli masz różne cenowo SKU (np. gpt-4o i gpt-4o-mini) i jakość jest dla Twojego use-case'u zamienna, co w praktyce zdarza się rzadko.

Cooldowny i kolejność (order)

Każdemu deploymentowi możesz nadać pole order. Router próbuje wszystkich order=1 przed wejściem w order=2. To czysty mechanizm "preferred + backup", niezależny od fallbacków między grupami. Łącząc order z fallbackami dostaję trzy warstwy obronne: preferowany region, kolejny region, inny dostawca. Konfiguracja jest deklaratywna i mieści się w 20 liniach YAML, czego nie da się powiedzieć o ręcznym tenacity plus circuit breakerze.

Tracking kosztów i budżety per zespół

Tu LiteLLM bije większość alternatyw. Po włączeniu Postgresa proxy zapisuje każdy request do tabeli LiteLLM_SpendLogs z dokładnym przelicznikiem cen aktualnym dla każdego modelu. Koszty są liczone po odpowiedzi, asynchronicznie. Z tego buduje się trzy poziomy raportowania: per virtual key, per team, per user.

Wirtualne klucze tworzysz endpointem /key/generate. Każdy klucz może mieć cap miesięczny, dzienny rate-limit i listę dozwolonych modeli:

curl -X POST http://litellm-proxy/key/generate \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "team_id": "team-search",
    "max_budget": 500.0,
    "budget_duration": "30d",
    "rpm_limit": 60,
    "models": ["prod-chat", "prod-embeddings"]
  }'

Po przekroczeniu 500 USD klucz przestaje działać (proxy zwraca błąd), a Ty dostajesz alert webhookiem. To zupełnie inny model operacyjny niż patrzenie raz w tygodniu na dashboard OpenAI i panikowanie. Jeśli interesują Cię techniki obniżania samych rachunków za tokeny, sprawdź też mój wcześniejszy poradnik o prompt cachingu w Claude API; łączenie tego z budżetami LiteLLM daje przewidywalność kosztów po obu stronach.

Observability, Prometheus i integracja z Langfuse

Proxy eksponuje endpoint /metrics w formacie Prometheusa. Najważniejsze metryki, które warto wyciągnąć od pierwszego dnia: litellm_requests_total (z labelami model, team, status), litellm_request_latency_ms, litellm_provider_remaining_budget_metric (USD zostające do końca okresu budżetowego per provider) oraz litellm_fallback_total. Dashboard, który zwykle składam w Grafanie, ma cztery panele: wolumen per provider, rozkład latencji p50/p95/p99, koszt narastający w miesiącu i ilość fallbacków per godzina. Ten ostatni jest najczulszym wskaźnikiem zdrowia upstreamów.

Do tracingu konwersacji LiteLLM ma natywną integrację z Langfuse, Helicone, MLflow i Arize Phoenix. Dla Langfuse wystarczy ustawić zmienne środowiskowe i włączyć callback:

import litellm

litellm.success_callback = ["langfuse"]
litellm.failure_callback = ["langfuse"]
# LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY / LANGFUSE_HOST z env

W trace'ach widzisz pełne prompty, response'y, latencję, koszt i informację, który deployment został wybrany przez routing. To bardzo przydatne, gdy chcesz zrozumieć, dlaczego konkretny request poszedł na fallback. Jeżeli budujesz większy stack jakości, polecam zestawić to z ewaluacją agentów AI z DeepEval i Langfuse, bo wspólny backend Langfuse pozwala porównywać runy ewaluacyjne z ruchem produkcyjnym 1:1.

Najczęstsze pułapki produkcyjne

Z każdego wdrożenia LiteLLM, w którym brałam udział, wynoszę tę samą listę:

  1. Brak Redisa pod load balancerem. Bez Redisa każda replika proxy ma własny licznik rate-limit, więc trzy repliki * 60 rpm = realnie 180 rpm. Dla małych ruchów OK, dla większych: niespodziewane 429-tki od providera. Włącz redis_host w configu od początku.
  2. Wszystkie wirtualne klucze w jednym teamie. Jeśli wszyscy używają jednego klucza "default", tracisz cały sens budżetów. Generuj klucz per usługa albo per env; zerwanie klucza jednemu workerowi nie zatrzyma reszty.
  3. Liczenie na fallbacki bez testów chaos. Konfiguracja jest deklaratywna, ale to nie znaczy, że działa "samo". Raz na sprint robię ćwiczenie: zmieniam api_key primary deploymentu na zły i sprawdzam, czy traffic przepływa na fallback w mniej niż 2 sekundy. Oficjalna dokumentacja fallbacków opisuje też tryb context_window_fallbacks, który warto włączyć osobno.
  4. Streaming i fallbacki. Przy SSE Router musi otworzyć strumień zanim wie, że providera nie ma. Fallback działa tylko na błędach przed pierwszym tokenem. Pamiętaj o tym, jeśli budujesz UI z natychmiastowym streamem; długie strumienie po prostu padają.
  5. Nadmierne num_retries. Domyślnie 2, kuszące jest dać 5. Po piątym retry providera już dawno powinieneś być na fallbacku. Wysokie retry maskują problemy w monitoringu; wolisz widzieć fallbacki niż "wszystko działa, tylko trochę wolno".

LiteLLM vs OpenRouter vs własny gateway

Porównuję trzy ścieżki w decyzji architektonicznej:

  • LiteLLM (self-hosted). Pełna kontrola, brak tax-u marży, możesz hostować w VPC obok aplikacji. Płacisz operacyjnie (Postgres, Redis, monitoring). Polecam, gdy masz już Kubernetesa i zespół SRE.
  • OpenRouter (managed). Zero ops, jedno API, ale liczy marżę 5% na każdym wywołaniu i Twoje prompty przechodzą przez ich infrastrukturę. Sensowny start dla prototypów, problematyczny dla branż regulowanych (medycyna, finanse).
  • Własny gateway w FastAPI. Pełna kontrola plus dokładnie te featury, których chcesz. Realnie kosztuje 2–3 sprinty inżyniera tylko na podstawową funkcjonalność (retry, cost calc, virtual keys), a potem dług utrzymaniowy. Robię to tylko wtedy, gdy LiteLLM nie spina jakiegoś bardzo niszowego providera, którego klient wymaga.

W 90% przypadków odpowiedź to LiteLLM Proxy w VPC. Jeśli interesują Cię szersze wzorce architektoniczne dla wieloagentowych pipeline'ów, zerknij na artykuł o systemach wieloagentowych w CrewAI i LangGraph; LiteLLM doskonale wpina się jako warstwa modelowa pod oboma frameworkami.

Często zadawane pytania

Czy LiteLLM działa z lokalnymi modelami przez Ollamę i vLLM?

Tak. LiteLLM traktuje Ollamę i vLLM jak każdego innego providera. W model_list wpisujesz "model": "ollama/llama3.1" albo "model": "openai/..." z api_base wskazującym na lokalny vLLM. Możesz mieszać lokalne i chmurowe modele w jednej grupie z fallbackami.

Jaki jest narzut latencji LiteLLM Proxy?

Według testów BerriAI i własnych pomiarów w VPC AWS narzut to około 4 ms na request i 2–3% przepustowości. To pomijalne wobec setek milisekund samego wywołania LLM. SDK w trybie in-process nie dodaje praktycznie nic.

Czy mogę używać LiteLLM bez Postgresa?

Możesz, jeśli używasz tylko SDK albo Proxy w trybie stateless. Postgres jest wymagany dopiero dla virtual keys, persystencji budżetów i logów spendu. Dla zespołowych wdrożeń warto go włączyć od początku, bo migracja konfiguracji jest niewdzięczna.

Jak LiteLLM oblicza koszt requesta?

Po każdej odpowiedzi proxy odczytuje liczbę tokenów input/output z metadata i mnoży przez cennik z lokalnej tabeli (aktualizowanej w nowych wersjach paczki). Wynik zapisuje asynchronicznie do LiteLLM_SpendLogs. Dla nietypowych modeli możesz nadpisać ceny w configu polem input_cost_per_token.

Czy LiteLLM wspiera tool use i structured output?

Tak. Proxy normalizuje pola tools, tool_choice i response_format do formatu OpenAI niezależnie od backendu (Anthropic tool use, Vertex function calling itd.). Dzięki temu kod kliencki pisany pod OpenAI działa bez modyfikacji na Claude'u czy Gemini.

Emma Bergstrom
O Autorze Emma Bergstrom

Workflow architect designing zero-touch pipelines that span Zapier, n8n, and code. Calls herself a recovering ops engineer.