On-device Apple Foundation Models tools with three distinct product surfaces:
fmtools: Python toolkit and developer CLIFMRuntime: Swift runtime and FFI layer underruntime/FMChat: standalone local macOS chat app understandalone/fmchat/
This repo is no longer just a single Python framework. The toolkit, runtime, and app share infrastructure, but they are different install paths and should be documented that way.
- macOS 26+ on Apple Silicon
- Python 3.13+
- local Foundation Model availability for inference features
The Python toolkit is the main import surface today.
It includes:
@local_extract,stream_extract, and pipeline APIs- the internal
fmtoolsdeveloper CLI - caching, debugging, adapters, Polars, DSPy, and watcher surfaces
- quality/evaluation workflows such as support-ticket and medical-triage optimization
- transcript export/resume helpers for backend-portable history workflows
Install:
uv venv --python 3.13 .venv
source .venv/bin/activate
uv pip install -U fmtools
fmtools doctorIf you do not want to activate a virtual environment, use uv run fmtools ... from the repo root instead of assuming fmtools is on PATH.
Local development from this repo:
uv sync --all-groups
uv run fmtools checkThe runtime package lives under runtime/.
It currently provides:
FMRuntimeCoreFMRuntimeFFI- structured generation over FFI
- transcript carry-over and resume over FFI
- runtime availability probing
- structured runtime error payloads
Build it with:
./scripts/build_fmruntime.shThe standalone chat app is a separate product surface.
- app mirror:
standalone/fmchat/ - implementation source:
examples/toga_local_chat_app/ - Homebrew cask / app artifact, not just another Python install mode
Install:
brew tap adpena/fmtools https://github.com/adpena/homebrew-fmtools
brew install fmchat
fmchatThe Python toolkit has a real backend layer now.
| Backend | Default | Status | Notes |
|---|---|---|---|
apple_sdk |
yes | stable | Uses the official apple-fm-sdk Python SDK |
ffi |
no | advanced | Uses the Swift runtime through the compiled dylib |
Use the optional runtime path with:
FMTOOLS_BACKEND=ffi uv run python your_script.pyThe FFI backend is only selected when the dylib loads and the runtime availability probe succeeds. Otherwise FMTools stays on the official Apple SDK path.
The loader auto-discovers the runtime library only when it exists under runtime/.build/... relative to the repo checkout. If you are using the FFI backend from another location, set FMTOOLS_RUNTIME_LIB=/absolute/path/to/libFMRuntimeFFI.dylib.
FMTools now has a dedicated evaluation/optimization layer instead of only demos.
Current shipped verticals:
- auditor quality review
- support-ticket extraction
- medical-triage extraction
Each workflow follows the same loop:
- reviewed eval dataset
- deterministic metric
- DSPy/GEPA optimization
- saved artifact
- runtime consumption through FMTools helpers
Examples:
uv run python examples/auditor_quality.py
uv run python examples/support_ticket_quality.py
uv run python examples/medical_triage_quality.pyFMTools now exposes transcript helpers at the toolkit layer:
export_transcript_dict(session)export_transcript_json(session)resume_session_from_transcript(transcript, *, model=None)
For task-local resumed workflows, use:
from fmtools._context import session_scope_from_transcriptExample:
uv run python examples/transcript_session_workflow.pyimport asyncio
import apple_fm_sdk as fm
from fmtools import local_extract
@fm.generable()
class SupportTicket:
category: str = fm.guide(anyOf=["Billing", "Technical", "Account", "Other"])
urgency: str = fm.guide(anyOf=["LOW", "MEDIUM", "HIGH", "CRITICAL"])
summary: str = fm.guide(description="One-sentence summary of the issue")
@local_extract(schema=SupportTicket)
async def classify_ticket(email_text: str) -> SupportTicket:
"""Classify a customer support email by category, urgency, and summary."""
async def main():
ticket = await classify_ticket("I was charged twice and need a refund immediately.")
print(ticket.model_dump())
asyncio.run(main())uv run fmtools doctor
uv run fmtools test
uv run fmtools check
uv run fmtools example --list
uv run fmtools chat- product docs scaffold:
docs-site/ - docs site local readme:
docs-site/README.md - toolkit docs draft:
docs-site/src/content/docs/fmtools/index.mdx - runtime docs draft:
docs-site/src/content/docs/fmruntime/index.mdx - app docs draft:
docs-site/src/content/docs/fmchat/index.mdx - backend guide:
docs-site/src/content/docs/guides/backends.mdx - quality guide:
docs-site/src/content/docs/guides/quality-workflows.mdx
Shipped and usable now:
- Python toolkit + CLI
- Swift runtime package + FFI backend
- FMChat app mirror
- support-ticket and medical-triage quality workflows
Still in progress:
- fully separate shipped Swift runtime CLI product
- fuller docs migration out of the old README style
- broader optimized verticals beyond support tickets and medical triage