LiteLLM er et open source Python-bibliotek, der giver dig et samlet OpenAI-kompatibelt interface til over 100 LLM-udbydere (OpenAI, Anthropic, Google, Groq, Bedrock, Azure og flere), så du kan skifte model, tilføje fallbacks, retries og cost tracking med få linjer kode. Med LiteLLM Router v1.52+ får du produktionsklar routing, latency-baseret load balancing og indbygget observability. I praksis betyder det færre 429-fejl, lavere p99-latency og én kodebase, der overlever, når din primære udbyder falder ud kl. 03:00.
LiteLLM 1.52+ giver en completion()-funktion, der taler samme protokol som OpenAI SDK'et, men router til over 100 udbydere via ét kald.
Router-klassen understøtter fallback-kæder (fx gpt-4o → claude-3.5-sonnet → llama-3.3-70b) med automatisk retry ved 429, 500 og timeout.
Indbygget cost tracking beregner USD pr. request via opdaterede pris-tabeller. Du kan aflæse response._hidden_params["response_cost"] direkte.
Load balancing understøtter tre strategier: simple-shuffle, latency-based og usage-based, hvilket sænker p99 med typisk 20–40 % i multi-key setups.
LiteLLM Proxy Server tilføjer virtuelle nøgler, budgetter pr. team og OTEL-tracing uden at ændre klientkoden.
Streaming, tool calling og structured outputs virker på tværs af udbydere. LiteLLM oversætter format-forskellene bag scenen.
Hvad er LiteLLM, og hvornår giver det mening?
LiteLLM er en Python-abstraktion udviklet af BerriAI, der oversætter kald mellem OpenAI-formatet og alle andre store LLM-udbydere. I stedet for at vedligeholde separate klient-integrationer for openai, anthropic, google-generativeai og boto3 kalder du én funktion, litellm.completion(), og angiver modelnavnet som prefix (anthropic/claude-3-5-sonnet-20241022, gemini/gemini-2.0-flash, groq/llama-3.3-70b-versatile). Biblioteket håndterer autentificering, format-mapping og fejlnormalisering.
I min hverdag som ops-lead er det faktisk ikke abstraktionen, der er værdifuld. Det er kontrollen. Når OpenAI's europæiske region falder ud (og det gør den 2–3 gange årligt), vil du have en en linjes ændring, der flytter trafikken til Anthropic eller Azure. Uden LiteLLM sidder du og skriver adapters i tre lag klokken to om natten. Med LiteLLM Router er det en konfiguration, der allerede er testet på fredag eftermiddag.
Hvornår giver det ikke mening? Hvis du kører én model, én region og har <10 requests i sekundet, er standard-SDK'et mere direkte. LiteLLM skinner, når du har multi-provider fallback, flere nøgler pr. udbyder eller behov for konsolideret cost tracking på tværs af teams. LiteLLM's officielle dokumentation lister den fulde matrix af understøttede features pr. udbyder.
Installation og første kald på tværs af udbydere
LiteLLM kræver Python 3.9+ og installeres direkte via pip. Hvis du planlægger at bruge Proxy Server, tilføjer du [proxy] som extra. Version 1.52.5 (november 2025) er den seneste stabile release i skrivende stund.
# Grundinstallation
pip install "litellm==1.52.5"
# Med proxy-server, cost tracking og guardrails
pip install "litellm[proxy]==1.52.5"
Sæt dine API-nøgler som miljøvariabler. LiteLLM læser standardnavne automatisk (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, GROQ_API_KEY). Det første kald ser sådan ud:
import os
import litellm
os.environ["OPENAI_API_KEY"] = "sk-..."
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."
# Samme funktionssignatur, kun modelnavnet ændres
gpt_response = litellm.completion(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Forklar CAP-teoremet på dansk."}],
max_tokens=300,
)
claude_response = litellm.completion(
model="anthropic/claude-3-5-haiku-20241022",
messages=[{"role": "user", "content": "Forklar CAP-teoremet på dansk."}],
max_tokens=300,
)
print(gpt_response.choices[0].message.content)
print(claude_response.choices[0].message.content)
# Responseobjektet er identisk struktureret på tværs af udbydere
print(f"Model brugt: {claude_response.model}")
print(f"Tokens ind/ud: {claude_response.usage.prompt_tokens}/{claude_response.usage.completion_tokens}")
Læg mærke til, at både choices, usage og model findes på begge responses. LiteLLM normaliserer Anthropic's input_tokens/output_tokens til OpenAI's prompt_tokens/completion_tokens. Det betyder, at din eksisterende OpenAI-kode fungerer uændret, selv når modellen bag er Claude.
Sådan bygger du en fallback-router til produktion
Enkelt-kald med litellm.completion() er fint til scripts, men i produktion vil du have en Router. Router-klassen tager en liste af "model deployments" og håndterer fallback, retry og load balancing automatisk. Konfigurationen er data, hvilket gør den let at versionere og A/B-teste.
from litellm import Router
model_list = [
{
"model_name": "primary-chat", # logisk alias, som app-koden bruger
"litellm_params": {
"model": "openai/gpt-4o",
"api_key": os.environ["OPENAI_API_KEY"],
"rpm": 500, # rate limit, router respekterer det
"timeout": 20,
},
},
{
"model_name": "primary-chat", # anden deployment af samme alias
"litellm_params": {
"model": "azure/gpt-4o-eu",
"api_key": os.environ["AZURE_API_KEY"],
"api_base": "https://myresource-eu.openai.azure.com",
"api_version": "2024-08-01-preview",
"rpm": 300,
},
},
{
"model_name": "fallback-chat",
"litellm_params": {
"model": "anthropic/claude-3-5-sonnet-20241022",
"api_key": os.environ["ANTHROPIC_API_KEY"],
"timeout": 25,
},
},
]
router = Router(
model_list=model_list,
fallbacks=[{"primary-chat": ["fallback-chat"]}],
num_retries=2,
retry_after=5, # sekunder mellem retries
routing_strategy="latency-based-routing",
set_verbose=False,
)
response = router.completion(
model="primary-chat", # ikke gpt-4o direkte, routeren vælger
messages=[{"role": "user", "content": "Skriv en changelog for v2.4"}],
)
print(f"Faktisk model: {response.model}")
Sekvensen ved en fejl: Router forsøger første primary-chat-deployment (OpenAI). Ved 429 eller timeout tester den den anden primary-chat-deployment (Azure EU). Hvis begge fejler, går den til fallback-chat (Claude). Alt uden at din applikationskode ved, at der er sket noget.
Den observation, der har reddet mest oppetid i mit team: routing-strategien matters. latency-based-routing pinger deployments og sender næste request til den hurtigste. Det sænker p99 markant, når én region er overbelastet. Vil du prioritere jævn belastning i stedet, brug usage-based-routing-v2, som tracker forbrug via Redis.
Retries, timeouts og backoff, du ville ønske du havde bygget først
Standard-retry-adfærden i LiteLLM ser ud af, at den bare "prøver igen", men detaljerne betyder noget. Router bruger eksponentiel backoff internt via tenacity, med jitter for at undgå thundering herd. Du kan konfigurere det pr. exception-type:
from litellm import Router
from openai import RateLimitError, APITimeoutError
router = Router(
model_list=model_list,
num_retries=3,
retry_policy={
"RateLimitErrorRetries": 4, # 429, retry mere aggressivt
"TimeoutErrorRetries": 2, # timeout, færre retries, hurtigere fallback
"InternalServerErrorRetries": 2, # 5xx
"ContentPolicyViolationErrorRetries": 0, # aldrig retry, det er dit prompt
"AuthenticationErrorRetries": 0, # aldrig retry, det er dit API-key
},
allowed_fails=3, # antal fejl før deployment cool-downes
cooldown_time=60, # sekunder deployment er markeret ude af rotation
)
Timeouts er en anden almindelig fælde. Uden en eksplicit timeout hænger en LLM-request potentielt i minutter, mens en langsom TCP-forbindelse laver keepalive. Sæt altid timeout pr. deployment til noget realistisk (20 sekunder for chat, 60 for lange completions, 5 for embedding). Router vil så cutte og prøve næste deployment i fallback-kæden.
For scenarier hvor du selv vil have kontrol over retry-logikken, kan du kombinere LiteLLM med Tenacity-biblioteket. Det er den samme approach, vi tog i vores guide til function calling og tool use, hvor tool-fejl kræver særlig retry-behandling.
Load balancing på tværs af API-nøgler og regioner
Har du flere OpenAI-organisationer eller flere Azure-deployments? LiteLLM Router kan distribuere trafik på tværs af dem for at spare rate-limit-budget. Der er tre strategier:
Strategi
Sådan virker den
Bruges når
Krav
simple-shuffle
Vælger tilfældigt vægtet på RPM/TPM
Du har lige performance på deployments
Ingen
latency-based-routing
Foretrækker deployment med lavest gennemsnitlig response-tid
Du optimerer p99 for slutbrugere
Ingen
usage-based-routing-v2
Vælger deployment med mest resterende TPM/RPM-budget
Du rammer rate limits regelmæssigt
Redis-instans
least-busy
Router til deployment med færrest igangværende requests
Lange completions med varierende varighed
Ingen
cost-based-routing
Vælger billigste deployment blandt dem, der kan levere kvaliteten
Batch-jobs uden latency-krav
Ingen
Min anbefaling? Start med latency-based-routing. Det giver de fleste teams 20–40 % lavere p99 uden ekstra infrastruktur. Skift til usage-based-routing-v2, når rate limits bliver den dominerende fejlkilde. Det kræver en Redis-instans, men til gengæld ved routeren præcis, hvor meget budget hver deployment har brugt i det aktuelle vindue.
Én af LiteLLM's mest undervurderede features er den indbyggede cost calculator. Ærligt talt, det er den funktion, jeg hurtigst savner, når jeg arbejder direkte mod OpenAI's SDK. Efter hvert kald kan du læse USD-omkostningen direkte fra responseobjektet:
Prisdatabasen ligger i BerriAI/litellm på GitHub og opdateres hver gang, en udbyder ændrer priser. For selv-hostede modeller (fx via vLLM) kan du registrere dine egne priser med litellm.register_model().
For at håndhæve budgetter pr. bruger uden at bygge din egen tracking, bruger de fleste teams litellm.acompletion med en callback:
from decimal import Decimal
import litellm
# in-memory tracker, brug Redis eller Postgres i produktion
user_spend: dict[str, Decimal] = {}
def track_cost_callback(kwargs, completion_response, start_time, end_time):
user_id = kwargs.get("metadata", {}).get("user_id")
if not user_id:
return
cost = Decimal(str(completion_response._hidden_params["response_cost"]))
user_spend[user_id] = user_spend.get(user_id, Decimal(0)) + cost
litellm.success_callback = [track_cost_callback]
LiteLLM Proxy Server til multi-team miljøer
Så snart mere end ét team bruger LLM'er, bliver nøglehåndtering og fælles budgetter et problem. LiteLLM Proxy Server løser det. Du deployer én proxy (Docker eller pip-installeret), og alle klienter taler til den via OpenAI SDK'et, med en virtuel API-nøgle, du udsteder pr. team.
Fordelene er reelle: du roterer den egentlige udbyder-nøgle uden at røre klienter, hver virtuel nøgle har eget budget og forbrugslog, og proxien centraliserer rate limiting, så team A ikke kan opæde team B's kvote.
Observability: Langfuse, OpenTelemetry og logs
Uden observability er en LLM-app en black box. LiteLLM har native integrationer til Langfuse, Helicone, LangSmith, Arize Phoenix og OpenTelemetry. Aktiveringen er én linje:
Kombiner med vores guide til LLM-evaluering med DeepEval, så du kan tage produktions-traces og bruge dem som eval-dataset. Det er den feedback-loop, der faktisk forbedrer dine prompts over tid, ikke tavlen med bullet points fra sidste sprint-review.
For teams der allerede kører OpenTelemetry, sender LiteLLM spans direkte til enhver OTLP-kompatibel collector (Grafana Tempo, Honeycomb, Datadog):
Efter to år med LiteLLM på tværs af tre produktionsapps, er det her de fejl, jeg konsekvent ser nye teams begå:
At tro fallback ≠ retry: Router prøver samme deployment først (retry), så næste deployment (fallback). Hvis dit primary timeout er 30s og du har num_retries=3, kan din request sidde i 90+ sekunder, før første fallback overhovedet starter. Sæt aggressive timeouts.
Context window mismatch: Fallback fra Claude Sonnet (200k tokens) til GPT-4o-mini (128k) fejler stille, hvis prompten er over grænsen. Brug context_window_fallbacks for eksplicit håndtering.
Function calling og structured outputs varierer pr. udbyder: LiteLLM oversætter format, men ikke kvalitet. Gemini's tool calling er ikke identisk med OpenAI's. Test hver fallback-kombination separat, som beskrevet i vores guide til structured outputs med Pydantic.
Rate limits på virtuelle nøgler: Proxy-nøglens rate limit er separat fra udbyderens rate limit. Hvis udbyder-nøglen er den flaskehals, hjælper virtuelle nøgler ikke.
Cost tracking mangler på streaming uden flag: Sæt stream_options={"include_usage": True} eller lav din egen token-counter fra chunks.
Redis er single point of failure for usage-based routing: Kør Redis Sentinel eller minimum en replica. Hvis Redis dør, falder routing tilbage til round-robin.
Ofte stillede spørgsmål
Er LiteLLM gratis at bruge?
Ja. LiteLLM Python-biblioteket og LiteLLM Proxy Server er MIT-licenserede og gratis at bruge, selv kommercielt. BerriAI tilbygger en betalt Enterprise-udgave med SSO, audit logs og SLA, men core-funktionalitet inklusive fallback, retry og cost tracking er åben.
Hvad er forskellen på LiteLLM og LangChain?
LiteLLM er et tyndt oversættelseslag mellem din kode og LLM-udbydere: én funktion, én router. LangChain er et fuldt framework med chains, agents, retrievers og memory. Du kan bruge LiteLLM inde i LangChain (via ChatLiteLLM). Til multi-provider routing og cost tracking er LiteLLM mere direkte end LangChain's egne provider-integrationer.
Understøtter LiteLLM streaming?
Ja, både litellm.completion(stream=True) og Router.completion(stream=True) understøtter server-sent events på tværs af udbydere. Fallback fungerer også med streaming: hvis første chunk fejler, prøver routeren næste deployment. Husk stream_options={"include_usage": True} for at få token-count på sidste chunk.
Hvordan håndterer LiteLLM Anthropic's prompt caching?
LiteLLM 1.40+ understøtter Anthropic's cache_control-blocks direkte. Sæt {"type": "text", "text": "...", "cache_control": {"type": "ephemeral"}} i messages, og LiteLLM sender det korrekt til Claude. Se detaljer i vores separate guide til prompt caching med Claude API.
Kan jeg bruge LiteLLM med lokale modeller via Ollama eller vLLM?
Ja. For Ollama: model="ollama/llama3.3" med api_base="http://localhost:11434". For vLLM: brug model="openai/<model-navn>" med api_base pegende på din vLLM-server. vLLM eksponerer OpenAI-kompatible endpoints. Cost tracking kræver, at du registrerer priserne manuelt via litellm.register_model().
Hvad sker der, hvis alle fallbacks fejler?
Router kaster den sidste exception op til din kode. Wrap altid router.completion() i try/except og hav en degraderet UX-sti (cached svar, "prøv igen senere"-besked eller en simpel regel-baseret fallback). Under et OpenAI + Anthropic samtidigt outage (sket to gange i 2024) hjælper ingen router.
Semantic chunking splitter tekst, hvor betydningen skifter, ikke ved et fast tegnantal. Lær at bygge en semantic chunker i Python og måle, hvornår den forbedrer recall i din RAG-pipeline.
Guide til OpenAI Structured Outputs med Pydantic i Python: garanteret JSON Schema-overholdelse, Function Calling, refusals-håndtering og produktionsfælder. Med fungerende kodeeksempler til 2026.
Sådan tilføjer du Cohere Rerank 3.5 til en Python RAG-pipeline og løfter Recall@5 med 15-35%: to-trins retrieval, hybrid-søgning, eval, latency og priser.