llm-localfirst
llm-localfirst
Lokal-zuerst-LLM-Routing – behalten Sie sensible Daten und Massentextarbeit auf Ihren eigenen Modellen und rufen Sie die Cloud nur für den schwierigen Teil an.
Die meisten LLM-Router optimieren, welchen Cloud-Anbieter sie für Kosten oder Failover anrufen. llm-localfirst kehrt die Standardeinstellung um: Es läuft zuerst auf Ihrem eigenen lokalen Modell (Ollama / vLLM / LM Studio) und greift nur dann auf die Cloud zu, wenn die Arbeit es wirklich erfordert. Es fügt zwei Dinge hinzu, die Mainstream-Router nicht bieten:
🔒 Datenschutz-Routing, das fail-closed ist. Ein Aufruf, den Sie mit
sensitive=Truekennzeichnen, wird an ein lokales Modell gebunden und darf niemals auf die Cloud zurückfallen. Wenn das lokale Modell nicht verfügbar ist, löst der Aufruf eine Ausnahme aus – er sendet Ihre Eingabe nicht stillschweigend an eine Drittanbieter-API.🤝 Manager-Worker-Delegation. Geben Sie einem Cloud-„Direktor“-Agenten ein Drop-in-Werkzeug, das token-intensive, risikoarme Textarbeit (Zusammenfassen / Entwerfen / Übersetzen / Umformatieren / Extrahieren / Klassifizieren) an einen schnellen lokalen Worker auslagert – das senkt Cloud-Ausgaben und hält Massendaten auf Ihrer Hardware. (Extrahiert aus einem Produktions-Pydantic-AI-Agenten.)
Dazu kommen eine Allowlist-Absicherung für Modelle (beliebige Modellstrings werden abgelehnt – eine SSRF-/Kosten-Kontrollmaßnahme), gecachte Erreichbarkeitsprüfungen, ein MCP-Server-Wrapper und eine CLI.
Die Datenschutzgarantie in fünf Zeilen
from llm_localfirst import Router, LocalUnavailable
router = Router.from_env()
try:
out = router.complete("Redact all PII from this record.",
source=customer_record, sensitive=True)
except LocalUnavailable:
# Local model is down. We did NOT send the record to the cloud. You decide.
...sensitive=True bedeutet diese Daten dürfen das Gerät nicht verlassen. Der Router scheitert lieber, als dass er leakt. Diese Asymmetrie – sensible Aufrufe schlagen fehl, gewöhnliche Massenaufrufe fallen auf die Cloud zurück – ist das Produkt.
Related MCP server: OpenAI-Compatible MCP Gateway
Installation
pip install llm-localfirst # the routing brain — zero provider SDKs
pip install "llm-localfirst[openai]" # + talk to local Ollama/vLLM/LM Studio (and cloud OpenAI)
pip install "llm-localfirst[anthropic]" # + Claude (the default cloud fallback / reason model)
pip install "llm-localfirst[all]" # everything (also: mcp, pydantic-ai)Extra | Fügt hinzu | Benötigt für |
(keine) |
|
|
|
| Ausführen von Aufrufen auf einem lokalen OpenAI-kompatiblen Server (oder Cloud-OpenAI) |
|
| der Standard-Cloud-Fallback / das |
|
|
|
|
| die Manager-Worker- |
Der Entscheidungspfad (decide()) importiert kein Provider-SDK, sodass Sie das Routing – und die gesamte Testsuite – mit nur der Kerninstallation prüfen können.
60-Sekunden-Schnellstart (Ollama)
ollama pull qwen2.5:7b # any OpenAI-compatible local server works
pip install "llm-localfirst[openai,anthropic]"
export ANTHROPIC_API_KEY=sk-ant-... # only needed for the cloud fallback / reason pathfrom llm_localfirst import Router, Kind
router = Router.from_env()
# 1) Inspect routing WITHOUT spending a token.
print(router.decide(kind=Kind.BULK)) # -> local (cheap + private)
print(router.decide(kind="reason")) # -> cloud (the hard part)
print(router.decide(sensitive=True)) # -> local (pinned; never cloud)
# 2) Actually run it. Bulk work prefers local, and falls back to cloud only if local is down.
print(router.complete("Summarize this in one sentence.",
source=long_text, kind=Kind.BULK).text)Oder über die Shell:
llm-localfirst doctor # show config, the allowlist, and local up/down
llm-localfirst route "summarize this" --kind bulk
llm-localfirst route "redact this" --sensitive # exits non-zero if local is down (fail-closed)Wie das Routing entscheidet
decide() prüft, ob Ihr lokales Modell erreichbar ist (gecacht), und wendet dann diese Regeln in der Reihenfolge an:
Aufruf | Lokal verfügbar | Lokal nicht verfügbar |
| lokal | löst |
explizites | – | löst |
| Cloud | Cloud |
| lokal | Cloud-Fallback ( |
explizites | dieses allowlistete Modell (Cloud nur bei sensiblen blockiert) |
Jedes explizite model muss ein Name auf der Allowlist sein; ein beliebiger String (oder eine verirrte URL) löst ModelNotAllowed aus. Diese Allowlist ist die SSRF-/Kosten-Absicherung – ein Aufrufer kann den Router niemals auf einen neuen Endpunkt oder ein teures Modell lenken, das nicht konfiguriert wurde.
Manager-Worker-Delegation (Pydantic AI)
Lassen Sie einen Cloud-Direktor die Planung und Tool-Aufrufe übernehmen und lagern Sie die stupide Textarbeit an einen lokalen Worker aus:
from pydantic_ai import Agent
from llm_localfirst import Router
from llm_localfirst.integrations.pydantic_ai import attach_worker
router = Router.from_env()
director = Agent("anthropic:claude-haiku-4-5", system_prompt="...")
# Adds a `delegate_to_worker(task, source)` tool that routes to your LOCAL model.
# attach_worker REFUSES a non-local worker, so delegated source text can't leak.
attach_worker(director, router, worker_model="local",
on_delegate=lambda task, result: ...) # optional observability hookDer Direktor ruft delegate_to_worker für Zusammenfassungen, Entwürfe, Übersetzungen, Umformatierungen und Extraktionen auf; diese laufen auf Ihrer GPU statt Cloud-Token zu verbrennen. Siehe examples/manager_worker.py.
MCP-nativ
Stellen Sie den Router jedem MCP-Client (Claude Desktop, IDEs, Agenten) als drei Tools bereit – route (trockene Entscheidung), complete und usage (was diese Sitzung ausgegeben hat):
pip install "llm-localfirst[mcp]"
llm-localfirst mcp # serves over stdioCloud-Ausgabenobergrenze
Die Datenschutzgarantie beantwortet die Frage darf dieser Aufruf die Maschine verlassen?. Die andere Frage, die ein lokal-zuerst-Setup beantworten muss, ist wie viel hat das Verlassen der Maschine bereits gekostet?
Jede Vervollständigung wird automatisch erfasst – keine Konfiguration, kein Flag:
router = Router.from_env()
router.complete("summarise this", source=long_document)
router.ledger.calls("cloud") # 1
router.ledger.tokens("local") # Usage(input_tokens=..., output_tokens=...)
router.ledger.snapshot() # JSON-safe, for logsGeben Sie eine Obergrenze vor, und es stoppt, statt zu überziehen – dieselbe Fail-closed-Haltung wie beim Datenschutz-Pin, angewendet auf Geld:
from llm_localfirst import Budget, Router
router = Router(..., budget=Budget(max_cloud_tokens=200_000))
...
llm_localfirst.BudgetExceeded: cloud token budget spent: 203_400/200_000 tokensLokale Aufrufe werden nie begrenzt. Sie zu deckeln würde den Sinn des lokalen Betriebs zunichtemachen – ein erschöpftes Cloud-Budget bedeutet nur, dass die Cloud geschlossen ist, und Massenarbeit fließt weiter.
Oder nach Kosten, was Preise erfordert:
export LF_PRICES='{"haiku": [0.8, 4.0], "sonnet": [3.0, 15.0], "opus": [15.0, 75.0]}'
export LF_MAX_CLOUD_COST=5.00Zwei Dinge, die dies bewusst nicht tut:
Es liefert keine Preistabelle. Preise ändern sich, und eine veraltete hartcodierte Zahl ist schlimmer als keine Zahl. Sie liefern sie – und eine Kostenobergrenze weigert sich zu starten, wenn einem allowlisteten Cloud-Modell ein Preis fehlt, statt still bei
$0.00zu sitzen und nie auszulösen.max_cloud_tokensundmax_cloud_callssind exakt und benötigen keinerlei Konfiguration.Es begrenzt keinen einzelnen Aufruf. Token-Zahlen existieren erst, nachdem der Anbieter geantwortet hat, also blockiert die Obergrenze den nächsten Cloud-Aufruf, nachdem sie überschritten wurde. Sie begrenzt den Überschuss auf einen Aufruf; sie kann keinen einzelnen Aufruf begrenzen.
Das Hauptbuch lebt im Speicher, begrenzt auf einen Router. Es ist eine Leitplanke für einen Prozess, keine Abrechnung – wenn Sie Ausgaben über Prozesse hinweg durchsetzen müssen, persistieren Sie ledger.snapshot() in Ihrem eigenen Speicher.
llm-localfirst complete "..." --usage # tally on stderr, completion on stdout
llm-localfirst doctor # shows the budget and which models are pricedWie es sich vergleicht
llm-localfirst ist kein allgemeiner Multi-Provider-Gateway und will es auch nicht sein. Um klar und fair zu sein: LiteLLM und Bifrost können bereits an lokale Modelle routen (Ollama, vLLM) – lokale Fähigkeit ist nicht das Unterscheidungsmerkmal. Die Unterscheidungsmerkmale sind der Fail-closed-Datenschutz-Pin, das Manager-Worker-Delegationswerkzeug und eine lokal-zuerst-Standardhaltung.
Fähigkeit | llm-localfirst | LiteLLM | OpenRouter | llmrouter-lib |
An lokale Modelle routen (Ollama/vLLM) | ✅ | ✅ | ❌ | ➖ |
Standardhaltung ist lokal-zuerst | ✅ | ❌ (Cloud-Proxy) | ❌ | ➖ |
Sensible Aufrufe schlagen fehl – nie Cloud-Fallback | ✅ | ❌ | ❌ | ❌ |
Manager-Worker-Delegationswerkzeug (Cloud→lokal) | ✅ | ❌ | ❌ | ❌ |
Allowlist-Absicherung (beliebige Modellstrings ablehnen) | ✅ | ➖ | ➖ | ➖ |
Viele Cloud-Anbieter / Lastverteilung / Caching | ➖ (bewusst) | ✅ | ✅ | ➖ |
Wenn Sie ein breites Cloud-Gateway mit Dutzenden von Anbietern möchten, verwenden Sie LiteLLM. Wenn Sie möchten, dass Ihre privaten Daten konstruktionsbedingt lokal bleiben und Ihre Massenarbeit auf Ihrer eigenen Hardware läuft, dann ist das diese Bibliothek.
Was dies NICHT ist
Kein Multi-Cloud-Gateway. Es liefert ein lokales Backend + Claude (+ optional OpenAI). Fügen Sie weitere hinzu, indem Sie sie auf der Allowlist registrieren; es wird keine hundert Provider-Shims bekommen.
Kein Inhaltsklassifikator. Sie kennzeichnen einen Aufruf mit
sensitive=True(oder wählen einkind). Es rät nicht, ob Ihr Text privat ist – es setzt durch, was Sie deklarieren.Keine Lastverteilung oder semantisches Caching. Das sind Gateway-Funktionen; dies ist eine Routing-Richtlinie mit einer Datenschutzgarantie.
Keine Kostenanalyse oder Abrechnung. Die Ausgabenobergrenze ist eine In-Process-Leitplanke, kein Dashboard: Zähler werden zurückgesetzt, wenn der Prozess endet, und es meldet, was der Anbieter gemeldet hat. Für echte Zahlen lesen Sie die Rechnung Ihres Anbieters.
Keine Prompt-Firewall. Es kontrolliert, wo ein Aufruf läuft, nicht was darin ist.
Konfiguration
Alle Einstellungen werden aus der Umgebung (Präfix LF_) oder einer .env-Datei gelesen. Siehe .env.example. Highlights:
Variable | Standard | Bedeutung |
|
| lokaler OpenAI-kompatibler Endpunkt |
|
| lokale Modell-ID |
|
| Cloud-Modell für nicht-sensiblen Fallback |
|
| Cloud-Modell für |
|
| verhindert, dass sensible Aufrufe je leaken |
|
| Sekunden, um die Erreichbarkeitsprüfung zu cachen |
|
|
|
| nicht gesetzt | Obergrenze für Cloud-Aufrufe pro Prozess |
| nicht gesetzt | Obergrenze für Cloud-Token pro Prozess |
| nicht gesetzt | Obergrenze für Cloud-Ausgaben (erfordert |
Entwicklung
uv venv && uv pip install -e '.[dev]'
ruff check . && pytestDas Routing-Gehirn (Richtlinie, Registry, Router, Erreichbarkeit) ist zu 100 % offline abgedeckt – keine Netzwerk- und keine Provider-SDKs erforderlich. Beiträge willkommen; siehe CONTRIBUTING.md.
Lizenz
MIT © Shaxzodbek Qambaraliyev / Blaze. Siehe LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseCqualityDmaintenanceAn MCP server that routes LLM requests across multiple providers and orchestrates other MCP servers, with a focus on local privacy for embeddings and memory.283
- FlicenseNot gradedqualityDmaintenanceLocal MCP server that exposes fixed tools for GPT, Claude, and Gemini while routing to any OpenAI-compatible chat completions backend with independent configuration per target.1
- AlicenseNot gradedqualityBmaintenanceA self-hostable MCP server that routes prompts to multiple LLM providers using declarative policies, with multi-role orchestration for independence and verification.MIT
- AlicenseNot gradedqualityCmaintenancePrivacy-first local MCP hub for coordinating multiple AI providers from Claude Code, supporting local Ollama seats and cloud providers with safety routing.MIT
Related MCP Connectors
Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/shaxzodbek-uzb/llm-localfirst'
If you have feedback or need assistance with the MCP directory API, please join our Discord server