-
Notifications
You must be signed in to change notification settings - Fork 429
Add model support config fetching from model repo #216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b3c34f4
47035a8
df8ad1c
5417802
cb4d7a8
7fc5dd0
60ad4e3
f309ded
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -165,6 +165,114 @@ public struct ModelComputeOptions { | |
} | ||
} | ||
|
||
public struct ModelSupport: Codable, Equatable { | ||
public let `default`: String | ||
public let supported: [String] | ||
/// Computed on init of ModelRepoConfig | ||
public var disabled: [String] = [] | ||
|
||
private enum CodingKeys: String, CodingKey { | ||
case `default`, supported | ||
} | ||
} | ||
|
||
public struct DeviceSupport: Codable { | ||
public let identifiers: [String] | ||
public var models: ModelSupport | ||
} | ||
|
||
public struct ModelSupportConfig: Codable { | ||
public let repoName: String | ||
public let repoVersion: String | ||
public var deviceSupports: [DeviceSupport] | ||
/// Computed on init | ||
public private(set) var knownModels: [String] | ||
public private(set) var defaultSupport: DeviceSupport | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case repoName = "name" | ||
case repoVersion = "version" | ||
case deviceSupports = "device_support" | ||
} | ||
|
||
public init(from decoder: Swift.Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
let repoName = try container.decode(String.self, forKey: .repoName) | ||
let repoVersion = try container.decode(String.self, forKey: .repoVersion) | ||
let deviceSupports = try container.decode([DeviceSupport].self, forKey: .deviceSupports) | ||
|
||
self.init(repoName: repoName, repoVersion: repoVersion, deviceSupports: deviceSupports) | ||
} | ||
|
||
public init(repoName: String, repoVersion: String, deviceSupports: [DeviceSupport], includeFallback: Bool = true) { | ||
self.repoName = repoName | ||
self.repoVersion = repoVersion | ||
|
||
if includeFallback { | ||
self.deviceSupports = Self.mergeDeviceSupport(remote: deviceSupports, fallback: Constants.fallbackModelSupportConfig.deviceSupports) | ||
self.knownModels = self.deviceSupports.flatMap { $0.models.supported }.orderedSet | ||
} else { | ||
self.deviceSupports = deviceSupports | ||
self.knownModels = deviceSupports.flatMap { $0.models.supported }.orderedSet | ||
} | ||
|
||
// Add default device support with all models supported for unknown devices | ||
self.defaultSupport = DeviceSupport( | ||
identifiers: [], | ||
models: ModelSupport( | ||
default: "openai_whisper-base", | ||
supported: self.knownModels | ||
) | ||
) | ||
|
||
computeDisabledModels() | ||
} | ||
|
||
@available(macOS 13, iOS 16, watchOS 10, visionOS 1, *) | ||
public func modelSupport(for deviceIdentifier: String = WhisperKit.deviceName()) -> ModelSupport { | ||
for support in deviceSupports { | ||
if support.identifiers.contains(where: { deviceIdentifier.hasPrefix($0) }) { | ||
return support.models | ||
} | ||
} | ||
|
||
Logging.info("No device support found for \(deviceIdentifier), using default") | ||
return defaultSupport.models | ||
} | ||
|
||
private mutating func computeDisabledModels() { | ||
for i in 0..<deviceSupports.count { | ||
let disabledModels = Set(knownModels).subtracting(deviceSupports[i].models.supported) | ||
self.deviceSupports[i].models.disabled = Array(disabledModels) | ||
} | ||
} | ||
|
||
private static func mergeDeviceSupport(remote: [DeviceSupport], fallback: [DeviceSupport]) -> [DeviceSupport] { | ||
var mergedSupports: [DeviceSupport] = [] | ||
let remoteIdentifiers = Set(remote.flatMap { $0.identifiers }) | ||
|
||
// Add remote device supports, merging with fallback if identifiers overlap | ||
for remoteSupport in remote { | ||
if let fallbackSupport = fallback.first(where: { $0.identifiers.contains(where: remoteSupport.identifiers.contains) }) { | ||
let mergedModels = ModelSupport( | ||
default: remoteSupport.models.default, | ||
supported: (remoteSupport.models.supported + fallbackSupport.models.supported).orderedSet | ||
) | ||
mergedSupports.append(DeviceSupport(identifiers: remoteSupport.identifiers, models: mergedModels)) | ||
} else { | ||
mergedSupports.append(remoteSupport) | ||
} | ||
} | ||
|
||
// Add fallback device supports that don't overlap with remote | ||
for fallbackSupport in fallback where !fallbackSupport.identifiers.contains(where: remoteIdentifiers.contains) { | ||
mergedSupports.append(fallbackSupport) | ||
} | ||
|
||
return mergedSupports | ||
} | ||
} | ||
|
||
// MARK: - Chunking | ||
|
||
public struct AudioChunk { | ||
|
@@ -1346,4 +1454,141 @@ public enum Constants { | |
public static let defaultLanguageCode: String = "en" | ||
|
||
public static let defaultAudioReadFrameSize: AVAudioFrameCount = 1_323_000 // 30s of audio at commonly found 44.1khz sample rate | ||
|
||
public static let fallbackModelSupportConfig: ModelSupportConfig = { | ||
var config = ModelSupportConfig( | ||
repoName: "whisperkit-coreml-fallback", | ||
repoVersion: "0.2", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would we need to identify that it's a fallback config? maybe append -local to version here? |
||
deviceSupports: [ | ||
DeviceSupport( | ||
identifiers: ["iPhone11", "iPhone12", "Watch7", "Watch8"], | ||
models: ModelSupport( | ||
default: "openai_whisper-tiny", | ||
supported: [ | ||
"openai_whisper-base", | ||
"openai_whisper-base.en", | ||
"openai_whisper-tiny", | ||
"openai_whisper-tiny.en", | ||
] | ||
) | ||
), | ||
DeviceSupport( | ||
identifiers: ["iPhone13", "iPad13,18", "iPad13,1"], | ||
models: ModelSupport( | ||
default: "openai_whisper-base", | ||
supported: [ | ||
"openai_whisper-tiny", | ||
"openai_whisper-tiny.en", | ||
"openai_whisper-base", | ||
"openai_whisper-base.en", | ||
"openai_whisper-small", | ||
"openai_whisper-small.en", | ||
] | ||
) | ||
), | ||
DeviceSupport( | ||
identifiers: ["iPhone14", "iPhone15", "iPhone16", "iPhone17", "iPad14,1", "iPad14,2"], | ||
models: ModelSupport( | ||
default: "openai_whisper-base", | ||
supported: [ | ||
"openai_whisper-tiny", | ||
"openai_whisper-tiny.en", | ||
"openai_whisper-base", | ||
"openai_whisper-base.en", | ||
"openai_whisper-small", | ||
"openai_whisper-small.en", | ||
"openai_whisper-large-v2_949MB", | ||
"openai_whisper-large-v2_turbo_955MB", | ||
"openai_whisper-large-v3_947MB", | ||
"openai_whisper-large-v3_turbo_954MB", | ||
"distil-whisper_distil-large-v3_594MB", | ||
"distil-whisper_distil-large-v3_turbo_600MB", | ||
"openai_whisper-large-v3-v20240930_626MB", | ||
"openai_whisper-large-v3-v20240930_turbo_632MB", | ||
] | ||
) | ||
), | ||
DeviceSupport( | ||
identifiers: [ | ||
"Mac13", | ||
"iMac21", | ||
"MacBookAir10,1", | ||
"MacBookPro17", | ||
"MacBookPro18", | ||
"Macmini9", | ||
"iPad13,16", | ||
"iPad13,4", | ||
"iPad13,8", | ||
], | ||
models: ModelSupport( | ||
default: "openai_whisper-large-v3-v20240930", | ||
supported: [ | ||
"openai_whisper-tiny", | ||
"openai_whisper-tiny.en", | ||
"openai_whisper-base", | ||
"openai_whisper-base.en", | ||
"openai_whisper-small", | ||
"openai_whisper-small.en", | ||
"openai_whisper-large-v2", | ||
"openai_whisper-large-v2_949MB", | ||
"openai_whisper-large-v3", | ||
"openai_whisper-large-v3_947MB", | ||
"distil-whisper_distil-large-v3", | ||
"distil-whisper_distil-large-v3_594MB", | ||
"openai_whisper-large-v3-v20240930", | ||
"openai_whisper-large-v3-v20240930_626MB", | ||
] | ||
) | ||
), | ||
DeviceSupport( | ||
identifiers: [ | ||
"Mac14", | ||
"Mac15", | ||
"Mac16", | ||
"iPad14,3", | ||
"iPad14,4", | ||
"iPad14,5", | ||
"iPad14,6", | ||
"iPad14,8", | ||
"iPad14,9", | ||
"iPad14,10", | ||
"iPad14,11", | ||
"iPad16", | ||
], | ||
models: ModelSupport( | ||
default: "openai_whisper-large-v3-v20240930", | ||
supported: [ | ||
"openai_whisper-tiny", | ||
"openai_whisper-tiny.en", | ||
"openai_whisper-base", | ||
"openai_whisper-base.en", | ||
"openai_whisper-small", | ||
"openai_whisper-small.en", | ||
"openai_whisper-large-v2", | ||
"openai_whisper-large-v2_949MB", | ||
"openai_whisper-large-v2_turbo", | ||
"openai_whisper-large-v2_turbo_955MB", | ||
"openai_whisper-large-v3", | ||
"openai_whisper-large-v3_947MB", | ||
"openai_whisper-large-v3_turbo", | ||
"openai_whisper-large-v3_turbo_954MB", | ||
"distil-whisper_distil-large-v3", | ||
"distil-whisper_distil-large-v3_594MB", | ||
"distil-whisper_distil-large-v3_turbo", | ||
"distil-whisper_distil-large-v3_turbo_600MB", | ||
"openai_whisper-large-v3-v20240930", | ||
"openai_whisper-large-v3-v20240930_turbo", | ||
"openai_whisper-large-v3-v20240930_626MB", | ||
"openai_whisper-large-v3-v20240930_turbo_632MB", | ||
] | ||
) | ||
), | ||
], | ||
includeFallback: false | ||
) | ||
|
||
return config | ||
}() | ||
|
||
public static let knownModels: [String] = fallbackModelSupportConfig.deviceSupports.flatMap { $0.models.supported }.orderedSet | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add log that defaultSupport was used