Unified Python interface for OpenAI, Anthropic, Google, and Ollama LLMs
Project description
LLMRing
A comprehensive Python library for LLM integration with unified interface, advanced features, and MCP support. Supports OpenAI, Anthropic, Google Gemini, and Ollama with consistent APIs.
โจ Key Features
- ๐ Unified Interface: Single API for all major LLM providers
- โก Streaming Support: Real streaming for all providers (not simulated)
- ๐ ๏ธ Native Tool Calling: Provider-native function calling with consistent interface
- ๐ Unified Structured Output: JSON schema works across all providers with automatic adaptation
- ๐ Alias Management: Semantic model aliases via lockfile (
deep,fast,balanced) - ๐ฐ Cost Tracking: Automatic cost calculation and receipt generation
- ๐ฏ Registry Integration: Centralized model capabilities and pricing
- ๐ง Advanced Features:
- OpenAI: JSON schema, o1 models, PDF processing
- Anthropic: Prompt caching (90% cost savings)
- Google: Native function calling, multimodal, 2M+ context
- Ollama: Local models, streaming, custom options
- ๐ Type Safety: Comprehensive typed exceptions and error handling
- ๐ MCP Integration: Model Context Protocol support for tool ecosystems
๐ Quick Start
Installation
# With uv (recommended)
uv add llmring
# With pip
pip install llmring
Basic Usage
from llmring.service import LLMRing
from llmring.schemas import LLMRequest, Message
# Initialize service (auto-detects API keys)
service = LLMRing()
# Simple chat
request = LLMRequest(
model="openai:gpt-4o",
messages=[
Message(role="system", content="You are a helpful assistant."),
Message(role="user", content="Hello!")
]
)
response = await service.chat(request)
print(response.content)
Streaming
# Real streaming for all providers
request = LLMRequest(
model="anthropic:claude-3-5-sonnet",
messages=[Message(role="user", content="Count to 10")],
stream=True
)
async for chunk in await service.chat(request):
print(chunk.delta, end="", flush=True)
Tool Calling
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}]
request = LLMRequest(
model="google:gemini-1.5-pro",
messages=[Message(role="user", content="What's the weather in NYC?")],
tools=tools
)
response = await service.chat(request)
if response.tool_calls:
print("Function called:", response.tool_calls[0]["function"]["name"])
๐ง Advanced Features
๐ฏ Unified Structured Output (All Providers)
# Same JSON schema API works across ALL providers!
request = LLMRequest(
model="anthropic:claude-3-5-sonnet", # Works with any provider
messages=[Message(role="user", content="Generate a person")],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string"}
},
"required": ["name", "age"]
}
},
"strict": True # Validates across all providers
}
)
response = await service.chat(request)
print("JSON:", response.content) # Valid JSON string
print("Data:", response.parsed) # Python dict ready to use
Provider-Specific Parameters
# Anthropic: Prompt caching for 90% cost savings
request = LLMRequest(
model="anthropic:claude-3-5-sonnet",
messages=[
Message(
role="system",
content="Very long system prompt...", # 1024+ tokens
metadata={"cache_control": {"type": "ephemeral"}}
),
Message(role="user", content="Hello")
]
)
# Extra parameters for provider-specific features
request = LLMRequest(
model="openai:gpt-4o",
messages=[Message(role="user", content="Hello")],
extra_params={
"logprobs": True,
"top_logprobs": 5,
"presence_penalty": 0.1,
"seed": 12345
}
)
Model Aliases
# Initialize lockfile with smart defaults
llmring lock init
# Use semantic aliases instead of specific models
request = LLMRequest(
model="deep", # โ claude-3-opus (powerful reasoning)
model="fast", # โ gpt-4o-mini (quick responses)
model="balanced", # โ claude-3-5-sonnet (best overall)
messages=[Message(role="user", content="Hello")]
)
๐ช Raw SDK Access (Escape Hatch)
When you need the full power of the underlying SDKs:
# Access any provider's raw client for maximum SDK features
openai_client = service.get_provider("openai").client # openai.AsyncOpenAI
anthropic_client = service.get_provider("anthropic").client # anthropic.AsyncAnthropic
google_client = service.get_provider("google").client # google.genai.Client
ollama_client = service.get_provider("ollama").client # ollama.AsyncClient
# Use any SDK feature not exposed by LLMRing
response = await openai_client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
logprobs=True,
top_logprobs=10,
parallel_tool_calls=False,
# Any OpenAI parameter
)
# Anthropic with all SDK features
response = await anthropic_client.messages.create(
model="claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=100,
top_p=0.9,
top_k=40,
system=[{
"type": "text",
"text": "You are helpful",
"cache_control": {"type": "ephemeral"}
}]
)
# Google with native SDK features
response = google_client.models.generate_content(
model="gemini-1.5-pro",
contents="Hello",
generation_config={
"temperature": 0.7,
"top_p": 0.8,
"top_k": 40,
"candidate_count": 3
},
safety_settings=[{
"category": "HARM_CATEGORY_HARASSMENT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
}]
)
When to use raw clients:
- Advanced SDK features not in LLMRing
- Provider-specific optimizations
- Complex configurations
- Performance-critical applications
๐ Provider Support
| Provider | Models | Streaming | Tools | Special Features |
|---|---|---|---|---|
| OpenAI | GPT-4o, GPT-4o-mini, o1 | โ Real | โ Native | JSON schema, PDF processing |
| Anthropic | Claude 3.5 Sonnet/Haiku | โ Real | โ Native | Prompt caching, large context |
| Gemini 1.5/2.0 Pro/Flash | โ Real | โ Native | Multimodal, 2M+ context | |
| Ollama | Llama, Mistral, etc. | โ Real | ๐ง Prompt | Local models, custom options |
๐ฆ Setup
Environment Variables
# Add to your .env file
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_GEMINI_API_KEY=AIza...
# Optional
OLLAMA_BASE_URL=http://localhost:11434 # Default
Dependencies
# Required for specific providers
pip install openai>=1.0 # OpenAI
pip install anthropic>=0.67 # Anthropic
pip install google-genai # Google Gemini
pip install ollama>=0.4 # Ollama
๐ MCP Integration
from llmring.mcp.client.enhanced_llm import create_enhanced_llm
# Create MCP-enabled LLM with tool ecosystem
llm = await create_enhanced_llm(
model="openai:gpt-4o",
mcp_server_path="path/to/mcp/server"
)
# Now has access to MCP tools
response = await llm.chat([
Message(role="user", content="Use available tools to help me")
])
๐ Documentation
- Provider Usage Guide - Provider-specific features and examples
- API Reference - Detailed API documentation
- Structured Output - Unified JSON schema across all providers
- MCP Integration - Model Context Protocol guide
- Examples - Working code examples
๐งช Development
# Install for development
uv sync --group dev
# Run tests
uv run pytest
# Lint and format
uv run ruff check src/
uv run ruff format src/
๐ ๏ธ Error Handling
LLMRing uses typed exceptions for better error handling:
from llmring.exceptions import (
ProviderAuthenticationError,
ModelNotFoundError,
ProviderRateLimitError,
ProviderTimeoutError
)
try:
response = await service.chat(request)
except ProviderAuthenticationError:
print("Invalid API key")
except ModelNotFoundError:
print("Model not supported")
except ProviderRateLimitError as e:
print(f"Rate limited, retry after {e.retry_after}s")
๐ฏ Key Benefits
- ๐ Unified Interface: Switch providers without code changes
- โก Performance: Real streaming, prompt caching, optimized requests
- ๐ก๏ธ Reliability: Circuit breakers, retries, typed error handling
- ๐ Observability: Cost tracking, usage analytics, receipt generation
- ๐ง Flexibility: Provider-specific features + raw SDK access
- ๐ Standards: Type-safe, well-tested, production-ready
๐ License
MIT License - see LICENSE file for details.
๐ค Contributing
- Fork the repository
- Create a feature branch
- Add tests for your changes
- Ensure all tests pass:
uv run pytest - Submit a pull request
๐ Examples
See the examples/ directory for complete working examples:
- Basic chat and streaming
- Tool calling and function execution
- Provider-specific features
- MCP integration
- Cost tracking and receipts
LLMRing: The comprehensive LLM library for Python developers ๐
Project details
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 llmring-0.4.0.tar.gz.
File metadata
- Download URL: llmring-0.4.0.tar.gz
- Upload date:
- Size: 155.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2724b35b02586f0112781458e8afbc8c9c3246433a23dd6af6830624fd6ea54
|
|
| MD5 |
2a1bbb6ee44b7e4fa6e0245467336499
|
|
| BLAKE2b-256 |
de1d89c6e5e84df97fad90d51f9dd357ca5b4f855ca83385471ab877d453f1b6
|
File details
Details for the file llmring-0.4.0-py3-none-any.whl.
File metadata
- Download URL: llmring-0.4.0-py3-none-any.whl
- Upload date:
- Size: 199.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e1d8d9fef199223cb48ef4407fdc4e958ac08fdde1f5c16a7d1f6ff35ad898d
|
|
| MD5 |
f95d248cb8de4260fe4b0df9f8b3940d
|
|
| BLAKE2b-256 |
d474bf6abbef805df1b41f93312438431ec686ede9f354710f8ac753e27daad1
|