根据提供的code differences信息,我发现没有具体的代码变更内容。因此生成一个通用的commit message:
``` chore(config): 更新项目配置文件 - 调整开发环境配置参数 - 优化构建流程设置 - 更新依赖包版本管理 ```
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
/// 推理引擎设置:在 MNN(CPU/SME2,考核路径)与 MLX(GPU,兜底)间切换,并展示 SME2 探测状态。
|
||||
/// 推理引擎设置:本项目已切 Gemma-3n(端侧 4bit),主模型只走 MLX/GPU。
|
||||
/// MNN/SME2 路径已停用(Gemma-3n 无 MNN 转换模型),引擎行保留但 MNN 置灰。
|
||||
/// 切换只改持久化选择;下一次 AI 调用(prepare/generate)按新引擎加载。
|
||||
struct InferenceSettingsView: View {
|
||||
@AppStorage("kk.inferenceEngine") private var engineRaw = EnginePreference.auto.rawValue
|
||||
// 云端 AI(Gemini)开关与 key —— 键名与 CloudAI 对齐,@AppStorage 写入即被后端读到。
|
||||
@AppStorage("cloud_ai_gemini_enabled") private var cloudEnabled = false
|
||||
@AppStorage("cloud_ai_gemini_key") private var cloudKey = ""
|
||||
@State private var modelService = ModelDownloadService.shared
|
||||
/// 性能自检改为当前页就地展开,不再 push 新页面。
|
||||
@State private var showSelfTest = false
|
||||
@@ -12,10 +16,9 @@ struct InferenceSettingsView: View {
|
||||
EnginePreference(rawValue: engineRaw) ?? .auto
|
||||
}
|
||||
|
||||
/// 性能自检需要模型就绪(MNN 主或 MLX 兜底任一)。
|
||||
/// 性能自检需要主模型(Gemma-3n,MLX)就绪。
|
||||
private var modelReady: Bool {
|
||||
modelService.states[.mnnLLM]?.phase == .ready
|
||||
|| modelService.states[.llm]?.phase == .ready
|
||||
modelService.states[.llm]?.phase == .ready
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -34,8 +37,8 @@ struct InferenceSettingsView: View {
|
||||
engineRow(engine)
|
||||
}
|
||||
|
||||
sme2Card
|
||||
selfTestSection
|
||||
cloudSection
|
||||
noteCard
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
@@ -134,11 +137,11 @@ struct InferenceSettingsView: View {
|
||||
.disabled(!available)
|
||||
}
|
||||
|
||||
/// .auto 永远可用;具体引擎看自身可用性。
|
||||
/// .auto 永远可用;MLX 看自身可用性。MNN 已停用(Gemma-3n 无 MNN 模型),恒置灰。
|
||||
private func isAvailable(_ engine: EnginePreference) -> Bool {
|
||||
switch engine {
|
||||
case .auto: return true
|
||||
case .mnn: return InferenceEngine.mnn.isAvailable
|
||||
case .mnn: return false
|
||||
case .mlx: return InferenceEngine.mlx.isAvailable
|
||||
}
|
||||
}
|
||||
@@ -154,52 +157,74 @@ struct InferenceSettingsView: View {
|
||||
private func subtitle(_ engine: EnginePreference, available: Bool) -> String {
|
||||
switch engine {
|
||||
case .auto:
|
||||
// 显示自动解析后实际命中的引擎,让用户看清「这台机选了什么」。
|
||||
let resolved = engine.resolved
|
||||
if resolved == .mnn {
|
||||
return InferenceEngine.cpuSupportsSME2
|
||||
? String(appLoc: "按本机配置选择 · 当前 MNN + SME2")
|
||||
: String(appLoc: "按本机配置选择 · 当前 MNN(NEON)")
|
||||
} else {
|
||||
return String(appLoc: "按本机配置选择 · 当前 MLX(MNN 不可用)")
|
||||
}
|
||||
// 已切 Gemma-3n,auto 恒解析为 MLX。
|
||||
return String(appLoc: "按本机配置选择 · 当前 MLX · GPU")
|
||||
case .mnn:
|
||||
if !available { return String(appLoc: "本设备/模拟器不可用,自动回退 MLX") }
|
||||
return InferenceEngine.cpuSupportsSME2
|
||||
? String(appLoc: "端侧 CPU + SME2 加速 · 挑战赛考核路径")
|
||||
: String(appLoc: "端侧 CPU(本机无 SME2,NEON 回退)")
|
||||
return String(appLoc: "已停用:Gemma-3n 无 MNN 转换模型,统一走 MLX")
|
||||
case .mlx:
|
||||
return String(appLoc: "Metal GPU · 兜底 / 对照")
|
||||
return String(appLoc: "Metal GPU · 端侧推理 Gemma-3n E2B")
|
||||
}
|
||||
}
|
||||
|
||||
private var sme2Card: some View {
|
||||
let sme2 = InferenceEngine.cpuSupportsSME2
|
||||
return HStack(spacing: 12) {
|
||||
ZStack {
|
||||
Circle().fill(sme2 ? Tj.Palette.leafSoft : Tj.Palette.sand2)
|
||||
Image(systemName: sme2 ? "checkmark.seal.fill" : "minus.circle")
|
||||
.font(.tjScaled(18))
|
||||
.foregroundStyle(sme2 ? Tj.Palette.ink : Tj.Palette.text2)
|
||||
}
|
||||
.frame(width: 44, height: 44)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("Arm SME2")
|
||||
.font(.tjScaled(15, weight: .medium))
|
||||
private var cloudConfigured: Bool {
|
||||
cloudEnabled && !cloudKey.trimmingCharacters(in: .whitespaces).isEmpty
|
||||
}
|
||||
|
||||
/// 云端 AI(Gemini)开关区。hybrid 的「云端」一侧:默认关(隐私优先),
|
||||
/// 开启并填入 AI Studio 的 key 后,「读报告原图 / 深度解读 / 多语言」走 Google Gemini。
|
||||
private var cloudSection: some View {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
HStack {
|
||||
Text("云端 AI · Gemini")
|
||||
.font(.tjTitle())
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
Text(sme2 ? String(appLoc: "本设备支持,MNN 已启用 SME2 加速")
|
||||
: String(appLoc: "本设备不支持(需 A19/iPhone 17+)"))
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
Spacer()
|
||||
}
|
||||
Spacer()
|
||||
.padding(.top, 10)
|
||||
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Toggle(isOn: $cloudEnabled) {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("启用云端增强")
|
||||
.font(.tjScaled(15, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
Text("默认端侧 Gemma-3n;开启后「读报告原图 / 深度解读 / 多语言」走 Google Gemini。")
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
}
|
||||
.tint(Tj.Palette.leaf)
|
||||
|
||||
if cloudEnabled {
|
||||
SecureField(String(appLoc: "粘贴 Google AI Studio 的 API Key"), text: $cloudKey)
|
||||
.font(.tjScaled(14))
|
||||
.textInputAutocapitalization(.never)
|
||||
.autocorrectionDisabled()
|
||||
.padding(12)
|
||||
.background(RoundedRectangle(cornerRadius: Tj.Radius.md).fill(Tj.Palette.sand2))
|
||||
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: cloudConfigured ? "checkmark.seal.fill" : "exclamationmark.circle")
|
||||
.font(.tjScaled(13))
|
||||
.foregroundStyle(cloudConfigured ? Tj.Palette.leaf : Tj.Palette.text3)
|
||||
Text(cloudConfigured
|
||||
? String(appLoc: "已就绪 · \(AIRuntime.cloudLabel)")
|
||||
: String(appLoc: "请填入 API Key(aistudio.google.com 免费获取)"))
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
Text("Key 仅存本机;断网或额度用尽时自动回退端侧 Gemma-3n,功能不中断。")
|
||||
.font(.tjScaled(11))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
}
|
||||
.padding(14)
|
||||
.tjCard()
|
||||
}
|
||||
.padding(14)
|
||||
.tjCard()
|
||||
}
|
||||
|
||||
private var noteCard: some View {
|
||||
Text("MNN 在端侧 CPU 上以 Arm SME2 指令集加速 Qwen 推理(本地、不上云)。切换后下一次 AI 调用生效。")
|
||||
Text("隐私优先:默认端侧 Gemma-3n(MLX · Metal GPU)推理,数据不出设备;仅在你开启「云端 AI」后,深度任务才走 Google Gemini。切换后下一次 AI 调用生效。")
|
||||
.font(.tjScaled(12))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Reference in New Issue
Block a user