Universal LLM Client
Swap LLM providers with one command or environment variable. No code changes, no SDK dependencies.
Pure HTTP implementation - works with OpenAI, Anthropic, Google Gemini, and Ollama using standard HTTP requests.
from universal_llm import Settings, get_client, Models
# Use any provider with model constants
settings = Settings(
provider="anthropic",
model=Models.anthropic.CLAUDE_3_5_HAIKU_20241022
)
client = get_client(settings)
response = client.ask("Explain the CAP theorem in 2 sentences.")
print(response)
Installation
pip install universal-llm
That's it! All providers work out of the box - no extra dependencies needed.
Quick Start
1. Install from PyPI
pip install universal-llm
2. Set your API key
# For OpenAI
export LLM_API_KEY="your-openai-api-key"
export LLM_PROVIDER="openai"
# For Anthropic
export LLM_API_KEY="your-anthropic-api-key"
export LLM_PROVIDER="anthropic"
# For Google Gemini
export LLM_API_KEY="your-google-api-key"
export LLM_PROVIDER="google"
# For Ollama (local, no API key needed)
export LLM_PROVIDER="ollama"
3. Use in your code
from universal_llm import Settings, get_client
# Settings automatically loads from environment variables
settings = Settings()
client = get_client(settings)
# Simple question
response = client.ask("What is the capital of France?")
print(response)
# Full conversation
messages = [
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hi there!"},
{"role": "user", "content": "How are you?"}
]
response = client.chat_sync(messages)
print(response)
Supported Providers
| Provider | Models | Setup |
|---|---|---|
| OpenAI | gpt-4o, gpt-4o-mini, gpt-3.5-turbo | Get API key from OpenAI |
| Anthropic | claude-3-5-sonnet, claude-3-5-haiku | Get API key from Anthropic |
| Google Gemini | gemini-2.0-flash, gemini-1.5-pro | Get API key from Google AI Studio |
| Ollama | llama3.2, qwen2.5, etc. | Install Ollama locally |
Configuration Options
Environment Variables
LLM_PROVIDER- Provider name (openai, anthropic, google, ollama)LLM_MODEL- Model nameLLM_API_KEY- API key (not needed for Ollama)LLM_BASE_URL- Custom base URLLLM_TEMPERATURE- Temperature (default: 0.2)LLM_TIMEOUT- Timeout in seconds (default: 60)
Programmatic Configuration
from universal_llm import Settings, get_client, Models
# Override any setting with model constants
settings = Settings(
provider="openai",
model=Models.openai.GPT_4O_MINI,
api_key="your-key-here",
temperature=0.7
)
client = get_client(settings)
Model Constants
Universal LLM provides constants for all supported models, updated regularly:
from universal_llm import Models, OpenAIModels, AnthropicModels
# Access models by provider
print(f"Latest OpenAI model: {OpenAIModels.GPT_4O}")
print(f"Fast Anthropic model: {AnthropicModels.CLAUDE_3_5_HAIKU_20241022}")
# Get recommended models
fast_model = Models.get_recommended_model("openai", "fast") # gpt-4o-mini
balanced_model = Models.get_recommended_model("anthropic", "balanced") # claude-3-5-sonnet
# List all models for a provider
all_openai = Models.get_all_models("openai")
print(f"OpenAI has {len(all_openai)} models available")
# Validate model names
is_valid = Models.is_valid_model("google", "gemini-2.0-flash") # True
Available Model Categories
OpenAI: GPT-4.1, GPT-4o, O3/O4 reasoning models, GPT-3.5 Turbo
Anthropic: Claude 4 (Opus/Sonnet), Claude 3.7 Sonnet, Claude 3.5 Sonnet/Haiku
Google: Gemini 2.5 Pro/Flash, Gemini 2.0 Flash, Gemini 1.5 models, embeddings
Ollama: Llama3, Mistral, LLaVA (multimodal), SmolLM2, and more
Use universal-llm list-models to see all current models. Constants are updated with each release.
CLI Usage
Universal LLM includes a command-line interface:
# Interactive setup
universal-llm configure
# Quick question
universal-llm ask "What is Python?"
# Interactive chat
universal-llm chat
# Set provider
universal-llm set-provider openai
universal-llm set-key # Will prompt for API key
# Show current config
universal-llm show-config
# List available models
universal-llm list-models # All providers
universal-llm list-models --provider openai # Specific provider
Advanced Usage
Streaming Responses
import asyncio
from universal_llm import Settings, get_client
async def stream_example():
settings = Settings(provider="openai")
client = get_client(settings)
async for chunk in await client.chat([
{"role": "user", "content": "Count from 1 to 10"}
], stream=True):
if isinstance(chunk, str):
print(chunk, end="")
print()
asyncio.run(stream_example())
Provider-Specific Options
# OpenAI-specific options
response = client.chat_sync(messages,
max_tokens=100,
response_format={"type": "json_object"},
tools=[...])
# Anthropic-specific options
response = await client.chat(messages,
max_tokens=100,
stop_sequences=["END"],
system="You are a helpful assistant")
# Ollama-specific options
response = client.chat_sync(messages,
options={"temperature": 0.8, "num_ctx": 4096})
Error Handling
from universal_llm import Settings, get_client, LLMError
try:
client = get_client(Settings(provider="openai", api_key="invalid"))
response = client.ask("Hello")
except LLMError as e:
print(f"Error: {e}")
print(f"Error code: {e.code}")
print(f"Provider: {e.provider}")
Why Universal LLM?
- No SDK dependencies - Pure HTTP implementation, no vendor lock-in
- Consistent interface - Same code works with any provider
- Provider flexibility - Switch providers with one environment variable
- Production ready - Proper error handling, streaming, timeouts
- Local development - Works with Ollama for offline development
- Simple setup - Single pip install, no complex configuration
Contributing
See CLAUDE.md for development setup and architecture details.
Metadata
Release files for universal-llm 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| universal_llm-0.2.0.tar.gz | 85.1 kB | Without provenance | Details for universal_llm-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| universal_llm-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for universal_llm-0.2.0-py3-none-any.whl |
Total release size: 100.7 kB
Release files / universal_llm-0.2.0.tar.gz
| Download URL | universal_llm-0.2.0.tar.gz |
|---|---|
| Size | 85.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
71e4e86a8d7e406b7a8f7bc8a00094953a28a4f8684d120ffd16d7ccc88bd019
|
|
BLAKE2b-256 checksum How to use checksums |
fb24403e5ba696026cc2c79af30207a3e37e98abb18db2049332e8313b03db43
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.10.12
|
Release files / universal_llm-0.2.0-py3-none-any.whl
| Download URL | universal_llm-0.2.0-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
739771749f6e97ed2dd938b93e857b905794ca3330365c74c3ef92c97a5510a6
|
|
BLAKE2b-256 checksum How to use checksums |
c1e4dc48a61faa1e3b668dd8f20ee865298a5ad4e4d91fa5a1afa09c479228a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.10.12
|
Security for universal-llm 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.