80 lines
3.5 KiB
Swift
80 lines
3.5 KiB
Swift
import Testing
|
|
import Foundation
|
|
@testable import 康康
|
|
|
|
/// 语音直达的两个纯函数:LLM 输出解析 + 关键词回退。
|
|
struct VoiceIntentServiceTests {
|
|
|
|
// MARK: - parseIntent(LLM 输出容错)
|
|
|
|
@Test func parsesStandardJSON() {
|
|
#expect(VoiceIntentService.parseIntent(from: #"{"intent":"indicator"}"#) == .indicator)
|
|
}
|
|
|
|
@Test func parsesFencedAndThinkWrapped() {
|
|
let raw = """
|
|
<think>用户想记血压</think>
|
|
```json
|
|
{"intent": "Indicator"}
|
|
```
|
|
"""
|
|
#expect(VoiceIntentService.parseIntent(from: raw) == .indicator)
|
|
}
|
|
|
|
@Test func parsesBareWord() {
|
|
#expect(VoiceIntentService.parseIntent(from: "symptom") == .symptom)
|
|
#expect(VoiceIntentService.parseIntent(from: "\"diary\"。") == .diary)
|
|
}
|
|
|
|
@Test func unknownReturnsNil() {
|
|
#expect(VoiceIntentService.parseIntent(from: #"{"intent":"unknown"}"#) == nil)
|
|
#expect(VoiceIntentService.parseIntent(from: "我不知道") == nil)
|
|
}
|
|
|
|
// MARK: - keywordMatch(回退规则与优先级)
|
|
|
|
@Test func reminderBeatsMedication() {
|
|
// 「提醒我吃药」是设提醒,不是记用药 —— reminder 规则必须排最前
|
|
#expect(VoiceIntentService.keywordMatch("每天八点提醒我吃药") == .reminder)
|
|
}
|
|
|
|
@Test func commonUtterances() {
|
|
#expect(VoiceIntentService.keywordMatch("记一下血压,高压128") == .indicator)
|
|
#expect(VoiceIntentService.keywordMatch("我有点头疼") == .symptom)
|
|
#expect(VoiceIntentService.keywordMatch("拍个药盒") == .medication)
|
|
#expect(VoiceIntentService.keywordMatch("把体检报告存进去") == .archive)
|
|
#expect(VoiceIntentService.keywordMatch("整理一份给医生看的") == .export)
|
|
#expect(VoiceIntentService.keywordMatch("写个日记") == .diary)
|
|
}
|
|
|
|
@Test func unmatchedDefaultsToDiary() {
|
|
// 不明确命中其它意图时,兜底进日记(最常见、最自由的入口)
|
|
#expect(VoiceIntentService.keywordMatch("啦啦啦啦") == .diary)
|
|
#expect(VoiceIntentService.keywordMatch("今天感觉不太舒服") == .diary)
|
|
#expect(VoiceIntentService.keywordMatch("有点难受") == .diary)
|
|
}
|
|
|
|
// MARK: - 相机类意图的误开防护(本次修复重点)
|
|
|
|
@Test func negatedMedicationDoesNotOpenCamera() {
|
|
// 「没吃药 / 忘了吃药 / 不用吃药」不该归 medication(会弹拍药盒相机),落 diary
|
|
#expect(VoiceIntentService.keywordMatch("今天太忙,忘了吃药") == .diary)
|
|
#expect(VoiceIntentService.keywordMatch("我今天没吃药") == .diary)
|
|
#expect(VoiceIntentService.keywordMatch("医生说先不用吃药") == .diary)
|
|
}
|
|
|
|
@Test func casualReportMentionDoesNotOpenCamera() {
|
|
// 顺口提到体检/报告,不是要拍报告归档,不该弹文档相机
|
|
#expect(VoiceIntentService.keywordMatch("下周打算去做个体检") == .diary)
|
|
#expect(VoiceIntentService.keywordMatch("医生说我报告没什么大问题") == .diary)
|
|
}
|
|
|
|
@Test func genuineCameraIntentsStillMatch() {
|
|
// 真实的拍药盒 / 归档意图仍要正确命中
|
|
#expect(VoiceIntentService.keywordMatch("拍个药盒") == .medication)
|
|
#expect(VoiceIntentService.keywordMatch("我吃了降压药,记一下") == .medication)
|
|
#expect(VoiceIntentService.keywordMatch("把体检报告存进去") == .archive)
|
|
#expect(VoiceIntentService.keywordMatch("这张化验单归档") == .archive)
|
|
}
|
|
}
|