Files
kangkang/康康Tests/MedicationScanServiceTests.swift
link2026 9d856fcfc4 ```
feat(AI): 集成MNN推理引擎替换MLX作为主AI运行时

- 引入MNN(alibaba) + Arm SME2 + CPU作为主AI运行时,支持A19/iPhone17的
  SME2和A17的NEON加速
- 添加MLX Swift作为兜底GPU推理方案,实现双后端切换机制
- 使用单一Qwen3.5-2B多模态模型(1.2GB),替代原有的LLM+VL分离架构
- 实现InferenceEngine.current引擎选择逻辑,真机默认MNN,模拟器回退MLX
- 更新AIAgent架构,通过MNNLLMBridge(ObjC++) → MNNBackend进行推理
- 修改队列机制防止并发推理导致OOM,使用信号量闸门控制显存占用
- 更新文档中的技术栈说明、模块边界和周次交付计划
```
2026-06-15 09:24:59 +08:00

104 lines
4.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Testing
import Foundation
import SwiftData
@testable import
/// MedicationScanService.parseMedicationsJSON (JSON )
struct MedicationScanServiceTests {
@Test func parsesStandardObject() throws {
let raw = """
{"medications":[{"name":"","strength":"80mg×7","usage":""}]}
"""
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.count == 1)
#expect(meds[0].name == "缬沙坦胶囊")
#expect(meds[0].strength == "80mg×7粒")
#expect(meds[0].entryText == "缬沙坦胶囊 80mg×7粒")
}
@Test func parsesBareArrayWithFence() throws {
let raw = """
```json
[{"name":"","strength":"0.5g×30","usage":",1,2"}]
```
"""
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.count == 1)
#expect(meds[0].entryText == "二甲双胍缓释片 0.5g×30片 · 口服,一次1片,一日2次")
}
@Test func parsesChineseKeysAndDedupes() throws {
let raw = """
{"medications":[
{"":"","":"100mg","":""},
{"name":"","strength":"100mg","usage":""}
]}
"""
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.count == 1)
}
@Test func emptyNameRowsAreDropped() throws {
let raw = #"{"medications":[{"name":"","strength":"10mg","usage":""}]}"#
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.isEmpty)
}
@Test func trailingCommaIsRepaired() throws {
let raw = #"{"medications":[{"name":"","strength":"10mg×6","usage":"",},]}"#
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.count == 1)
#expect(meds[0].name == "氯雷他定片")
}
@Test func invalidJSONThrows() {
#expect(throws: (any Error).self) {
try MedicationScanService.parseMedicationsJSON("识别不出来,抱歉")
}
}
/// (prompt );,
@Test func parsesEnglishDrugName() throws {
let raw = #"{"medications":[{"name":"Amoxicillin","strength":"500mg","usage":"Take one capsule three times daily"}]}"#
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.count == 1)
#expect(meds[0].name == "Amoxicillin")
#expect(meds[0].entryText == "Amoxicillin 500mg · Take one capsule three times daily")
}
/// + (prompt "()")
@Test func parsesGenericWithBrandName() throws {
let raw = #"{"medications":[{"name":"()","strength":"80mg×7","usage":""}]}"#
let meds = try MedicationScanService.parseMedicationsJSON(raw)
#expect(meds.count == 1)
#expect(meds[0].name == "缬沙坦胶囊(代文)")
}
}
/// 线(tab )
@MainActor
struct MedicationTimelineTests {
private func makeContext() throws -> ModelContext {
// DiaryEntry Asset(),schema Asset.self,
let schema = Schema([DiaryEntry.self, Asset.self])
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
return ModelContext(try ModelContainer(for: schema, configurations: [config]))
}
@Test func medicationTaggedDiaryMapsToMedicationKind() throws {
let ctx = try makeContext()
let med = DiaryEntry(content: "缬沙坦胶囊 80mg×7粒", tags: [DiaryEntry.medicationTag])
let plain = DiaryEntry(content: "今天睡得不错")
ctx.insert(med); ctx.insert(plain)
try ctx.save()
let medEntry = TimelineEntry.from(diary: med)
#expect(medEntry.kind == .medication)
#expect(medEntry.title == "缬沙坦胶囊 80mg×7粒")
#expect(TimelineEntry.from(diary: plain).kind == .diary)
}
}