Files
2026-07-13 13:33:03 +08:00

111 lines
4.3 KiB
Swift

//
// ModelUtils.swift
// MNNLLMiOS
//
// Created by 游薪渝(揽清) on 2025/9/29.
//
import Foundation
class ModelUtils {
/// Check if the model supports thinking mode switching
/// - Parameter tags: Model tags
/// - Returns: Whether thinking mode switching is supported
static func isSupportThinkingSwitch(_ tags: [String], modelName: String) -> Bool {
return isQwen3(modelName) && !modelName.contains("2507") && (tags.contains(where: { $0.localizedCaseInsensitiveContains("Think") }) ||
tags.contains(where: { $0.localizedCaseInsensitiveContains("思考") }))
}
/// Check if the model is built in local model
/// - Parameter model: ModelInfo
/// - Returns: Whether is built in local model
static func isBuiltInLocalModel(_ model: ModelInfo) -> Bool {
guard let vendor = model.vendor, vendor.lowercased() == "local" else { return false }
guard let sources = model.sources, let localSource = sources["local"] else { return false }
return true
}
/// Check if it's an R1 model
/// - Parameter modelName: Model name
/// - Returns: Whether it's an R1 model
static func isR1Model(_ modelName: String) -> Bool {
return modelName.lowercased().contains("deepseek-r1")
}
/// Check if it's a Qwen3 model
/// - Parameter modelName: Model name
/// - Returns: Whether it's a Qwen3 model
static func isQwen3(_ modelName: String) -> Bool {
return modelName.lowercased().contains("qwen3")
}
/// Check if it's an audio model
/// - Parameter modelName: Model name
/// - Returns: Whether it's an audio model
static func isAudioModel(_ modelName: String) -> Bool {
return modelName.lowercased().contains("audio")
}
static func isThinkMode(_: [Any]) -> Bool {
return false
}
/// Check if it's a visual model
/// - Parameter modelName: Model name
/// - Returns: Whether it's a visual model
static func isVisualModel(_ modelName: String) -> Bool {
return modelName.lowercased().contains("vl") || isOmni(modelName)
}
/// Check if it's an Omni model
/// - Parameter modelName: Model name
/// - Returns: Whether it's an Omni model
static func isOmni(_ modelName: String) -> Bool {
return modelName.lowercased().contains("omni")
}
/// Check if it's a diffusion model
/// - Parameter modelName: Model name
/// - Returns: Whether it's a diffusion model
static func isDiffusionModel(_ modelName: String) -> Bool {
return modelName.lowercased().contains("stable-diffusion")
}
/// Check if it's a Sana Diffusion model (style transfer)
/// - Parameter modelName: Model name
/// - Returns: Whether it's a Sana Diffusion model
static func isSanaDiffusionModel(_ modelName: String) -> Bool {
let lowercased = modelName.lowercased()
return lowercased.contains("sana") || lowercased.contains("ghibli")
}
/// Check if it's a Sana Diffusion model by checking the model directory structure
/// - Parameter path: Path to the model directory
/// - Returns: Whether the directory contains a Sana Diffusion model
static func isSanaDiffusionModel(atPath path: String) -> Bool {
let fm = FileManager.default
let llmPath = (path as NSString).appendingPathComponent("llm")
let connectorPath = (path as NSString).appendingPathComponent("connector.mnn")
let vaeEncoderPath = (path as NSString).appendingPathComponent("vae_encoder.mnn")
// Sana Diffusion model requires llm/ subdirectory, connector.mnn, and vae_encoder.mnn
return fm.fileExists(atPath: llmPath) &&
fm.fileExists(atPath: connectorPath) &&
fm.fileExists(atPath: vaeEncoderPath)
}
/// Check if it's any type of diffusion model (Stable Diffusion or Sana)
/// - Parameter modelName: Model name
/// - Returns: Whether it's any diffusion model
static func isAnyDiffusionModel(_ modelName: String) -> Bool {
return isDiffusionModel(modelName) || isSanaDiffusionModel(modelName)
}
/// Check if audio output is supported
/// - Parameter modelName: Model name
/// - Returns: Whether audio output is supported
static func supportAudioOutput(_ modelName: String) -> Bool {
return isOmni(modelName)
}
}