feat: 交叉验证 AI vs LAMP(#15,一致确认/不一致升级会诊)
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
package service
|
||||
|
||||
// CrossValidate 交叉验证:AI 检测结果 vs LAMP 检测结果(规格书:一致→确认诊断;不一致→升级专家会诊)
|
||||
func CrossValidate(aiClass, lampResult string, lampDiseases []string) (bool, string) {
|
||||
switch {
|
||||
case lampResult == "invalid":
|
||||
return false, "LAMP 判读无效,建议复检或专家会诊"
|
||||
case aiClass == "":
|
||||
return false, "未找到关联巡检记录,暂无法交叉验证"
|
||||
case aiClass == "sick" && lampResult == "positive":
|
||||
return true, "AI 检出异常与 LAMP 阳性一致,确认诊断"
|
||||
case aiClass == "healthy" && lampResult == "negative":
|
||||
return true, "AI 未见异常与 LAMP 阴性一致"
|
||||
case aiClass == "sick" && lampResult == "negative":
|
||||
return false, "AI 检出异常但 LAMP 阴性,建议专家会诊"
|
||||
case aiClass == "healthy" && lampResult == "positive":
|
||||
return false, "AI 未见异常但 LAMP 阳性,建议专家会诊"
|
||||
default:
|
||||
return false, "交叉验证结果待确认"
|
||||
}
|
||||
}
|
||||
|
||||
// AIClassFromDetections 从巡检检测结果归纳 AI 结论(任一非 healthy 视为 sick)
|
||||
func AIClassFromDetections(detections []AIDetection) string {
|
||||
if len(detections) == 0 {
|
||||
return ""
|
||||
}
|
||||
for _, d := range detections {
|
||||
if d.ClassName != "healthy" {
|
||||
return "sick"
|
||||
}
|
||||
}
|
||||
return "healthy"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCrossValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
aiClass string
|
||||
lampResult string
|
||||
wantOK bool
|
||||
}{
|
||||
{"AI异常+LAMP阳性 一致", "sick", "positive", true},
|
||||
{"AI健康+LAMP阴性 一致", "healthy", "negative", true},
|
||||
{"AI异常+LAMP阴性 不一致", "sick", "negative", false},
|
||||
{"AI健康+LAMP阳性 不一致", "healthy", "positive", false},
|
||||
{"LAMP无效 不一致", "sick", "invalid", false},
|
||||
{"无AI记录 不一致", "", "positive", false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
ok, reason := CrossValidate(c.aiClass, c.lampResult, []string{"核型多角体病"})
|
||||
if ok != c.wantOK {
|
||||
t.Errorf("%s: ok=%v, want %v(原因 %s)", c.name, ok, c.wantOK, reason)
|
||||
}
|
||||
if reason == "" {
|
||||
t.Errorf("%s: 缺少原因说明", c.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAIClassFromDetections(t *testing.T) {
|
||||
if got := AIClassFromDetections(nil); got != "" {
|
||||
t.Errorf("空检测应为空,实际 %s", got)
|
||||
}
|
||||
if got := AIClassFromDetections([]AIDetection{{ClassName: "healthy", Confidence: 0.9}}); got != "healthy" {
|
||||
t.Errorf("全健康应为 healthy,实际 %s", got)
|
||||
}
|
||||
if got := AIClassFromDetections([]AIDetection{{ClassName: "healthy"}, {ClassName: "sick", Confidence: 0.6}}); got != "sick" {
|
||||
t.Errorf("含 sick 应为 sick,实际 %s", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user