Skip to main content

Local-first LLM wrapper (import local_llm_wrapper) with pluggable transports (Ollama, Apple, optional Claude Code CLI) and a stable text-in text-out API.

Project description

local_llm_wrapper

Local-first LLM wrapper with a stable text-in text-out API. Supports pluggable transports (Ollama, Apple, and an optional Claude Code CLI cloud transport) with structured output helpers and retry for unattended runs.

Package name: local-llm-wrapper (import as local_llm_wrapper).

Overview

  • Library-first wrapper for text models with a small, stable API.
  • Local-first design; an optional cloud transport (Claude Code CLI) is also available.
  • Fallback across transports when a backend is unavailable.
  • Structured helpers for rename/sort workflows with strict parsing and format-fix retries.

Features

  • Pluggable transports in local_llm_wrapper/transports/.
  • Fallback chain in LLMClient with guardrail and context-window handling.
  • Structured prompts and parsers for rename, keep, and sort workflows.
  • Prompt sanitization and output normalization utilities.
  • Quiet mode for non-verbose runs.
  • Unified API for text prompts and chat-style message lists.

Quick start

import local_llm_wrapper.llm as llm

client = llm.LLMClient(
	transports=[
		llm.AppleTransport(),
		llm.OllamaTransport(model=llm.choose_model(None)),
	],
	quiet=True,
)

response = client.generate("Say hello in one sentence.", max_tokens=120)
print(response)

Chat example

import local_llm_wrapper.llm as llm

client = llm.LLMClient(
	transports=[llm.OllamaTransport(model="qwen3.5:9b-q4_K_M")],
	quiet=True,
)
messages = [
	{"role": "system", "content": "Answer in one sentence."},
	{"role": "user", "content": "What is a mutex?"},
]
print(client.generate(messages=messages, max_tokens=120))

CLI example

source source_me.sh && python3 llm_generate.py -p "Say hello in one sentence." -t 80

CLI usage

llm_generate.py is a repo-root helper for quick prompt tests against the Ollama transport.

source source_me.sh && python3 llm_generate.py --help

Options:

  • -p, --prompt: Prompt text to send (default: "Say hello in one sentence.").
  • -m, --model: Override the auto-selected model (default: auto).
  • -t, --max-tokens: Maximum tokens to generate (default: 80).
  • -q, --quiet: Suppress progress output (default).
  • -v, --verbose: Show progress output.

CLI chat demo

llm_chat.py is an interactive chat loop that uses chat-style messages.

source source_me.sh && python3 llm_chat.py

Options:

  • -m, --model: Override the auto-selected model (default: auto).
  • -s, --system: Optional system message to start the chat.
  • -t, --max-tokens: Maximum tokens to generate per response (default: 240).
  • -q, --quiet: Suppress progress output (default).
  • -v, --verbose: Show progress output.

XML tag demo

llm_xml_demo.py requests a tagged response and extracts <answer> from the model output.

source source_me.sh && python3 llm_xml_demo.py -p "Say hello in one sentence."

Structured helpers

The engine includes structured helpers for common file-organization tasks.

import local_llm_wrapper.llm as llm

client = llm.LLMClient(transports=[llm.OllamaTransport(model="qwen3.5:9b-q4_K_M")])
item = {
	"path": "notes.txt",
	"name": "notes",
	"ext": "txt",
	"description": "meeting notes",
}
result = client.sort([item])
print(result.assignments)

Install extras

The Apple backend requires at least one Apple SDK. Install via optional extras:

pip install local-llm-wrapper[apple]           # prebuilt wheels, no Xcode needed (recommended)
pip install local-llm-wrapper[apple-official]   # Apple's official SDK, requires Xcode 26+
pip install local-llm-wrapper[apple-all]        # both backends (for dev/CI)

When both SDKs are installed, the transport prefers apple-fm-sdk when it is available and safe to use, and falls back to apple-foundation-models otherwise.

Claude Code transport

ClaudeCodeTransport delegates to the claude CLI in non-interactive --print mode.

import local_llm_wrapper.llm as llm

client = llm.LLMClient(
	transports=[
		llm.AppleTransport(),
		llm.OllamaTransport(model=llm.choose_model(None)),
		llm.ClaudeCodeTransport(model="sonnet"),
	],
	quiet=True,
)

response = client.generate("Say hello in one sentence.", max_tokens=120)
print(response)

Caveats when using ClaudeCodeTransport:

  • Prompts are sent to the Anthropic cloud, not processed locally or offline.
  • The CLI runs in --print mode which skips the workspace trust dialog; only use it from directories you trust.
  • By default, all Claude Code tools are disabled (--tools ""), so the transport does not intentionally grant workspace read, write, or execute access.

Transports

  • Apple: local_llm_wrapper/transports/apple.py (dual-backend: apple-fm-sdk and apple-foundation-models).
  • Ollama: local_llm_wrapper/transports/ollama.py.
  • Claude Code CLI: local_llm_wrapper/transports/claude_code.py.
  • Protocol: local_llm_wrapper/transports/base.py.

Errors

Standardized exception types live in local_llm_wrapper/errors.py so callers can handle guardrails, context window errors, and transport availability consistently.

Testing

source source_me.sh && python3 -m pytest tests/

Docs

Notes

  • This repo is text-only; image or OCR workflows belong elsewhere.
  • Configuration is explicit through arguments or config objects, not custom environment variables.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

local_llm_wrapper-26.5.tar.gz (149.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

local_llm_wrapper-26.5-py3-none-any.whl (50.9 kB view details)

Uploaded Python 3

File details

Details for the file local_llm_wrapper-26.5.tar.gz.

File metadata

  • Download URL: local_llm_wrapper-26.5.tar.gz
  • Upload date:
  • Size: 149.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for local_llm_wrapper-26.5.tar.gz
Algorithm Hash digest
SHA256 8bae56dc3c27f5ae94f4c8d223247706328dc8be93b97b86012db16bcb73e68f
MD5 a3ddddddbf00974b61aafb02bba1f9e4
BLAKE2b-256 124c3945e9cd92c49ea208f9c7bc9465bcf29366b9f2a413d7e9cce6103353cc

See more details on using hashes here.

File details

Details for the file local_llm_wrapper-26.5-py3-none-any.whl.

File metadata

File hashes

Hashes for local_llm_wrapper-26.5-py3-none-any.whl
Algorithm Hash digest
SHA256 469a6414ffae9250ad44b56b4c2db94d412c535058722da16a7050ae2f67d73a
MD5 7e98bbbb3f6b6967b985450c2ab3ed58
BLAKE2b-256 fd8cfab27cc00b1d7f0c14b75061a185769e0df63179077e290ebc7cc28ca0eb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page