Cursus
Wisselen tussen verschillende LLM-providers zou niet moeten betekenen dat je je hele codebase moet herschrijven. Maar dat is precies wat er nu gebeurt als je met meerdere AI-services werkt. Elke provider heeft z’n eigen SDK, authenticatiemethode en responsformaat. LiteLLM lost dit op met een uniforme interface.
In deze tutorial leg ik de belangrijkste onderdelen van LiteLLM uit en laat ik je zien hoe je begint met basis-API-calls en doorgaat naar streamingresponses, gestructureerde outputs en kostentracking.
Wat is LiteLLM?
LiteLLM is een open-sourcelibrary voor Python die werkt als een universele vertaler voor AI-modellen. In plaats van verschillende API’s per provider te moeten leren, gebruik je één interface die met meer dan 100 LLM-services kan verbinden.
Het framework heeft twee hoofdonderdelen. De Python-SDK laat je code één keer schrijven en met elke provider uitvoeren. De proxyserver fungeert als centrale gateway voor teams en bedrijven die AI-services op schaal moeten beheren.
LiteLLM biedt daarnaast deze voordelen:
- Ingebouwde kostentracking: Zie uitgaven bij alle providers in één dashboard in plaats van meerdere factureringssystemen te checken
- Automatische failovers: Als één provider uitvalt of tegen rate limits aanloopt, probeert LiteLLM automatisch je back-upopties
- Optie voor self-hosting: Laat alles op je eigen servers draaien als je dataprivacy of compliance nodig hebt
Let op: OpenRouter biedt vergelijkbare uniforme toegang tot meerdere LLM’s, maar met andere prijzen en functies.
De proxyserver voegt uitgavenlimieten per team toe, gebruikstracking over projecten heen en gecentraliseerd beheer van API-sleutels. Alle configuratie gebeurt via eenvoudige YAML-bestanden.
LiteLLM werkt goed voor verschillende typen gebruikers:
- Individuele ontwikkelaars die meerdere modellen willen testen zonder overal accounts aan te maken
- Kleine teams die inzicht in kosten nodig hebben en geen vendor lock-in willen
- Grote bedrijven die centraal beheer, budgetcontrole en gedetailleerde gebruiksstatistieken nodig hebben
De library heeft een MIT-licentie en is volledig open-source. Je kunt de code inspecteren, aanpassen aan jouw behoeften of bijdragen aan het project.
Nu je weet wat LiteLLM kan, zo richt je je omgeving in.
Vereisten
Voordat je met LiteLLM aan de slag kunt, moet je een paar dingen instellen. Het meeste hiervan heb je waarschijnlijk al gedaan als je eerder met AI-modellen hebt gewerkt.
Python-omgeving
Je hebt Python 3.7 of nieuwer nodig. De meeste systemen hebben dit tegenwoordig, maar je kunt je versie checken met:
import sys
print(f"Python version: {sys.version_info.major}.{sys.version_info.minor}")
Pakketinstallatie
Installeer LiteLLM en python-dotenv voor het beheren van omgevingsvariabelen:
uv add litellm python-dotenv
# or with pip: pip install litellm python-dotenv
API-sleutels
Je hebt API-sleutels nodig van de providers die je wilt gebruiken. Voor deze tutorial werken we met twee modellen:
- OpenAI API-sleutel: Je kunt een sleutel krijgen via platform.openai.com (voor GPT-5)
- Anthropic API-sleutel: Je kunt een sleutel krijgen via console.anthropic.com (voor Claude Sonnet 4)
Sla deze op in een .env-bestand in je projectmap:
OPENAI_API_KEY=your_openai_key_here
ANTHROPIC_API_KEY=your_anthropic_key_here
Omgevingscheck
Voer dit script uit om je setup te controleren:
import os
import sys
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Check Python version
print(f"Python version: {sys.version_info.major}.{sys.version_info.minor}")
# Check LiteLLM
try:
import litellm
print("✓ LiteLLM installed")
except ImportError:
print("✗ LiteLLM not installed")
# Check API keys
openai_key = os.getenv("OPENAI_API_KEY")
anthropic_key = os.getenv("ANTHROPIC_API_KEY")
if openai_key:
print(f"✓ OpenAI API key found")
else:
print("✗ OpenAI API key not found")
if anthropic_key:
print(f"✓ Anthropic API key found")
else:
print("✗ Anthropic API key not found")
Python version: 3.11
✓ LiteLLM installed
✓ OpenAI API key found
✓ Anthropic API key found
Als je overal groene vinkjes ziet, ben je klaar om te starten. Als er iets faalt, zorg dan dat je de pakketten hebt geïnstalleerd en je API-sleutels aan het .env-bestand hebt toegevoegd.
Je eerste API-call met LiteLLM
LiteLLM gebruikt dezelfde interface die je misschien kent van OpenAI, maar werkt met elke provider.
Basissetup
Begin met deze imports:
import litellm
from dotenv import load_dotenv
# Load your API keys
load_dotenv()
Een basisverzoek aan GPT-5 volgt dit patroon: definieer je berichten, roep litellm.completion() aan en haal de response op.
messages = [
{"role": "user", "content": "Write a simple Python function that adds two numbers"}
]
response = litellm.completion(
model="gpt-5",
messages=messages
)
print(response.choices[0].message.content)
def add(a, b):
"""Return the sum of a and b."""
return a + b
Je hebt zojuist GPT-5 aangeroepen via LiteLLM. Het response-object volgt het OpenAI-formaat, dus als je hun API al hebt gebruikt, ziet dit er bekend uit. Je wilt misschien bekijken welk model daadwerkelijk heeft geantwoord en het tokenverbruik checken:
print(f"Model used: {response.model}")
print(f"Response ID: {response.id}")
print(f"Total tokens: {response.usage.total_tokens}")
Model used: gpt-5-2025-08-07
Response ID: chatcmpl-CIbZWUDE1amW2vHtHDmieTX6hnZUq
Total tokens: 557
Wisselen van providers
De echte kracht van LiteLLM zie je bij het wisselen van providers. Wil je in plaats daarvan Claude Sonnet 4 proberen? Verander één parameter:
response = litellm.completion(
model="anthropic/claude-sonnet-4-20250514",
messages=messages
)
print(response.choices[0].message.content)
Here's a simple Python function that adds two numbers:
def add_numbers(a, b):
"""
Adds two numbers and returns the result.
Args:
a: First number
b: Second number
Returns:
The sum of a and b
"""
return a + b
# Example usage:
result = add_numbers(5, 3)
print(result) # Output: 8
This function:
- Takes two parameters a and b
- Returns their sum using the + operator
- Works with integers, floats, and even negative numbers
- Includes a docstring to explain what the function does
Dezelfde codestructuur, andere provider. Claude geeft een veel gedetailleerdere response met documentatie en voorbeelden, terwijl GPT-5 bondiger was.
Eenvoudige foutafhandeling
Voeg wat foutafhandeling toe voor wanneer het misgaat:
try:
response = litellm.completion(
model="gpt-5",
messages=messages
)
print(response.choices[0].message.content)
except Exception as e:
print(f"API call failed: {e}")
Dit patroon vangt veelvoorkomende problemen op zoals ongeldige API-sleutels, netwerkproblemen of modelonbeschikbaarheid.
Wat nu
Je kent nu het basispatroon voor het gebruiken van LiteLLM met elke provider. De Getting Started-documentatie behandelt meer details over ondersteunde modellen en parameters, en de referentie van de Completion-functie toont alle beschikbare opties.
Voor productieapplicaties wil je ook best practices voor API-design volgen om betrouwbare, performante systemen te bouwen.
Wisselen van providers en fallbacks
Het fallbacksysteem van LiteLLM handelt providerstoringen automatisch af zodat je gebruikers geen foutmeldingen zien. Als je echte applicaties bouwt, heb je back-ups nodig die werken zonder extra code van jouw kant.
Basis-fallbacksetup
Om een fallback in te stellen, voeg je een fallbacks-lijst toe aan je completion-aanroep:
messages = [
{"role": "user", "content": "Explain what a Python decorator is in one sentence"}
]
response = litellm.completion(
model="gpt-5",
messages=messages,
fallbacks=["anthropic/claude-sonnet-4-20250514"]
)
print(f"Response: {response.choices[0].message.content}")
print(f"Model used: {response.model}")
Response: A Python decorator is a callable that wraps another function or class to augment its behavior and returns it, applied with the @ syntax so you can add reusable functionality without changing the original code.
Model used: gpt-5-2025-08-07
Als GPT-5 faalt, probeert LiteLLM automatisch Claude Sonnet 4. Gebruikers krijgen in beide gevallen een response.
Fallbackketens bouwen
Je kunt meerdere providers ketenen voor meer betrouwbaarheid. Met dezelfde berichten als hiervoor:
response = litellm.completion(
model="gpt-5",
messages=messages,
fallbacks=["anthropic/claude-sonnet-4-20250514", "gpt-3.5-turbo"]
)
print(f"Model used: {response.model}")
Model used: gpt-5-2025-08-07
LiteLLM probeert modellen op volgorde. Als de primaire faalt, probeert het de eerste fallback. Als die faalt, probeert het de tweede. Meerdere lagen bescherming.
Retries toevoegen
Combineer fallbacks met retries voor nog meer betrouwbaarheid:
response = litellm.completion(
model="gpt-5",
messages=messages, # Same messages as before
num_retries=2
)
Probeert hetzelfde model twee keer opnieuw voordat het naar fallbacks gaat. Handig bij tijdelijke netwerkproblemen of pieken in rate limits.
Fallbacks handelen de meeste fouten automatisch af, maar je moet nog steeds gevallen opvangen waarbij alle modellen falen:
try:
response = litellm.completion(
model="gpt-5",
messages=messages, # Same messages as before
fallbacks=["anthropic/claude-sonnet-4-20250514"],
num_retries=2
)
return response.choices[0].message.content
except Exception as e:
# All models failed - handle gracefully
return "Sorry, I'm having trouble right now. Please try again."
Zelfs als providers perfect werken, krijgen gebruikers nog een ander probleem: frustrerende wachttijd. Iemand klikt op verzenden in je app en ziet enkele seconden niets. Ze vragen zich af of er iets kapot is.
Streaming voor realtime responses
De meeste AI-API-responses komen als één compleet blok binnen, zoals het downloaden van een bestand. Gebruikers wachten zonder feedback tot de hele response klaar is. Streaming verandert dit door tekst te tonen terwijl die wordt gegenereerd, woord voor woord.
Waarom streaming de gebruikerservaring verandert
In plaats van te wachten op de complete response, toont streaming tekst terwijl de AI die genereert. Bekijk het verschil:
import litellm
from dotenv import load_dotenv
load_dotenv()
messages = [{"role": "user", "content": "What is Python in one sentence?"}]
response = litellm.completion(
model="gpt-5",
messages=messages,
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
Python is a high-level, interpreted, dynamically typed, general-purpose programming language known for its readability and vast ecosystem, used across web development, data science, automation, scripting, and more.
De tekst verschijnt geleidelijk in plaats van in één keer (als je het fragment hierboven op je machine uitvoert). Gebruikers zien direct voortgang, wat veel responsiever aanvoelt dan naar een laadspinner staren.
Hoe streaming daadwerkelijk werkt
Dit werkt op chunk-niveau. In plaats van één grote response krijg je veel kleine stukjes, deltas genoemd. Soms zijn chunks leeg, dus je moet ze veilig afhandelen:
response = litellm.completion(
model="anthropic/claude-sonnet-4-20250514",
messages=[{"role": "user", "content": "Define JavaScript in exactly two sentences"}],
stream=True
)
for chunk in response:
if hasattr(chunk.choices[0].delta, 'content') and chunk.choices[0].delta.content:
print(f"'{chunk.choices[0].delta.content}'", end=" ")
'JavaScript is a high' '-level, interpreted programming language primarily used for creating' ' interactive and dynamic content on web pages, running' ' in web browsers to manip' 'ulate HTML elements, handle user events' ', and communicate with servers.' ' Originally designed for client-side web development, JavaScript has evolve' 'd into a versatile language that can also' ' be used for server-side development, mobile applications' ', and desktop software through various runtime' ' environments like Node.js.'
Streaming herbruikbaar maken
Voor echte applicaties wil je de volledige response vastleggen terwijl je de streamingoutput blijft tonen. Hier is een functie om dat te doen:
def stream_and_capture(model, messages):
"""Stream response while capturing the complete text"""
response = litellm.completion(
model=model,
messages=messages,
stream=True
)
full_response = ""
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
print(content, end="", flush=True)
full_response += content
print() # New line after response
return full_response
# Test it
messages = [{"role": "user", "content": "Define APIs in 2 sentences max"}]
result = stream_and_capture("gpt-5", messages)
APIs (Application Programming Interfaces) are standardized contracts, often exposed as endpoints, that specify how software components or services can communicate, including the allowed operations, inputs, and outputs. They let developers access functionality or data without knowing the underlying implementation, enabling modular, interoperable systems.
De parameter end="" voorkomt regeleinden tussen chunks. flush=True forceert directe weergave in plaats van buffering.
Streaming met fallbacks
Je kunt streaming ook combineren met het fallbacksysteem voor meer betrouwbaarheid:
response = litellm.completion(
model="gpt-5",
messages=[{"role": "user", "content": "Define machine learning in one sentence"}],
fallbacks=["anthropic/claude-sonnet-4-20250514"],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
Machine learning is a branch of artificial intelligence where algorithms learn patterns from data to make predictions or decisions without being explicitly programmed.
Directe feedback plus automatisch wisselen van provider als het primaire model faalt.
Streaming geeft gebruikers directe feedback, maar je krijgt nog een ander probleem bij het bouwen van echte applicaties. Zodra die tekst binnenkomt, moet je code ermee werken. Je wilt misschien data extraheren, informatie opslaan in databases of waarden doorgeven aan andere functies. Maar tekstresponses parsen is rommelig en breekt snel als het formaat verandert.
Gestructureerde outputs gebruiken
Dit is wat er daadwerkelijk gebeurt: je bouwt een app die klantfeedback analyseert. Je AI retourneert tekst zoals “De sentiment-score is positief met vertrouwen 0,85 en top-trefwoorden: responsief, behulpzaam, snel.” Je schrijft regex-patronen om de vertrouwensscore en trefwoorden te extraheren. Alles werkt tijdens het testen.
Dan verandert de AI het responseformaat lichtjes naar “Sentiment: positief (confidence: 0,85). Trefwoorden zijn onder meer responsief, behulpzaam en snel.” Je regex breekt. Je datapijplijn stopt met werken. Klantsentimentrapporten tonen lege waarden in plaats van scores. Je dashboard crasht. Je bent uren bezig met het repareren van parsecode die gisteren nog werkte.
Gestructureerde outputs omzeilen dit probleem door vanaf het begin data in voorspelbare formaten terug te geven.
JSON in plaats van tekst krijgen
LiteLLM kan JSON retourneren in plaats van platte tekst. Je geeft via je prompt aan welke structuur je wilt, en het komt correct geformatteerd terug:
import litellm
from dotenv import load_dotenv
load_dotenv()
messages = [{"role": "user", "content": "Describe Python as a programming language. Return as JSON with fields: language, difficulty, description"}]
response = litellm.completion(
model="gpt-5",
messages=messages,
response_format={"type": "json_object"}
)
print(response.choices[0].message.content)
{
"language": "Python",
"difficulty": "Beginner-friendly (easy to learn, moderate to master)",
"description": "Python is a high-level, interpreted, dynamically typed, general-purpose programming language focused on readability and developer productivity. It supports multiple paradigms (object-oriented, functional, procedural), uses indentation for block structure, and includes a large standard library with an extensive third-party ecosystem (PyPI). Common uses include web development, data science, machine learning, automation/scripting, scientific computing, and DevOps. While not the fastest for CPU-bound tasks, it integrates well with C/C++ and accelerators, and runs cross-platform."
}
Deze gestructureerde aanpak elimineert veelvoorkomende parseproblemen. In plaats van door tekst te speuren, krijg je geldige JSON terug met precies de velden die je hebt gevraagd. Geen parsehoofdpijn, geen formatsurprises.
Werken met de JSON-data
Ruwe JSON-strings zijn niet nuttig totdat je ze omzet naar Python-objecten waar je applicatie mee kan werken. Je moet die string omzetten naar Python-objecten die je daadwerkelijk kunt gebruiken:
import json
messages = [{"role": "user", "content": "Describe JavaScript in 2 sentences. Return as JSON with fields: name, paradigm, use_cases (array of exactly 3 items)"}]
response = litellm.completion(
model="anthropic/claude-sonnet-4-20250514",
messages=messages,
response_format={"type": "json_object"}
)
# Parse the JSON response
data = json.loads(response.choices[0].message.content)
print(f"Language: {data['name']}")
print(f"Paradigm: {data['paradigm']}")
print(f"Use cases: {', '.join(data['use_cases'])}")
Language: JavaScript
Paradigm: multi-paradigm (object-oriented, functional, event-driven)
Use cases: web development and browser scripting, server-side development with Node.js, mobile app development with frameworks like React Native
Nu je gestructureerde data hebt, kun je die direct doorgeven aan andere functies, opslaan in databases of tonen in je UI zonder tekstmanipulatie. Voor data-analyseworkflows kunnen tools zoals Pandas AI direct met deze gestructureerde output werken om inzichten te genereren.
Typesafety toevoegen met Pydantic
JSON-parsing vangt syntaxisfouten, maar onjuiste datatypen of ontbrekende velden zijn andere problemen. Pydantic‑modellen lossen dit op door je datastructuur te valideren en problemen te detecteren voordat ze je applicatie breken:
from pydantic import BaseModel
import json
class ProgrammingLanguage(BaseModel):
name: str
paradigm: str
use_cases: list[str]
messages = [{"role": "user", "content": "Describe CSS briefly. Return as JSON with fields: name, paradigm, use_cases (array of 3 items)"}]
response = litellm.completion(
model="gpt-5",
messages=messages,
response_format={"type": "json_object"}
)
# Parse and validate with Pydantic
data = json.loads(response.choices[0].message.content)
language = ProgrammingLanguage(**data)
print(f"Validated data: {language.name} - {language.paradigm}")
print(f"Use cases: {language.use_cases}")
Validated data: CSS (Cascading Style Sheets) - Declarative, rule-based stylesheet language for describing the presentation of structured documents.
Use cases: ['Styling layout, colors, and typography of web pages', 'Responsive design across devices and viewports', 'Animations, transitions, and visual effects']
Pydantic valideert automatisch dat name en paradigm strings zijn, en use_cases een lijst van strings. Als de AI de verkeerde types retourneert of een verplicht veld vergeet, krijg je een duidelijke fout in plaats van later mysterieuze bugs.
JSON-fouten afhandelen
JSON-parsing kan mislukken als de AI ongeldige JSON of geen JSON-tekst terugstuurt. Voeg eenvoudige foutafhandeling toe:
import json
messages = [{"role": "user", "content": "Summarize machine learning in 1 sentence. Return as JSON with topic and summary fields"}]
try:
response = litellm.completion(
model="anthropic/claude-sonnet-4-20250514",
messages=messages,
response_format={"type": "json_object"}
)
data = json.loads(response.choices[0].message.content)
print(f"Topic: {data['topic']}")
print(f"Summary: {data['summary']}")
except json.JSONDecodeError:
print("Invalid JSON returned")
except Exception as e:
print(f"Request failed: {e}")
Topic: machine learning
Summary: Machine learning is a subset of artificial intelligence that allows computers to learn and make predictions or decisions from data without being explicitly programmed for each specific task.
Gestructureerde outputs vervangen rommelig tekstparsen door schone datastructuren. Je kunt JSON-modus combineren met fallbacks net als bij gewone completions.
Gestructureerde outputs geven je schone, voorspelbare data die je parse-logica niet breken. Maar er is nog een ander probleem wanneer je van prototype naar productie gaat: de rekening. Elke API-call kost geld, en die kosten kunnen je verrassen.
Kostentracking
Dit gebeurt er: je prototype werkt prima tijdens het testen met 50 API-calls per dag. Je geeft ongeveer $2 per week uit. Alles lijkt goed. Je gaat live en krijgt 500 gebruikers. Nu maak je 5.000 API-calls per dag. Je maandelijkse rekening schiet omhoog van $8 naar $800.
Zonder kostentracking had je geen waarschuwing. Je kunt niet zien welke features het meest kosten, welke modellen duurder zijn of hoe je voor groei moet budgetteren. Je ontdekt de piek in de rekening weken later als de creditcardafschrift binnenkomt.
LiteLLM houdt precies bij wat je uitgeeft bij alle providers.
Tokengebruik begrijpen
Elke AI-response bevat gedetailleerde gebruiksinformatie die precies laat zien waar je voor wordt gefactureerd:
import litellm
from dotenv import load_dotenv
load_dotenv()
messages = [{"role": "user", "content": "Explain what a REST API is in two sentences"}]
response = litellm.completion(
model="gpt-5",
messages=messages
)
print(f"Response: {response.choices[0].message.content}")
print(f"Prompt tokens: {response.usage.prompt_tokens}")
print(f"Completion tokens: {response.usage.completion_tokens}")
print(f"Total tokens: {response.usage.total_tokens}")
Response: A REST API is a web service that follows the Representational State Transfer architectural style, exposing resources identified by URLs and manipulated with HTTP methods like GET, POST, PUT, and DELETE. It uses stateless client-server communication, cacheability, and uniform representations (often JSON) to support scalable, decoupled interactions.
Prompt tokens: 15
Completion tokens: 201
Total tokens: 216
Inputtokens zijn je prompt, outputtokens zijn de response van de AI. Verschillende providers rekenen verschillende tarieven voor elk type.
Automatische kostencalculatie
Ruwe tokenaantallen vertellen je niet het bedrag in dollars. LiteLLM berekent de werkelijke kosten voor je:
# Get the cost for a completed response
cost = litellm.completion_cost(completion_response=response)
print(f"Total cost: ${cost:.4f}")
Total cost: $0.0020
De prijzendatabase van LiteLLM zet tokens om naar dollars op basis van je model.
Handmatige kostencalculaties
Soms wil je kosten inschatten voordat je een call doet, of kosten berekenen voor tekst die je al hebt:
# Calculate cost without making an API call
prompt_text = "Explain machine learning"
completion_text = "Machine learning is a method of data analysis that automates analytical model building."
estimated_cost = litellm.completion_cost(
model="anthropic/claude-sonnet-4-20250514",
prompt=prompt_text,
completion=completion_text
)
print(f"Estimated cost: ${estimated_cost:.4f}")
Estimated cost: $0.0002
Dit is nuttig voor budgettering en het vergelijken van modellen.
Meerdere API-calls bijhouden
Voor applicaties die veel API-calls doen, kun je cumulatieve kosten bijhouden:
total_cost = 0.0
conversation = [
"What is Python?",
"How do you install Python packages?",
"What are virtual environments?"
]
for i, question in enumerate(conversation):
response = litellm.completion(
model="gpt-5",
messages=[{"role": "user", "content": question}]
)
call_cost = litellm.completion_cost(completion_response=response)
total_cost += call_cost
print(f"Call {i+1}: ${call_cost:.4f}")
print(f"Total cost: ${total_cost:.4f}")
Call 1: $0.0057
Call 2: $0.0134
Call 3: $0.0102
Total cost: $0.0292
Kostentracking helpt je weloverwogen keuzes te maken over welke modellen je gebruikt en verrassingsrekeningen te voorkomen. Zie precies wat elke API-call kost en vergelijk providers.
Conclusie
Je hebt nu de tools om AI-applicaties te bouwen zonder vendor lock-in. Je hebt basis-API-calls, automatische fallbacks, streamingresponses, gestructureerde outputs en kostentracking geleerd.
Dit geeft je de vrijheid om de beste modellen per taak te kiezen. Wissel eenvoudig van provider, stel automatische fallbacks in en houd kosten bij. Als er betere modellen verschijnen, kun je die adopteren zonder je code te herschrijven.
Ik ben een contentmaker op het gebied van data science met meer dan 2 jaar ervaring en een van de grootste achterbannen op Medium. Ik schrijf graag uitgebreide artikelen over AI en ML met een vleugje sarcastische stijl, want je moet toch íets doen om ze wat minder saai te maken. Ik heb meer dan 130 artikelen en een DataCamp-cursus gemaakt, en er is nog een nieuwe in de maak. Mijn content is door meer dan 5 miljoen paar ogen gezien, van wie 20k volgers werden op zowel Medium als LinkedIn.

