import Foundation /// 「健康记录」写入时,让 LLM 从医生问诊角度提 3-4 个追问。 /// 输出严格 JSON,每个 question 带 dim(问诊维度)+ q(展示)+ fill(可一键追加的模板)。 /// /// 为什么要 `dim`(对齐 2026-05-30 prompt 优化): /// 1.7B 模型对「不要重复」这类否定指令遵循很差,且先验会把每轮问题都拉向同一簇症状。 /// 改成「从固定维度清单里挑,每条标注 dim,跨轮排除已覆盖维度」这种正向结构约束后, /// 去重从「字面比对」升级为「按维度结构去重」,轮内扎堆和轮间换皮重复都能压住。 enum DiaryAssistPrompts { /// 固定问诊维度清单。模型每条问题必须正好归属其中一个;UI 累积已覆盖维度回传下一轮。 /// 顺序即展示/示例顺序,改动需同步 few-shot。 static let dimensions: [String] = [ "起病诱因", "症状性质", "伴随症状", "加重缓解", "持续频率", "既往家族史", "用药过敏", "生活方式", ] /// - content: 患者当前全文。 /// - coveredDimensions: 之前各轮已经问过(或记录里已写明)的维度名,本轮必须避开。 /// 第一轮传空数组。 static func suggest(content: String, coveredDimensions: [String] = []) -> String { let covered = coveredDimensions.filter { !$0.isEmpty } let coveredLine = covered.isEmpty ? "无" : covered.joined(separator: "、") let excludeRule = covered.isEmpty ? "" : "\n- 本轮【严禁】选择这些已覆盖维度:\(covered.joined(separator: "、"));只能从其余维度里挑。" return """ 你是社区医生的小助手。患者写了一段身体状态的健康记录,信息可能不够完整。 请从医生问诊角度提出 3-4 个最值得追问的问题,帮患者把这条记录补全。 【问诊维度清单】每个问题必须正好归属其中一个,并用 dim 标注: 1. 起病诱因 —— 何时开始、有无诱因 2. 症状性质 —— 部位、性质、程度 3. 伴随症状 —— 是否伴随其他不适 4. 加重缓解 —— 什么情况下加重或缓解 5. 持续频率 —— 持续多久、多频繁、是否反复发作 6. 既往家族史 —— 以前是否有类似、家族相关史 7. 用药过敏 —— 在服药物、过敏史 8. 生活方式 —— 睡眠、饮食、运动习惯、压力 硬性规则: - 本轮每个问题必须来自【不同】维度,严禁两条落在同一维度(例如不能两条都问"伴随症状")。\(excludeRule) - 只问【最新记录】里还没写明的事。方括号 `[xxx]` 表示该话题已被提出、只是细节待填,【不要】再作为新问题重复它。 - 不给诊断、不给用药建议、不写「建议就医」。 - q ≤ 20 字,像真人医生在问;fill 是采纳后追加到原文的中文补充句,可含方括号占位符如 [时间] [部位]。 - 至少 3 条,最多 4 条。 只输出严格 JSON,不要解释、不要 markdown 围栏、不要 标签。结构: {"questions":[{"dim":"<清单里的一个维度名>","q":"<问题>","fill":"<补充句模板>"}]} 示例 1(第一轮,记录:头痛了一上午): {"questions":[ {"dim":"起病诱因","q":"具体什么时候开始的?","fill":"症状从 [时间] 开始,"}, {"dim":"症状性质","q":"是哪种性质的头痛?","fill":"部位/性质是 [部位/胀痛/刺痛],"}, {"dim":"伴随症状","q":"还伴有其他不适吗?","fill":"还伴有 [症状],"}, {"dim":"生活方式","q":"最近睡眠和压力怎么样?","fill":"近期睡眠 [小时]、压力 [情况],"} ]} 示例 2(后续轮,已覆盖维度:起病诱因、症状性质、伴随症状): {"questions":[ {"dim":"加重缓解","q":"做什么会加重或缓解?","fill":"[活动/休息] 时会 [加重/缓解],"}, {"dim":"持续频率","q":"这种情况反复或持续多久了?","fill":"已持续/反复 [时长/频率],"}, {"dim":"既往家族史","q":"以前有过类似情况吗?","fill":"既往类似 [有/无,频率],"} ]} 现在输出 JSON。 已覆盖维度(必须避开):\(coveredLine) 【最新记录】: \(content) Output: /no_think """ } }