feat: migrate on-device Qwen3 ASR to CoreML for background Flow dictation
Replace MLX GPU inference with CoreML bundles so transcription continues while the host app is backgrounded. Adds model download and warm-up, vendored Qwen3Speech, and updates onboarding, settings, and copy for the ~1.6 GB CoreML package (iOS 18+).
This commit is contained in:
@@ -35,6 +35,8 @@ public struct AppGroupStore: @unchecked Sendable {
|
||||
static let modeId = "config.modeId"
|
||||
static let localeId = "config.localeId"
|
||||
static let engineMode = "config.engineMode"
|
||||
static let localASRBackend = "config.localASRBackend"
|
||||
static let uiLanguage = "config.uiLanguage"
|
||||
}
|
||||
|
||||
// MARK: - Reads
|
||||
@@ -70,12 +72,25 @@ public struct AppGroupStore: @unchecked Sendable {
|
||||
defaults.string(forKey: Key.localeId) ?? "auto"
|
||||
}
|
||||
|
||||
/// "local" → on-device ASR only, no LLM polishing.
|
||||
/// "local" → on-device ASR only (raw transcript delivery).
|
||||
/// "cloud" → ASR + LLM polish (default behaviour).
|
||||
public var engineMode: String {
|
||||
defaults.string(forKey: Key.engineMode) ?? "cloud"
|
||||
}
|
||||
|
||||
/// Which on-device ASR engine backs the "local" engine mode. Falls
|
||||
/// back to the iOS SpeechAnalyzer path so legacy installs (which
|
||||
/// never wrote this key) keep working.
|
||||
public var localASRBackend: LocalASRBackend {
|
||||
let raw = defaults.string(forKey: Key.localASRBackend) ?? LocalASRBackend.speechAnalyzer.rawValue
|
||||
return LocalASRBackend(rawValue: raw) ?? .speechAnalyzer
|
||||
}
|
||||
|
||||
/// Host-app UI language override (`auto` / `en` / `zh-Hans`).
|
||||
public var uiLanguage: AppUILanguage {
|
||||
AppUILanguage.fromStored(defaults.string(forKey: Key.uiLanguage))
|
||||
}
|
||||
|
||||
// MARK: - Writes
|
||||
|
||||
public func setModeId(_ id: String) {
|
||||
@@ -90,6 +105,14 @@ public struct AppGroupStore: @unchecked Sendable {
|
||||
defaults.set(mode, forKey: Key.engineMode)
|
||||
}
|
||||
|
||||
public func setLocalASRBackend(_ backend: LocalASRBackend) {
|
||||
defaults.set(backend.rawValue, forKey: Key.localASRBackend)
|
||||
}
|
||||
|
||||
public func setUILanguage(_ language: AppUILanguage) {
|
||||
defaults.set(language.rawValue, forKey: Key.uiLanguage)
|
||||
}
|
||||
|
||||
// MARK: - Client
|
||||
|
||||
public func makeClient() -> LLMClient {
|
||||
|
||||
Reference in New Issue
Block a user