Lightweight multi-provider LLM client for Python
Project description
LLMWire
Lightweight multi-provider LLM client for Python. A single async interface to
OpenAI, Anthropic, and Ollama — with automatic fallback, exponential-backoff retry,
streaming, and structured Pydantic output. No provider SDK dependencies; all requests
go over plain httpx.
Features
- Unified API — one
LLMClientfor all supported providers - Async-first — built entirely on
asyncioandhttpx - Automatic fallback — on provider failure, tries the next provider in the list
- Exponential backoff — configurable retry with full jitter
- Streaming — token-by-token via
client.stream(), async generator interface - Structured output — pass any Pydantic
BaseModelasresponse_model - No provider SDKs — runtime deps are only
httpx,pydantic,pydantic-settings,pyyaml - Environment variable config — all settings readable from
LLMKIT_*env vars
Quick Start
pip install llmwire
Chat
import asyncio
from llmwire import LLMClient, LLMConfig, ProviderConfig
config = LLMConfig(
providers=[
ProviderConfig(name="openai", api_key="sk-...", model="gpt-4o"),
ProviderConfig(name="anthropic", api_key="sk-ant-...", model="claude-3-5-sonnet-20241022"),
]
)
async def main():
async with LLMClient(config) as client:
response = await client.chat("What is the capital of France?")
print(response.content)
# Provider: openai | Model: gpt-4o | Tokens: 42
asyncio.run(main())
Streaming
async def main():
async with LLMClient(config) as client:
async for chunk in client.stream("Write a haiku about async programming."):
print(chunk.content, end="", flush=True)
print()
Structured Output
from pydantic import BaseModel
class Sentiment(BaseModel):
label: str # "positive", "negative", or "neutral"
confidence: float
async def main():
async with LLMClient(config) as client:
result: Sentiment = await client.chat(
"Classify: 'I love this library!'",
response_model=Sentiment,
)
print(result.label, result.confidence) # positive 0.97
Configuration
Direct
from llmwire import LLMConfig, ProviderConfig
config = LLMConfig(
providers=[
ProviderConfig(name="openai", api_key="sk-...", model="gpt-4o"),
ProviderConfig(name="ollama", model="llama3.2"), # no key needed
],
fallback=True, # try next provider on failure (default: True)
max_retries=3, # per-provider retry attempts (default: 3)
timeout=30.0, # request timeout in seconds (default: 30.0)
)
Environment Variables
export LLMKIT_PROVIDERS__0__NAME=openai
export LLMKIT_PROVIDERS__0__API_KEY=sk-...
export LLMKIT_PROVIDERS__0__MODEL=gpt-4o
export LLMKIT_PROVIDERS__1__NAME=anthropic
export LLMKIT_PROVIDERS__1__API_KEY=sk-ant-...
export LLMKIT_PROVIDERS__1__MODEL=claude-3-5-sonnet-20241022
export LLMKIT_FALLBACK=true
export LLMKIT_MAX_RETRIES=3
config = LLMConfig() # reads from environment
Provider Support
| Provider | Chat | Streaming | Auth | Default endpoint |
|---|---|---|---|---|
| OpenAI | yes | yes | API key | https://api.openai.com/v1 |
| Anthropic | yes | yes | API key | https://api.anthropic.com/v1 |
| Ollama | yes | yes | none | http://localhost:11434 |
The base_url field on ProviderConfig lets you point any provider at a compatible
endpoint (e.g. Azure OpenAI, local OpenAI-compatible servers).
Further Reading
- ARCHITECTURE.md — design decisions, component overview, and provider protocol
- CONTRIBUTING.md — dev setup, code style, and how to add a new provider
- Documentation — full API reference and guides
License
MIT. See 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 llmwire-0.1.0.tar.gz.
File metadata
- Download URL: llmwire-0.1.0.tar.gz
- Upload date:
- Size: 20.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86895f31ce6d0ab1687f068ea8eca65639ed8d169244ec76a8d431f3ec7a27a6
|
|
| MD5 |
0b334b9ce34c021d8e4b81c92755212b
|
|
| BLAKE2b-256 |
178e284cc2e70e60d5a74c4995a5e64c8df553172734ba4a0e41fbe08a7e7b1e
|
File details
Details for the file llmwire-0.1.0-py3-none-any.whl.
File metadata
- Download URL: llmwire-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70bc88679e5a6e663f6fd3d0c4d4c1fc2dc8a35860a382a681769f47cac61ecd
|
|
| MD5 |
64e80dc2663d755287033aba9e762aeb
|
|
| BLAKE2b-256 |
a89e50e3e88d4ec8d19e41522f956d80eca78429500a112d83026ab4dfc6d7d0
|