Files
MLXServer/MLXServer/Models/ModelConfig.swift

98 lines
3.1 KiB
Swift

import Foundation
import MLXLMCommon
/// Defines a supported model with its metadata.
struct ModelConfig: Identifiable, Hashable {
enum LoaderKind: Hashable {
case llm
case vlm
}
let id: String // alias: "gemma", "gemma3n", "qwen"
let repoId: String // HuggingFace ID
let displayName: String
let contextLength: Int
let loaderKind: LoaderKind
let supportsImages: Bool
let supportsTools: Bool
/// All models supported by the app.
static let availableModels: [ModelConfig] = [
ModelConfig(
id: "gemma",
repoId: "mlx-community/gemma-3-4b-it-4bit",
displayName: "Gemma 3 4B",
contextLength: 128_000,
loaderKind: .vlm,
supportsImages: true,
supportsTools: true
),
ModelConfig(
id: "qwen",
repoId: "mlx-community/Qwen3.5-4B-MLX-4bit",
displayName: "Qwen3.5 4B",
contextLength: 256_000,
loaderKind: .vlm,
supportsImages: true,
supportsTools: true
),
ModelConfig(
id: "qwen3.5-0.8b",
repoId: "mlx-community/Qwen3.5-0.8B-4bit",
displayName: "Qwen3.5 0.8B",
contextLength: 256_000,
loaderKind: .vlm,
supportsImages: true,
supportsTools: true
),
ModelConfig(
id: "qwen3.5-9b",
repoId: "mlx-community/Qwen3.5-9B-4bit",
displayName: "Qwen3.5 9B",
contextLength: 256_000,
loaderKind: .vlm,
supportsImages: true,
supportsTools: true
),
ModelConfig(
id: "stheno",
repoId: "synk/L3-8B-Stheno-v3.2-MLX",
displayName: "Stheno L3 8B",
contextLength: 8_192,
loaderKind: .llm,
supportsImages: false,
supportsTools: false
),
]
static let `default` = availableModels[0]
/// Whether this model is cached locally (no download needed).
var isLocal: Bool {
LocalModelResolver.isAvailable(repoId: repoId)
}
/// Build a ModelConfiguration for mlx-swift-lm from this config.
var modelConfiguration: ModelConfiguration {
ModelConfiguration(id: repoId)
}
/// Resolve a model string (alias, full repo ID, or partial match) to a ModelConfig.
/// Mirrors the Python server's `ModelManager.resolve_model()`.
static func resolve(_ requested: String) -> ModelConfig? {
// Exact alias match
if let config = availableModels.first(where: { $0.id == requested }) {
return config
}
// Exact repo ID match
if let config = availableModels.first(where: { $0.repoId == requested }) {
return config
}
// Partial match (e.g. "gemma-3-4b-it" matches the gemma entry)
if let config = availableModels.first(where: { requested.contains($0.id) || $0.repoId.contains(requested) || requested.contains($0.repoId) }) {
return config
}
return nil
}
}