From 52db6fb85aa0faf0e20141959a6872e350ec2e0c Mon Sep 17 00:00:00 2001 From: link2026 Date: Wed, 17 Jun 2026 09:00:09 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(AI):=20=E5=88=87=E6=8D=A2=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E4=B8=8B=E8=BD=BD=E6=BA=90=E8=87=B3=E9=AD=94=E6=90=AD?= =?UTF-8?q?=E5=AE=98=E6=96=B9=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 modelScopeRepo 函数,为不同模型类型配置魔搭官方仓库ID - 修改 fileURL 函数,主模型(MNN/MLX)优先使用魔搭官方源, 已废弃的VL模型回退自建镜像 - 更新文档注释,说明魔搭OSS支持Range请求和断点续传特性 refactor(i18n): 优化AI相关界面文本和提示信息 - 新增数值验证相关的国际化字符串 - 调整AI整理失败提示文案,更明确表达原意 - 更新AI解读不可用提示,引导用户前往模型管理页面 - 补充删除操作的相关确认提示文本 - 添加录音权限错误提示和识别失败重试建议 chore(i18n): 清理过时的解析失败提示文本 ``` --- 康康/AI/ModelManifest.swift | 22 ++++++++++++--- 康康/Localizable.xcstrings | 53 +++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/康康/AI/ModelManifest.swift b/康康/AI/ModelManifest.swift index 951d07e..7b98faa 100644 --- a/康康/AI/ModelManifest.swift +++ b/康康/AI/ModelManifest.swift @@ -11,10 +11,21 @@ struct ModelFile: Equatable, Sendable { /// 字节数与服务器素材逐一核对一致,见 /// docs/superpowers/specs/2026-05-29-model-download-design.md 附录 A。 nonisolated enum ModelManifest { - /// 自建 Caddy 静态服务(用户自建 HTTPS 反代)。 + /// 自建 Caddy 静态镜像。现仅 `.vl`(已废弃,不再下载)回退用;主模型 / MLX 兜底已切魔搭官方。 /// 备选纯 IP(需 App 端 ATS 例外): http://101.132.124.52:5244/ static let baseURL = URL(string: "https://file.myv0.com/")! + /// 各模型的魔搭(ModelScope)官方仓库 id。大陆可达;`resolve/master` 会 302 跳阿里 OSS, + /// OSS 支持 Range,断点续传穿透重定向(实测 206 + 精确分片)。各文件大小与本清单逐一核对一致(2026-06 实测)。 + /// 注意组织名:MNN 模型在魔搭组织为 `MNN`(非 HuggingFace 的 taobao-mnn);MLX 沿用 mlx-community。 + static func modelScopeRepo(for kind: ModelKind) -> String? { + switch kind { + case .mnnLLM: return "MNN/Qwen3.5-2B-MNN" + case .llm: return "mlx-community/Qwen3.5-2B-4bit" + case .vl: return nil // 已废弃,不再下载 / 分发,不提供魔搭源 + } + } + static func files(for kind: ModelKind) -> [ModelFile] { switch kind { case .llm: @@ -79,9 +90,14 @@ nonisolated enum ModelManifest { files(for: kind).reduce(0) { $0 + $1.bytes } } - /// 单个文件的下载 URL = baseURL / <仓库名> / <相对路径>。 + /// 单个文件的下载 URL。主模型 MNN / MLX 兜底走魔搭官方 `resolve/master`; + /// 已废弃的 `.vl` 回退自建镜像(实际不会被下载)。 static func fileURL(for kind: ModelKind, file: ModelFile) -> URL { - baseURL + if let repo = modelScopeRepo(for: kind) { + return URL(string: "https://modelscope.cn/models/\(repo)/resolve/master/")! + .appendingPathComponent(file.path) + } + return baseURL .appendingPathComponent(kind.rawValue, isDirectory: true) .appendingPathComponent(file.path) } diff --git a/康康/Localizable.xcstrings b/康康/Localizable.xcstrings index 4980489..37e6637 100644 --- a/康康/Localizable.xcstrings +++ b/康康/Localizable.xcstrings @@ -335,6 +335,12 @@ } } } + }, + "%@数值超出合理范围" : { + + }, + "%@请填数字" : { + }, "%lld" : { @@ -1166,7 +1172,7 @@ "AI 整理中 · 本地推理" : { }, - "AI 整理失败,已填入原话" : { + "AI 整理没成功,已填入未整理的原文" : { }, "AI 模型尚未准备好" : { @@ -1266,7 +1272,7 @@ } } }, - "AI 解读暂不可用(模型未就绪或繁忙)" : { + "AI 解读需先在「我的 · 模型管理」下载模型" : { }, "AI 识别与解读可能出现错误或遗漏:拍照得到的数值、单位、参考范围请务必与原始报告核对," : { @@ -2228,6 +2234,9 @@ }, "从药品库删除" : { + }, + "从药品库删除这种药?" : { + }, "任何健康决策(是否就医、用药、调整治疗方案等)请咨询专业医疗人员,并以其意见为准。" : { "localizations" : { @@ -3260,6 +3269,9 @@ } } } + }, + "关联的原图会一并永久删除,无法恢复。" : { + }, "关节痛" : { "localizations" : { @@ -3596,6 +3608,9 @@ } } } + }, + "删除后不再监测该指标,已记录的历史数据仍保留。" : { + }, "删除后无法恢复。" : { "localizations" : { @@ -3640,6 +3655,9 @@ } } } + }, + "删除后该提醒不再触发。" : { + }, "删除提醒" : { "localizations" : { @@ -3662,6 +3680,9 @@ } } } + }, + "删除这条提醒?" : { + }, "删除这项自定义指标" : { "localizations" : { @@ -3684,6 +3705,9 @@ } } } + }, + "删除这项自定义指标?" : { + }, "到点啦,记得完成" : { "localizations" : { @@ -8000,6 +8024,9 @@ }, "无法导入 Apple 健康资料" : { + }, + "无法开始录音,请检查麦克风 / 语音识别权限" : { + }, "日" : { "localizations" : { @@ -8304,6 +8331,7 @@ } }, "未知错误:%@" : { + "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { @@ -8650,6 +8678,9 @@ } } } + }, + "本地推理这次没成功,点右上「解读」重试" : { + }, "本地档案中暂无相关记录,将仅按你的描述整理" : { @@ -9569,6 +9600,12 @@ }, "没有识别到指标,点「加一项」手动补充,或返回重拍" : { + }, + "没自动认出指标,挪一下框再试,或手动填写" : { + + }, + "没认出药品信息,可检查照片清晰度后重拍,或手动填写" : { + }, "没识别到文字,拍清楚一点再试" : { @@ -11122,9 +11159,6 @@ }, "规格,如:80mg×7粒" : { - }, - "解析失败:%@" : { - }, "解读" : { @@ -11491,6 +11525,15 @@ }, "识别此张" : { + }, + "识别没成功,可重拍或手动填写" : { + + }, + "识别没成功,挪一下框再试,或手动填写" : { + + }, + "识别没成功,请手动填写" : { + }, "识别没有读出指标,请手动补充" : { "extractionState" : "stale",