CoreAIKit

OpsDemo

The anchored ops end to end. Point it at a voice memo and one audio file becomes a transcript, a cleaned-up text, a one-line summary, typed action items, a Japanese translation, and a spoken reply (speech.wav); point it at an image and it is captioned, object-detected, and OCR’d — all on device. No sessions, no prompts, no model names in app code: ops are the stable API and the kit resolves a catalog model behind them.

Run

swift run OpsDemo                    # text + search ops on built-in samples (qwen3 4B + EmbeddingGemma)
swift run OpsDemo voice-memo.wav     # speech -> text -> speech (downloads Whisper + VoxCPM once)
swift run OpsDemo photo.jpg          # caption + detect + read (Qwen3-VL 2B, RF-DETR, GLM-OCR)
swift run OpsDemo transcript.txt     # raw ASR transcript -> written text (S1-mini, chunked)

The memo path cleans the transcript with CoreAI.tidyTranscript, not proofread: the input is raw dictation, and the op for that position drops fillers and false starts and writes spoken numbers and dates out — which proofread is contracted not to do.

A .txt / .md argument runs that op alone, which is where long input is worth watching. A 695-token meeting transcript is cut into word-boundary chunks and stitched (13.6 s on an M4 Max), because on iPhone the engine caps prompt + generated at 1024 tokens:

> CoreAI.tidyTranscript(raw)  [3480 characters in]
[clean] Okay, let me just get all of this down before I forget it. We had the quarterly
review this morning, and there were basically three things that came out of it.

First, the pipeline numbers are actually better than we thought. We closed 19 deals in Q3,
not 17. The discrepancy was two deals that got booked on October 1 instead of September 30.
…

Real pipeline output (Mac, ~38 s warm for the five text ops):

> CoreAI.transcribe(memo)
[transcript] Team meeting notes. Please ship 12 units of the Alpha widget to the Osaka
office by Friday. Also, schedule a follow-up call with Dana next Tuesday to review the
launch plan.

> CoreAI.summarize(clean, style: .oneLine)
[summary] Ship 12 Alpha widgets to the Osaka office by Friday and schedule a follow-up
call with Dana next Tuesday to review the launch plan.

> CoreAI.extract(clean, as: ActionItems.self)
[task] Please ship 12 units of the Alpha widget to the Osaka office by Friday.
[task] Schedule a follow-up call with Dana next Tuesday to review the launch plan.

> CoreAI.translate(clean, to: .japanese)
[ja] チーム会議のメモ。12個のアルファウィジェットを大阪支社に金曜日までに発送してください。…

> CoreAI.speak(summary)
[audio] 8.4 s -> speech.wav

extract shapes the reply with the @Generable type’s generation schema and parses it back through the framework, so the demo’s ActionItems / Order types are exactly what you would write for Apple’s respond(generating:). Override any op’s model per call, e.g. options: .model("qwen3-0.6b") when speed matters more than fidelity, or options: .model("mineru2.5-pro") to swap the OCR engine behind read.