Add macOS LLM model engine support and environment setup

This commit is contained in:
Adolfo Reyna
2026-08-07 18:23:38 -04:00
parent 62d805e565
commit 598d55e383
7 changed files with 378 additions and 11 deletions
+91
View File
@@ -0,0 +1,91 @@
// LLMHelper.swift - Interface with macOS native on-device LLM (FoundationModels / Apple Intelligence)
//
// Usage:
// llm-helper --check
// llm-helper --prompt "Hello" [--system "System prompt"]
import Foundation
import FoundationModels
struct Options {
var prompt: String = ""
var systemPrompt: String? = nil
var check: Bool = false
}
func parseArguments() -> Options {
var options = Options()
var arguments = Array(CommandLine.arguments.dropFirst())
while let argument = arguments.first {
arguments.removeFirst()
switch argument {
case "--prompt":
if !arguments.isEmpty { options.prompt = arguments.removeFirst() }
case "--system":
if !arguments.isEmpty { options.systemPrompt = arguments.removeFirst() }
case "--check":
options.check = true
default:
if options.prompt.isEmpty && !argument.hasPrefix("--") {
options.prompt = argument
}
}
}
return options
}
func emit(_ payload: [String: Any]) {
if let data = try? JSONSerialization.data(withJSONObject: payload, options: [.sortedKeys]),
let str = String(data: data, encoding: .utf8) {
print(str)
fflush(stdout)
}
}
func fail(_ message: String) -> Never {
emit(["error": message])
exit(1)
}
@main
struct LLMHelperApp {
static func main() async {
let options = parseArguments()
if options.check {
let model = SystemLanguageModel.default
let isAvailable = model.isAvailable
emit([
"available": isAvailable,
"model": "macOS SystemLanguageModel",
"reason": isAvailable ? "macOS Apple Intelligence model available" : "SystemLanguageModel unavailable on this hardware/OS configuration"
])
exit(0)
}
guard !options.prompt.isEmpty else {
fail("no prompt provided")
}
do {
let model = SystemLanguageModel.default
guard model.isAvailable else {
fail("macOS SystemLanguageModel is not available on this machine")
}
let instructions = options.systemPrompt ?? ""
let session: LanguageModelSession
if !instructions.isEmpty {
session = LanguageModelSession(model: model, instructions: instructions)
} else {
session = LanguageModelSession(model: model)
}
let response = try await session.respond(to: options.prompt)
let resultText = String(describing: response)
emit(["done": true, "text": resultText])
} catch {
fail("LanguageModel error: \(error.localizedDescription)")
}
}
}
+13 -4
View File
@@ -13,14 +13,23 @@ swiftc -O -parse-as-library SpeechHelper.swift -o speech-helper
echo "built $HERE/speech-helper"
if ./speech-helper --check >/dev/null 2>&1; then
echo "it runs — ./speech-helper --check for details"
echo "speech-helper runs — ./speech-helper --check for details"
else
status=$?
if [ "$status" -eq 137 ]; then
echo "built, but killed on launch (137): request binary approval for"
echo "built speech-helper, but killed on launch (137): request binary approval for"
echo " $HERE/speech-helper"
echo "then wait a few minutes for it to sync."
else
echo "built, but exited $status — run ./speech-helper --check to see why"
echo "built speech-helper, but exited $status — run ./speech-helper --check to see why"
fi
fi
if swiftc -O LLMHelper.swift -o llm-helper 2>/dev/null; then
echo "built $HERE/llm-helper"
if ./llm-helper --check >/dev/null 2>&1; then
echo "llm-helper runs — ./llm-helper --check for details"
fi
else
echo "could not build llm-helper with FoundationModels; fallback to Python MLX/PyObjC bridge will be available"
fi