PyInferenceManager
A multi-provider LLM inference orchestrator with cost/latency-aware routing, real retry + budget guardrails, and local-first execution.
Routes requests to Anthropic Claude, OpenAI GPT, Google Gemini, or a local Ollama model based on task complexity, privacy, and observed provider health — with real retry/backoff on failures and a real spend cap you configure.
What this actually is
The core (Rust, ~11k lines, PyO3 bindings) is a workload orchestrator: it builds a small execution DAG for a task, profiles your local hardware, picks an engine (local Ollama model vs. a cloud provider) based on complexity/privacy/cost, executes with real retry and budget enforcement, and semantically caches results.
The Python API surface is a single Orchestrator class. There is no Manager.chat(), no streaming API, and no 11-provider marketplace — see Providers for the honest list.
Install
pip install pyinferencemanager
Requires Python 3.10+.
Set whichever provider keys you plan to use (none are required for local-only Ollama use):
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
export GEMINI_API_KEY=... # or GOOGLE_API_KEY
See .env.example.
Quick start
from pyinferencemanager import Orchestrator
orchestrator = Orchestrator(mode="local_first") # or "cloud_first"
result = orchestrator.run(task="question_answering", message="What is the capital of France?")
print(result.output)
print(f"Engines used: {result.engines_used}")
print(f"Cost: ${result.total_cost_usd:.4f} | Latency: {result.total_latency_ms}ms | Tokens: {result.total_tokens}")
mode="local_first" runs on your local Ollama model when it's adequate for the task's complexity and escalates to a cloud provider otherwise. mode="cloud_first" prefers a cloud provider, falling back to local only for very low-complexity tasks. privacy="high" on any call always forces local execution regardless of mode.
If the selected backend is unreachable or unauthenticated, run() doesn't raise — it returns a result whose output says so (e.g. "[cloud inference unavailable: ...]"), so a single bad provider doesn't crash your pipeline.
Core API
orchestrator = Orchestrator(mode="local_first")
# Execute a task — real inference against Ollama or a cloud provider.
result = orchestrator.run(task="...", file=None, message=None, privacy="low")
# result.output, .total_tokens, .total_cost_usd, .total_latency_ms, .engines_used, .cache_hits
# Estimate cost/latency without executing anything.
plan = orchestrator.plan("Summarize this document")
# plan.stages, .estimated_cost_usd, .estimated_latency_ms, .local_first
# Real-time provider health, from actually completed cloud calls.
orchestrator.provider_ranking() # [(provider_key, health_score), ...]
orchestrator.provider_performance() # {provider_key: {success_rate, avg_latency_ms, ...}}
# Cost guardrails, enforced on every real cloud call.
orchestrator.configure_budget(max_cost_usd=10.0, max_requests=1000,
alert_threshold_percent=80.0, enforce_hard_limit=True)
orchestrator.budget_status()
# Retry/backoff policy for retryable errors (HTTP 429/408/5xx).
orchestrator.configure_retry(max_attempts=3, backoff="exponential",
initial_ms=100, max_ms=5000)
# Synthetic load test exercising the same budget + dynamic-routing logic
# run() uses, at a volume impractical against live APIs. Latencies/costs
# here are simulated, not real network calls.
orchestrator.run_load_test(num_requests=200, budget_usd=5.0)
# Local hardware profile (memory tier, Apple Silicon/Metal, Ollama models).
orchestrator.profile_hardware()
orchestrator.available_backends()
See examples/ for runnable scripts covering each of these.
Providers
Real HTTP calls, with retry/backoff and cost tracking:
| Provider | Env var | Notes |
|---|---|---|
| Anthropic Claude | ANTHROPIC_API_KEY |
claude-haiku-4-5, claude-opus-4-1 |
| OpenAI | OPENAI_API_KEY |
gpt-4o-mini |
| Google Gemini | GEMINI_API_KEY / GOOGLE_API_KEY |
gemini-1.5-flash |
| Ollama (local) | — | whatever models you've pulled locally |
| vLLM (local) | — | OpenAI-compatible endpoint, default localhost:8000 |
Additionally, tensorrt_llm, mlc_llm, and colibri exist as cost-estimator-only stubs (BackendKind/RuntimeBackend trait implementations with real cost/latency estimation logic, but no live inference) — they're placeholders for self-hosted inference servers, not currently wired to make real calls. orchestrator.available_backends() lists all of these honestly, including the stubs.
Cloud execution dispatches through BackendRegistry/RuntimeBackend (not a hand-matched provider enum): ProviderExecutor::execute maps a CloudProvider to its BackendKind, registers the one backend it needs (reading the API key from the env vars above), and calls it through the same RuntimeBackend::infer trait object every backend implements — so adding a new cloud provider is a new BackendKind/backend + one dispatch arm, not edits scattered across every call site that used to match the old enum.
MCP tools
pyinferencemanager._mcp_tools.PyInferenceManagerMCPHandler exposes 13 MCP-style tools (list_available_models, execute_inference, estimate_inference_cost, get_provider_status, etc.), all backed by a real Orchestrator instance — no hardcoded responses. See examples/mcp_pyinferencemanager.py.
The network connector (_mcp_connector.InferenceManager.start_mcp_connector()) binds to 127.0.0.1 by default with scoped CORS and permissions; binding elsewhere requires passing allow_remote=True explicitly.
Testing
- Rust core:
cargo test --workspace(350+ tests, including HTTP-mocked request/response tests for every cloud client viawiremock). - Python:
pytest tests/— coversOrchestrator.run/plan/provider_ranking, the MCP tool handlers, budget/retry configuration, load testing, and MCP connector security defaults, all without requiring live API keys.
Known issues
tensorrt_llm,mlc_llm, andcolibribackends are cost-estimator-only stubs (see Providers) — they do not make live inference calls yet.vllmwas a stub too as of 1.2.0 but is now a real backend.- No open GitHub issues and no
TODO/FIXMEmarkers in the codebase at the time of this writing.
License
Proprietary License — free to use with explicit attribution. See LICENSE.
Release files for pyinferencemanager 1.3.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 | |
|---|---|---|---|
| pyinferencemanager-1.3.0.tar.gz | 113.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyinferencemanager-1.3.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 3.7 MB
Release files / pyinferencemanager-1.3.0.tar.gz
| Download URL | pyinferencemanager-1.3.0.tar.gz |
|---|---|
| Size | 113.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9957d8e42546d6a1d18342a76d01b55c2fe3c2dc8ec374cddcd8d7040d3bd579
|
|
BLAKE2b-256 checksum How to use checksums |
213667ee094239dc9f6ebbe589b5fa816081eaf4831e8bb13771f4cb63dd3903
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / pyinferencemanager-1.3.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | pyinferencemanager-1.3.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 3.6 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
5f67b613bb1e89e8995c388a50d3237708ee440bb1e62d6011c9bdc5342324d3
|
|
BLAKE2b-256 checksum How to use checksums |
3ef1840791f9851a23f987eb05dccf70702c55c84ae8a485df7f918636bb2fab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|