Skip to main content

promptchain

Load, unload, and swap any number of local LLMs on one GPU — with full, explicit control. A small library for driving LM Studio, Ollama, and any OpenAI-compatible server from Python, plus unified streaming across local and cloud backends, and an MCP server so agents can manage your VRAM for you.

Servers already handle the automatic case — LM Studio auto-evicts, Ollama's keep_alive expires, llama-swap proxies swapping for the servers it manages. What none of them give you is one client that spans LM Studio + Ollama + any OpenAI-compatible endpoint with a policy engine on top: pin a model so it's never evicted, pre-warm the next one before you need it, swap a whole working set in one call, cap residency by count or VRAM budget — and hand all of that to your agent over MCP.

pip install promptchain

Quickstart

from promptchain import ModelManager, Endpoint

# One GPU, one model resident at a time; evict after 5 min idle.
mgr = ModelManager(policy="auto", max_resident=1, idle_unload=300)

mgr.register("drafter", Endpoint("lmstudio", "gemma-4-4b"))
mgr.register("coder",   Endpoint("ollama", "qwen3-coder:30b"), priority=10)
mgr.register("reviewer", Endpoint("anthropic", "claude-sonnet-5"))  # cloud: never counts against VRAM

with mgr.use("coder") as m:            # evicts 'drafter' first if needed, loads 'coder'
    for token in m.stream(user_message="write fizzbuzz in rust"):
        print(token, end="", flush=True)

mgr.resident()        # -> ["coder"]

Full control over the GPU

mgr.load("coder", wait=True)        # pre-warm, block until the server reports it ready
mgr.preload("critic")               # pre-warm in the background
mgr.swap("drafter", "coder")        # atomic unload -> load in one call
mgr.pin("coder"); mgr.unpin("coder")# pinned models are never auto-evicted
mgr.group("review", ["critic", "fixer"])
mgr.activate("review")              # swap a whole working set in; evict everything else
mgr.unload_all()

mgr.refresh_residency()             # reconcile belief with the server (Ollama /api/ps, LM Studio REST)
mgr.stats()                         # per-model loads, evictions, tokens, est. cost
  • policy="auto" evicts other models as needed before a load — lowest priority first, least-recently-used as the tiebreak — under max_resident and/or vram_budget.
  • policy="manual" never loads or unloads implicitly; you drive every lifecycle change yourself.
  • Cloud and custom backends stream normally but never count against VRAM and are never evicted.

Unified streaming

One stream() across every backend, returning a handle you iterate for tokens:

from promptchain import stream

resp = stream(backend="ollama", model="qwen3:8b", base_url="http://localhost:11434",
              user_message="explain async/await")
text = resp.consume()
resp.usage        # {"input_tokens": ..., "output_tokens": ...} (cloud backends)
resp.reasoning    # hidden <think>...</think> reasoning, stripped from the visible text
resp.tool_calls   # parsed tool calls when tools= was passed

Reasoning models (DeepSeek-R1 / Qwen3 / GLM) have their <think> blocks stripped automatically; Hermes-format <tool_call> tags are parsed out for local tool calling.

Backends

Backend Load / unload / ps Streaming Usage reporting
lmstudio ✅ ✅ —
ollama ✅ ✅ —
custom (llama.cpp, vLLM, llama-swap, Jan, and any OpenAI-compatible cloud) — ✅ ✅ (when keyed)
openai n/a ✅ ✅
gemini n/a ✅ ✅
anthropic n/a ✅ ✅

API keys for the named clouds are read from OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY. Install Anthropic support with pip install "promptchain[anthropic]" (OpenAI/Gemini need no extra — they're OpenAI-compatible).

Any OpenAI-compatible provider

Point the custom backend at any OpenAI-compatible endpoint and pass a key — DeepSeek, Groq, Together, Fireworks, OpenRouter, Mistral, DeepInfra, an authenticated vLLM, whatever:

Endpoint("custom", "deepseek-chat",   base_url="https://api.deepseek.com",  api_key="sk-...")
Endpoint("custom", "llama-3.3-70b",   base_url="https://api.groq.com/openai", api_key="gsk-...")
Endpoint("custom", "anthropic/claude-sonnet-4", base_url="https://openrouter.ai/api", api_key="sk-or-...")

Set base_url to the part before /v1 — the library appends /v1/chat/completions. Token usage is reported whenever a key is present.

Let an agent manage your GPU (MCP)

pip install "promptchain[mcp]"
promptchain-mcp        # stdio MCP server

Wire it into Hermes Agent, Claude Code, or Claude Desktop and it can ps your GPU, load/unload/swap models, and generate through them — in plain language. Models are configured in an endpoints.toml (auto-created on first run). See the agent setup guide.

The app built on this

The same repo ships the PromptChain app — a two-model Streamlit pipeline with a human review gate: a small local model drafts your prompt, you fix it, then the big (local or cloud) model writes the code. It's the flagship consumer of this library; clone the repo to run it.

Metadata

Release files for promptchain 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for promptchain 0.1.1
File Size Uploaded Provenance
promptchain-0.1.1.tar.gz 35.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for promptchain 0.1.1
File Interpreter ABI Platform
promptchain-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 73.7 kB

Release files / promptchain-0.1.1.tar.gz

Download URL promptchain-0.1.1.tar.gz
Size 35.2 kB
Tags Source
SHA-256 checksum
How to use checksums
35b621da758594a474f1c51840ea867194b45a6c08ee4786a235c767737dd7a1
BLAKE2b-256 checksum
How to use checksums
05f8ece2b0771d8d773e62b527864d5e4adb27ddd31458608d0bb893bf06b207
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release files / promptchain-0.1.1-py3-none-any.whl

Download URL promptchain-0.1.1-py3-none-any.whl
Size 38.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b3a94d73a164e9920629ea8c8efcf83fa901f9e4fba213bec918ca858ada484f
BLAKE2b-256 checksum
How to use checksums
61e534575b424c4b6f59f6aaa0f74004c51beb31219ae6deeb1b5b56ac0cb030
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Security for promptchain 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page