A production-ready routing, fallback, and rate-limiting client for OpenAI-compatible LLM endpoints.
Project description
LLMSwitch
A lightweight, production-ready routing and fallback client for LLM providers. It acts as a proxy for the official OpenAI Python SDK, implementing priority-based fallbacks, circuit breakers (with smart Retry-After header parsing), and client-side token/request rate limits.
Features
- Priority-Based Fallback Routing: Define a model alias (e.g.
gpt-4o) mapping to a list of provider endpoints (e.g., OpenAI, OpenRouter, Anthropic). If one fails, it automatically routes to the next candidate. - Async & Sync Support: Native implementation for both
ClientandAsyncClientmirroring the standard OpenAI interface. - Circuit Breaker on 429: Temporarily cools down rate-limited providers.
- Smart Retry-After Parsing: Extracts precise cooldown times from HTTP headers (standard
Retry-Afterand custom OpenAI reset headers). - Client-Side Rate Limiting: Token-bucket rate limiter that enforces configured requests-per-minute (RPM) and tokens-per-minute (TPM) limits locally.
- Streaming Fallback: Gracefully falls back to secondary endpoints if initial streaming connection fails.
- Client Pooling: Reuses underlying
OpenAIandAsyncOpenAIinstances to optimize connection pooling.
Installation
Add it to your Python project using pip:
pip install llmswitch-client
Or using uv:
uv add llmswitch-client
Quickstart
1. Define Configuration
Configure virtual model aliases and register their respective target endpoints:
from llmswitch import LLMSwitchConfig, Endpoint
# Configure gpt-4o fallback path
gpt4o_config = LLMSwitchConfig(
alias="gpt-4o",
endpoints=[
Endpoint(
provider="openai",
base_url="https://api.openai.com/v1",
api_key="your-openai-api-key",
model="gpt-4o"
),
Endpoint(
provider="openrouter",
base_url="https://openrouter.ai/api/v1",
api_key="your-openrouter-api-key",
model="openai/gpt-4o"
)
]
)
2. Synchronous Client
Use the client exactly like the official OpenAI Python SDK:
from llmswitch import Client
client = Client(configs=gpt4o_config)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Tell me a joke!"}]
)
print(response.choices[0].message.content)
3. Asynchronous Client
Use the AsyncClient for asynchronous python runtimes (FastAPI, Quart, asyncio, etc.):
import asyncio
from llmswitch import AsyncClient
async def main():
client = AsyncClient(configs=gpt4o_config)
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Tell me a story!"}]
)
print(response.choices[0].message.content)
asyncio.run(main())
Advanced Usage
Local Preemptive Rate Limiting (TPM / RPM)
Avoid sending calls that you know will fail. You can enforce token-bucket rate limits client-side by setting limits on endpoints. If an endpoint is rate-limited locally, the client will bypass it:
from llmswitch import Endpoint, RateLimit
endpoint_with_limits = Endpoint(
provider="openai",
base_url="https://api.openai.com/v1",
api_key="your-api-key",
model="gpt-4o",
limits=RateLimit(
rpm=10, # 10 requests per minute
tpm=40000 # 40k tokens per minute
)
)
Routing Strategies
You can configure different strategies to distribute load across your endpoints:
"priority"(default): Tries endpoints strictly in the order they are listed in configuration."round_robin": Cycles the starting endpoint for each request, distributing traffic evenly."random": Randomly shuffles the endpoints list on every request.
round_robin_config = LLMSwitchConfig(
alias="gpt-4o",
strategy="round_robin", # Can also be "random" or "priority"
endpoints=[...]
)
Streaming with Fallback
Streaming works out-of-the-box. If the initial stream setup fails, LLMSwitch falls back to the next healthy provider:
# Sync Streaming
stream = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Write a long essay."}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
# Async Streaming
stream = await async_client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Write a long essay."}],
stream=True
)
async for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
Enabling Logs
By default, logs are disabled to keep your logs clean. You can enable them for debugging:
from llmswitch import enable_logging
# Enable and print clean colorized logs to standard output
enable_logging(level="INFO")
License
This project is licensed under the Apache-2.0 License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llmswitch_client-0.0.1.tar.gz.
File metadata
- Download URL: llmswitch_client-0.0.1.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7b223f52b1118432546f265f85423baebd71e3b297460e6f13a34a19e3770ee
|
|
| MD5 |
2ec08a76e90cbda8202ea571e7a5e0e5
|
|
| BLAKE2b-256 |
a030d9727d58fbad9c012fc669cde204e73e2b65069b811c96df7792c4a4e168
|
File details
Details for the file llmswitch_client-0.0.1-py3-none-any.whl.
File metadata
- Download URL: llmswitch_client-0.0.1-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a52956ba30209e89813ae64a2ee68710d073f341014d02982b30640631b79224
|
|
| MD5 |
5f290a48c25ef9c1ccc696f987cae3eb
|
|
| BLAKE2b-256 |
3054d81c79125b909793a466aee3c1e555d76b7234bd61187ebc0b6661cf84c5
|