Python library for standardization, optimization and monitoring of LLM API calls
Project description
llm-std-lib
Python infrastructure library for production-grade LLM API calls.
One unified async client for OpenAI, Anthropic, Google, Azure OpenAI, AWS Bedrock, Ollama, Groq, and LM Studio — with semantic caching, model routing, resilience, and Prometheus/OTLP observability built in.
Features
| Feature | Description |
|---|---|
| Unified client | LLMClient.acomplete() works across 8 providers with one API |
| Semantic cache | Avoid re-paying for similar prompts (Redis, ChromaDB, Qdrant, Pinecone) |
| Model router | Route by complexity, cost, latency, or round-robin |
| Resilience | Retry, circuit breaker, timeout, and provider fallback chains |
| Middleware | PII redaction, cost tracking, rate limiting — all pluggable |
| Observability | Prometheus and OpenTelemetry (OTLP) exporters, Grafana dashboard included |
| Flexible config | YAML/TOML files, environment variables, HashiCorp Vault, AES-256 encryption |
Installation
# Core only
pip install llm-std-lib
# With common extras
pip install "llm-std-lib[redis,prometheus]"
# Everything
pip install "llm-std-lib[all]"
Available extras: redis, chroma, qdrant, pinecone, prometheus, otlp,
local-embeddings, vault, encryption, all.
Quick start
import asyncio
from llm_std_lib import LLMClient, LLMConfig
config = LLMConfig(
default_model="openai/gpt-4o-mini",
providers={"openai": {"api_key": "sk-..."}},
)
client = LLMClient(config)
async def main():
response = await client.acomplete(
prompt="Explain semantic caching in one sentence.",
)
print(response.text)
print(f"Cost: ${response.cost_usd:.6f} | Latency: {response.latency_ms:.0f}ms")
asyncio.run(main())
Or even shorter — load keys from environment variables:
export OPENAI_API_KEY=sk-...
client = LLMClient.from_env()
response = client.complete("What is the capital of France?") # sync
print(response.text) # Paris
Semantic cache
from llm_std_lib import LLMClient, LLMConfig, SemanticCache
from llm_std_lib.cache.backends.redis import RedisBackend
from llm_std_lib.cache.encoders.openai import OpenAIEncoder
cache = SemanticCache(
backend=RedisBackend(url="redis://localhost:6379"),
encoder=OpenAIEncoder(api_key="sk-..."),
similarity_threshold=0.92,
)
config = LLMConfig(
default_model="openai/gpt-4o-mini",
providers={"openai": {"api_key": "sk-..."}},
cache=cache,
)
client = LLMClient(config)
r1 = await client.acomplete(prompt="What is the capital of France?")
r2 = await client.acomplete(prompt="Tell me the capital city of France.")
print(r2.cached) # True — served from cache
Model router
from llm_std_lib import LLMClient, LLMConfig, ModelRouter
router = ModelRouter.complexity_based(tiers=[
{"models": ["openai/gpt-4o-mini"], "max_complexity": 0.3},
{"models": ["openai/gpt-4o"], "max_complexity": 0.7},
{"models": ["anthropic/claude-opus-3"], "max_complexity": 1.0},
])
client = LLMClient(LLMConfig.from_env(), router=router)
# Model is selected automatically based on prompt complexity
r = await client.acomplete(prompt="Hi") # → gpt-4o-mini
r = await client.acomplete(prompt="Prove Fermat's Last Theorem") # → claude-opus-3
Resilience
from llm_std_lib.resilience import ResilienceEngine
from llm_std_lib.resilience.circuit_breaker import CircuitBreaker
from llm_std_lib.resilience.retry import RetryPolicy
from llm_std_lib.resilience.backend import InMemoryBackend
engine = ResilienceEngine(
breaker=CircuitBreaker(
backend=InMemoryBackend(),
key="openai",
failure_threshold_ratio=0.5,
recovery_timeout=30.0,
),
retryer=RetryPolicy(max_attempts=3, base_delay=0.5),
)
response = await engine.execute(
lambda: client.acomplete(prompt="Hello")
)
Observability
from llm_std_lib.metrics import MetricsCollector, PrometheusExporter
from llm_std_lib.types import RequestContext, ResponseContext
exporter = PrometheusExporter()
collector = MetricsCollector(on_record=exporter.update)
exporter.start_http_server(port=8000) # scrape at http://localhost:8000/metrics
# Attach manually after each response
ctx = RequestContext(prompt="Hello", model="gpt-4o-mini", provider="openai")
response_ctx = await client._dispatch(ctx)
await collector.post_request(ctx, response_ctx)
Import grafana_dashboard.json (included in the repo) for a ready-made Grafana dashboard.
Supported providers
| Provider | Model prefix | Auth env var |
|---|---|---|
| OpenAI | openai/ |
OPENAI_API_KEY |
| Anthropic | anthropic/ |
ANTHROPIC_API_KEY |
| Google Gemini | google/ |
GOOGLE_API_KEY |
| Azure OpenAI | azure/ |
AZURE_OPENAI_API_KEY |
| AWS Bedrock | bedrock/ |
AWS credential chain |
| Ollama (local) | ollama/ |
— |
| Groq | groq/ |
GROQ_API_KEY |
| LM Studio (local) | lm_studio/ |
optional |
Configuration
From environment variables
from llm_std_lib import LLMClient
client = LLMClient.from_env()
From a YAML file
# config.yaml
default_model: openai/gpt-4o-mini
providers:
openai:
api_key: "${OPENAI_API_KEY}"
timeout_ms: 15000
anthropic:
api_key: "${ANTHROPIC_API_KEY}"
from llm_std_lib import LLMConfig
config = LLMConfig.from_file("config.yaml")
From HashiCorp Vault
from llm_std_lib.config import VaultConfig
vault = VaultConfig(url="https://vault.example.com", secret_path="llm/prod")
config = vault.load()
Documentation
- Getting Started Guide
- Configuration Reference
- Cookbook — 20 recipes
- Migration Guide — from LiteLLM, LangChain, raw API calls
- Contributing
License
MIT
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 llm_std_lib-1.0.0.tar.gz.
File metadata
- Download URL: llm_std_lib-1.0.0.tar.gz
- Upload date:
- Size: 107.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
474c6764eedd2391dbb7003db9f66adeb71845858342ffa3c3ec452a2adcfd62
|
|
| MD5 |
1aa8d3c86cf3b20de144b97ad18a3f5a
|
|
| BLAKE2b-256 |
fb834f9c13a8d3bef137ee3bb31da6574e01eb652ae8079ba16420820b460804
|
File details
Details for the file llm_std_lib-1.0.0-py3-none-any.whl.
File metadata
- Download URL: llm_std_lib-1.0.0-py3-none-any.whl
- Upload date:
- Size: 102.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ff307a3cf01ceaa1494aae04cc94992cb500bd6c31334ab2e412e2d62a6dfc1
|
|
| MD5 |
a4073abe9f613e5de21255ad665c8217
|
|
| BLAKE2b-256 |
875dd81477aa12080ae42200687ee84ad0e47fed0fe41c51716873a4bcaa34e7
|