docs / build with the engine
Local quick start
Open once, clean repeatedly, close when done.
Cleanup Engine is an unreleased developer preview. These guides are generated from the SDK repository, which is private for now; file paths are shown as text. Request access.
Quick start
1. Add the package
The root package has no MLX dependency. Local inference is distributed as the standalone PomvoxCleanupMLX package, generated from Runtime/MLX in this source repository. Add the public runtime repository in Xcode at exact version 0.1.0-beta.2, or declare:
// Package.swift dependency
.package(url: "https://github.com/pomvox/pomvox-cleanup-mlx.git", exact: "0.1.0-beta.2")
// Application target dependency
.product(name: "PomvoxCleanupMLX", package: "pomvox-cleanup-mlx")
Use an Xcode build to package the dependency's Metal shader resources. A plain swift build is insufficient to package the required shader library. The separate consumer (Examples/Consumer) demonstrates a working application build. The runtime pulls the matching core SDK version automatically; no submodule is required. Core/cloud-only consumers can instead add https://github.com/pomvox/pomvox-cleanup-engine.git at exact version 0.1.0-beta.2 and select PomvoxCleanup or PomvoxCleanupCloud.
2. Prepare assets already on disk
The baseline requires the exact snapshot recorded in pack.json (packs/simplewords-v3/pack.json). Given that snapshot:
python3 scripts/prepare-local-pack.py /path/to/pinned/snapshot .local/simplewords-v3
Apps can use the native PackInstaller.install(snapshot:manifestData:destination:) with the trusted bundled manifest instead of invoking Python. Install outside cloud-synced folders, keep the pack immutable, and pass the returned handle to .validated(installedPack) when opening. Model access is separate from SDK installation: the pinned upstream model currently requires accepting access conditions.
The tool copies and verifies the seven pinned artifacts, refuses existing destinations and cleans up failed copies. It never downloads or modifies the source. The upstream model currently has an access gate; reproducible public acquisition and an archived license/notice record remain release requirements. See installed packs.
3. Open once, clean repeatedly, close when done
import Foundation
import PomvoxCleanupMLX // Exports the runtime-independent PomvoxCleanup API.
let cleaner = try await Cleaner.open(
pack: .directory(URL(fileURLWithPath: "/absolute/path/to/installed/pack")),
runtime: .mlx,
policy: .local
)
let result = try await cleaner.clean(CleanupRequest(
"um please send the pomvox report tomorrow",
vocabulary: ["Pomvox"],
deadline: .seconds(2)
))
print(result.text)
print(result.status)
await cleaner.close()
open verifies hashes, loads the model, prepares the prefix and warms Metal kernels. Missing or incompatible assets throw before a usable cleaner is returned. Keep the pack immutable while open. The host should close its cleaner on both success and error paths when retiring it; opening per request wastes preparation work.
The baseline supports English and bounded vocabulary. It rejects nonempty context or settings, including style. Unicode-safe edits do not imply multilingual model quality. Output guards are heuristics and cannot guarantee meaning preservation.
Outcomes and cancellation
| Outcome | Meaning | Host action |
|---|---|---|
.cleaned | Accepted output differs from input | Inspect/apply the result |
.unchanged | Accepted output equals input, or input was empty | Preserve the result |
.fallback(reason) | Cleanup did not produce an accepted result | Result contains the exact input bytes and zero edits |
CancellationError | The caller canceled or its session was superseded | Do not insert text |
| Other thrown error | Invalid request, unsupported configuration or setup failure | Correct configuration or present an error |
Fallback reasons include timeout, rejection, unavailability, queue saturation and token limits. The local cleaner runs one request and queues at most two. A canceled/timed-out worker keeps its resources until it returns; replacement work is refused while it remains unresponsive. close() stops admission immediately and may return before that worker releases resources. A GPU kernel cannot be forcibly interrupted by this SDK.
Explicit deadlines cover admitted queueing and request work. The default is min(60, max(5, 2 + 0.012 × characterCount)) seconds. Preparation is measured separately. See lifecycle and request limits.
Applying edits
let reconstructed = try TextEdit.applying(result.edits, to: originalTranscript)
// Reconstructed bytes equal result.text. Offsets refer to the original transcript.
for edit in result.edits {
let swiftRange = try edit.range(in: originalTranscript)
let textViewRange = try edit.utf16Range(in: originalTranscript)
// Use the appropriate range for your host editor.
}
Edits use half-open UTF-8 byte offsets, not character offsets. Invalid or overlapping ranges throw. The local engine emits one minimal contiguous replacement; it may include an unchanged interior span and does not describe editorial intent. Keep the original transcript for mapping these ranges.