Skip to main content
Glama

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.

PyPI Python License: MIT

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:

  1. 🔒 Datenschutz-Routing, das fail-closed ist. Ein Aufruf, den Sie mit sensitive=True kennzeichnen, 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.

  2. 🤝 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)

pydantic-settings

router.decide(...) – reines Routing, keine Aufrufe

openai

openai

Ausführen von Aufrufen auf einem lokalen OpenAI-kompatiblen Server (oder Cloud-OpenAI)

anthropic

anthropic

der Standard-Cloud-Fallback / das reason-Modell (Claude)

mcp

mcp

llm-localfirst mcp (Router über MCP bereitstellen)

pydantic-ai

pydantic-ai-slim

die Manager-Worker-attach_worker-Integration

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 path
from 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

sensitive=True

lokal

löst LocalUnavailable aus (fail-closed)

explizites model="<cloud>" + sensitive=True

löst PrivacyViolation aus

kind="reason"

Cloud

Cloud

kind="bulk" / "auto" (Standard)

lokal

Cloud-Fallback (fell_back=True)

explizites model="<name>"

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 hook

Der 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 stdio

Cloud-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 logs

Geben 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 tokens

Lokale 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.00

Zwei 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.00 zu sitzen und nie auszulösen. max_cloud_tokens und max_cloud_calls sind 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 priced

Wie 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 ein kind). 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

LF_LOCAL_BASE_URL

http://localhost:11434/v1

lokaler OpenAI-kompatibler Endpunkt

LF_LOCAL_MODEL_ID

qwen2.5:7b

lokale Modell-ID

LF_FALLBACK_MODEL

haiku

Cloud-Modell für nicht-sensiblen Fallback

LF_REASON_MODEL

haiku

Cloud-Modell für kind="reason"

LF_SENSITIVE_FAIL_CLOSED

true

verhindert, dass sensible Aufrufe je leaken

LF_PROBE_TTL

30.0

Sekunden, um die Erreichbarkeitsprüfung zu cachen

LF_PRICES

{}

{"haiku": [in, out]} pro Million Token

LF_MAX_CLOUD_CALLS

nicht gesetzt

Obergrenze für Cloud-Aufrufe pro Prozess

LF_MAX_CLOUD_TOKENS

nicht gesetzt

Obergrenze für Cloud-Token pro Prozess

LF_MAX_CLOUD_COST

nicht gesetzt

Obergrenze für Cloud-Ausgaben (erfordert LF_PRICES)


Entwicklung

uv venv && uv pip install -e '.[dev]'
ruff check . && pytest

Das 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.

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
4wRelease cycle
3Releases (12mo)
Commit activity

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

  • A
    license
    Not graded
    quality
    B
    maintenance
    A self-hostable MCP server that routes prompts to multiple LLM providers using declarative policies, with multi-role orchestration for independence and verification.
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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