Skip to content

adpena/fmtools

Repository files navigation

FMTools

On-device Apple Foundation Models tools with three distinct product surfaces:

  • fmtools: Python toolkit and developer CLI
  • FMRuntime: Swift runtime and FFI layer under runtime/
  • FMChat: standalone local macOS chat app under standalone/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.

Requirements

  • macOS 26+ on Apple Silicon
  • Python 3.13+
  • local Foundation Model availability for inference features

Products

fmtools — Python toolkit

The Python toolkit is the main import surface today.

It includes:

  • @local_extract, stream_extract, and pipeline APIs
  • the internal fmtools developer 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 doctor

If 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 check

FMRuntime — Swift runtime

The runtime package lives under runtime/.

It currently provides:

  • FMRuntimeCore
  • FMRuntimeFFI
  • structured generation over FFI
  • transcript carry-over and resume over FFI
  • runtime availability probing
  • structured runtime error payloads

Build it with:

./scripts/build_fmruntime.sh

FMChat — standalone desktop app

The standalone chat app is a separate product surface.

Install:

brew tap adpena/fmtools https://github.com/adpena/homebrew-fmtools
brew install fmchat
fmchat

Backends

The 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.py

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

Quality Workflows

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:

  1. reviewed eval dataset
  2. deterministic metric
  3. DSPy/GEPA optimization
  4. saved artifact
  5. 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.py

Transcript Workflows

FMTools 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_transcript

Example:

uv run python examples/transcript_session_workflow.py

Quick Start

import 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())

Developer Commands

uv run fmtools doctor
uv run fmtools test
uv run fmtools check
uv run fmtools example --list
uv run fmtools chat

Docs

Current State

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

About

Foundation Models toolkit for structured extraction, streaming pipelines, and local AI workflows on Apple Silicon.

Topics

Resources

License

Stars

3 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors