Add LiteRTLanguageModel using the official LiteRT-LM Swift package - #229
Conversation
Runs .litertlm models (e.g. Gemma 4) fully on-device via Google's LiteRT-LM runtime, with Metal GPU acceleration on iOS and macOS. - LiteRT package trait, gating a swift-litert-lm dependency to iOS/macOS; default builds are unaffected - LiteRTLanguageModel: respond/streamResponse, image inputs for models with a vision tower, structured generation via schema-in-prompt + JSON extraction, and prompt-driven tool calling for respond (with the ToolExecutionDecision delegate flow) - Env-gated tests (LITERT_TEST_MODEL), README section and provider table updates
There was a problem hiding this comment.
🟡 Changes recommended
Generation limits, cancellation, structured tool outputs, retry behavior, and several tool-handling paths currently behave incorrectly.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds an on-device LiteRT-LM backend for .litertlm models with text, image, structured-generation, and tool support.
Changes:
- Adds the
LiteRTtrait and official LiteRT-LM dependency. - Implements lazy model loading, streaming, Hugging Face downloads, and tool handling.
- Adds documentation and gated integration tests.
File summaries
| File | Description |
|---|---|
Package.swift |
Configures the LiteRT trait and dependencies. |
Package.resolved |
Pins LiteRT-LM and transitive dependencies. |
Sources/AnyLanguageModel/Models/LiteRTLanguageModel.swift |
Implements the LiteRT backend. |
Tests/AnyLanguageModelTests/LiteRTLanguageModelTests.swift |
Adds configuration and gated inference tests. |
README.md |
Documents LiteRT setup and usage. |
Review details
Suppressed comments (2)
Sources/AnyLanguageModel/Models/LiteRTLanguageModel.swift:253
- The streaming path also drops
maximumResponseTokens. Pass it as LiteRT-LM's per-responsemaxOutputTokensso streamed responses honor the same public option as non-streamed responses.
for try await chunk in conversation.sendMessageStream(plan.prompt) {
Sources/AnyLanguageModel/Models/LiteRTLanguageModel.swift:289
- Cancelling the response stream only cancels this Swift task; LiteRT-LM's
sendMessageStreamdoes not connect task cancellation to the native inference, and the runtime exposesConversation.cancel()for that purpose. Retain the active conversation and callcancel()on termination so abandoned streams do not keep consuming GPU and battery until generation completes.
continuation.onTermination = { _ in
task.cancel()
}
- Files reviewed: 4/5 changed files
- Comments generated: 8
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
Structured non-object JSON and sampling-mode semantics are currently handled incorrectly.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 7/8 changed files
- Comments generated: 2
- Review effort level: Balanced
…-lm-pr175 # Conflicts: # Package.swift
Adds a
LiteRTtrait andLiteRTLanguageModelfor on-device.litertlminference on iOS and macOS, with local files, Hugging Face downloads, text streaming, image inputs, prompt-driven structured generation, and tool calling forrespond.Based on @john-rocky's #175 with their commit intact, using Google's official LiteRT-LM Swift package and the existing Hugging Face Hub client. Includes usage documentation, configuration tests, and inference tests gated by
LITERT_TEST_MODEL.