Skip to main content

Local LLM Kit

PyPI Python License: MIT

One Python API for local language models, desktop apps, and inference servers. Use OpenAI-shaped chat, streaming, tools and structured output while choosing where your model runs. The core install needs only typing-extensions; model engines and validation packages are optional.

Release 0.3.0 includes native Apple FM, MCP, discovery, Responses, agents, hybrid retrieval, logging and the hardware advisor. Install or upgrade from PyPI:

python -m pip install --upgrade local-llm-kit

For the released API, use the 0.3.0 documentation. No API key is needed for local inference. Prepare your engine, dependencies and model weights before disconnecting from the internet.

Start with a local model

Start Ollama, then download a model once:

ollama pull qwen2.5:0.5b
pip install local-llm-kit
local-llm-kit chat --backend ollama -m qwen2.5:0.5b --message 'Hello'
from local_llm_kit import LLM

llm = LLM('qwen2.5:0.5b', backend='ollama')
response = llm.chat([{'role': 'user', 'content': 'Explain recursion briefly.'}])
print(response['choices'][0]['message']['content'])

for chunk in llm.chat([{'role': 'user', 'content': 'Write a haiku.'}], stream=True):
    print(chunk['choices'][0]['delta'].get('content') or '', end='')

For tests without a model or a server:

llm = LLM('echo', backend='echo')
assert llm.chat([{'role': 'user', 'content': 'Hello'}])['choices'][0]['message']['content'].startswith('Echo:')

Choose your runtime

Server presets connect to an engine you have already started; they do not install or launch it. Always use that server's served model ID. You can override any URL with backend_kwargs={'base_url': 'http://127.0.0.1:PORT/v1'}.

Runtime backend Connection or extra
Ollama ollama Native HTTP; default port 11434
llama.cpp llamacpp / llama-server Local GGUF with [llamacpp], or server port 9931
LM Studio lmstudio Server port 1234
vLLM vllm Server port 8000
SGLang sglang Server port 30000
LocalAI localai Server port 8080
Jan jan Server port 1337
GPT4All gpt4all Server port 4891
MLX-LM mlx-lm Server port 8080
KoboldCpp koboldcpp Server port 5001
Hugging Face Transformers transformers / transformers-serve In-process [transformers], or server port 8000
AirLLM airllm Experimental in-process [airllm]; buffered streaming
Apple Foundation Models apple-fm Native [apple-fm], eligible Mac and SDK required
apfel apfel Apple model bridge; server port 11434
Other OpenAI-compatible servers openai-compat Explicit base_url

This is a compatibility list. Popularity and speed depend on workload and hardware. Tools, vision, embeddings and native schema enforcement depend on the actual engine, model, parser and configuration. GPT4All, MLX-LM and apfel presets have no embedding endpoint in this adapter. llama-server's current binary uses 9931; older versions and its Docker image may use 8080. See the compatibility guide for limits and upstream references.

Find running servers and check locality

local-llm-kit doctor
local-llm-kit doctor --json --url http://127.0.0.1:9000/v1
local-llm-kit doctor --require-local
from local_llm_kit import discover, find_local_server

report = discover()
for server in report.live:
    print(server.provider, server.base_url, [m.to_dict() for m in server.models])

server = find_local_server(require_local=True)

Discovery reads available native metadata from Ollama, llama.cpp, LM Studio and apfel. A reachable loopback URL or a local-sounding model name alone does not prove local inference: unknown locality stays unknown. Ollama cloud routes are marked remote. LLM(..., require_local=True) accepts known in-process engines or a loopback server with verified model metadata, and rechecks before chat and completion requests. This trusts server metadata; it is not a network sandbox and does not prevent a model engine from downloading weights or a tool from using the network.

HTTP adapters retry connection failures and selected transient statuses with bounded backoff. Configure backend_kwargs={'max_retries': 0} to fail fast or pass local_llm_kit.retry.RetryPolicy for delay controls. Streaming retries only the connection setup, avoiding repeated tokens after output starts.

Use Apple's built-in model

pip install 'local-llm-kit[apple-fm]'
llm = LLM('apple-foundationmodel', backend='apple-fm',
          backend_kwargs={'timeout': 30})
print(llm.chat([{'role': 'user', 'content': 'Summarise this idea.'}]))

The native backend needs Python 3.10+, macOS 26+, Xcode 26+ with its SDK agreement accepted, and an Apple Intelligence-capable Mac with Apple Intelligence enabled. It creates a fresh SDK session per request, forwards native JSON Schema, supports streaming stops across chunk boundaries and exposes count_tokens_exact. Inline data-URL images use temporary files; actual vision requires an SDK/OS version with image support. Unsupported sampling controls are documented. Use LLM.achat() from async code.

Alternatively, run apfel --serve and select backend='apfel'. This profile omits unsupported sampling fields, maps prompt completion to chat, and reports no embedding support. It shares Ollama's default port; configure separate ports to run both simultaneously.

Python tools, MCP and agents

from local_llm_kit import Agent, tool

@tool
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

llm.add_tool(add)
reply = llm.chat([{'role': 'user', 'content': 'What is 12 + 30?'}])

# Or let the bounded agent own the loop with tools scoped to that agent:
agent = Agent(llm, tools=[add], max_steps=5, tool_timeout=10)
result = agent.run('What is 12 + 30?')
print(result.content, result.success)

Tool execution uses complete parsed arguments, names scoped to the request, required-argument checks and a waiting timeout. Invalid or failed calls become error feedback; truncated arguments are not repaired into executable actions. A timed-out Python function can keep running, so tools with side effects still need their own execution controls. A model that supports tool calling is required. Use execute_tools=False to return calls for your application to handle.

Connect a trusted MCP server with the same tools interface:

from local_llm_kit import MCPServer

with LLM('qwen2.5:7b', backend='ollama') as llm:
    llm.add_mcp_server('files', command='your-mcp-server', args=['/allowed/path'])
    # Tools are namespaced files__<name>. llm.close() closes the connection.
    reply = llm.chat([{'role': 'user', 'content': 'List the available files.'}])
local-llm-kit mcp tools --command 'your-mcp-server /allowed/path' --json
local-llm-kit mcp call --url http://127.0.0.1:9000/mcp --tool read --args '{"path":"note.txt"}'

The synchronous MCP tools client supports stdio and Streamable HTTP (JSON/SSE), deadlines, pagination, namespacing and cleanup. Resources, prompts, OAuth and server-initiated subscriptions are outside this subset. A local subprocess may itself use the network; transport alone makes no offline guarantee.

Validate structured output

pip install 'local-llm-kit[structured]'
schema = {'type': 'object', 'properties': {'age': {'type': 'integer', 'minimum': 0}},
          'required': ['age'], 'additionalProperties': False}
data = llm.chat_structured([{'role': 'user', 'content': 'Return age 3 as JSON.'}],
                           schema=schema, max_retries=2)
assert data['age'] == 3

Dictionary schemas use jsonschema; Pydantic model validation is supported when Pydantic is installed. The helper validates types and constraints and asks for correction within its retry limit. Native constrained decoding is used where the backend supports it. extract_json and repair_json are optional output helpers that preserve quoted values; they are not used to repair executable tool calls.

Retrieval with local documents

from local_llm_kit import RAGPipeline, SimpleVectorStore

pipeline = RAGPipeline(llm)
pipeline.add_documents(['Local installation uses prepared weights.'],
                       metadatas=[{'topic': 'setup'}])
answer = pipeline.query('How does local installation work?', mode='lexical')
print(answer['answer'], answer['sources'])

SimpleVectorStore supports default dense/TF-IDF search, explicit BM25, metadata filters, deletion and JSON persistence. With an embed_fn, mode='hybrid' fuses dense/BM25 ranks; lambda_mult enables MMR diversity. The small in-memory store is intended for modest document collections. Hash embeddings in examples are deterministic fixtures, not semantic search models. Citation prompts do not prove that an answer is grounded; returned source records let applications check.

Save conversations and reuse prompts

from local_llm_kit import ConversationLog, PromptTemplate

prompt = PromptTemplate('Explain {{topic}} in {{style|plain language}}.').render(topic='recursion')
with ConversationLog('chat.db') as log:
    llm = LLM('qwen2.5:0.5b', backend='ollama', conversation_log=log)
    response = llm.chat([{'role': 'user', 'content': prompt}])
    print(log.export_conversation(response['conversation_id'], format='openai'))

Logging is opt-in. SQLite writes each completed interaction atomically, including usage, tool IDs and full message payloads; :memory: works across threads. Completed streams are logged too. An interrupted stream is not saved as a complete answer. Stored prompts, images and tool outputs are ordinary local database data. Templates use plain text replacement, not evaluation or automatic JSON escaping; JSON and plain-text files need no extra, while YAML files need [yaml].

local-llm-kit chat --backend echo -m echo --message Hello --conversation-log ./chat.db
local-llm-kit logs list --db ./chat.db
local-llm-kit logs export CONVERSATION_ID --db ./chat.db --format openai
local-llm-kit hardware --params-b 8 --context-length 8192

The hardware advisor reports measured or unknown memory and an approximate single-sequence model/KV budget. It does not combine separate GPUs into a fictional single device or guarantee a model will fit. Supply actual KV geometry to estimate_model_vram when available.

Connect an OpenAI SDK client

pip install 'local-llm-kit[server]' openai
local-llm-kit serve --backend ollama --model qwen2.5:0.5b --host 127.0.0.1 --port 8000
from openai import OpenAI
client = OpenAI(base_url='http://127.0.0.1:8000/v1', api_key='unused')
response = client.responses.create(model='qwen2.5:0.5b', input='Hello', store=False)
print(response.output_text)

The development server exposes chat/completions, completions, embeddings, model listing and a stateless Responses subset: text/image message input, instructions, function calls/results, text.format, and text/tool SSE lifecycles. Responses returns tools for the caller to execute. Stateful responses, built-in hosted tools, reasoning controls and background jobs are rejected. This is not full OpenAI API parity or a hardened multi-user inference gateway. Use a native embedding backend for semantic embeddings; the development fallback is a fixture.

Development and validation

pip install -e '.[dev,server]' httpx openai mcp
ruff check .
black --check .
pytest
LOCAL_LLM_KIT_OPENAI_INTEROP=1 pytest tests/test_responses_sdk.py
LOCAL_LLM_KIT_MCP_INTEROP=1 pytest tests/test_mcp_interop.py

Python 3.9+ is supported by the core. Official SDK interoperability checks use Python 3.10+ where their dependencies require it. Offline protocol fixtures verify routing and payload contracts; they do not certify all engines or GPU hardware. Native Apple live tests require LOCAL_LLM_KIT_APPLE_FM_LIVE=1 on an eligible Mac.

See examples, the API reference, contribution guide, changelog, and PR consolidation record. Report reproducible bugs through GitHub Issues. Local LLM Kit is licensed under MIT.

Metadata

Release files for local-llm-kit 0.3.0

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

Source distribution (sdist)

Source distribution for local-llm-kit 0.3.0
File Size Uploaded Provenance
local_llm_kit-0.3.0.tar.gz 281.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for local-llm-kit 0.3.0
File Interpreter ABI Platform
local_llm_kit-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 461.4 kB

Release files / local_llm_kit-0.3.0.tar.gz

Download URL local_llm_kit-0.3.0.tar.gz
Size 281.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7674dc47cd0a47032512dec5d386d17fbc0825a975fa82f3142413ad7f1a218a
BLAKE2b-256 checksum
How to use checksums
216ff4c1d7a48f248990e2ce8a8336b81552a216ce61d5c65418ae42010a0053
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / local_llm_kit-0.3.0-py3-none-any.whl

Download URL local_llm_kit-0.3.0-py3-none-any.whl
Size 180.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
161ac1998d3feb5d6c7be89f8d85a3de489f57e73e7cc288b0091d9891e3d47e
BLAKE2b-256 checksum
How to use checksums
3e9e7e572c5aec66d240ee3a9592c940f39606f54af27428f5879663310586e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Security for local-llm-kit 0.3.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for local_llm_kit-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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