import Foundation /// 「导出身体档案」用到的两个 LLM prompt: /// 1. `intentExtraction` —— 抽取时间窗 + 指标/症状关键词,只输出 JSON /// 2. `reportGeneration` —— 拼真实数据后生成给医生看的 Markdown /// /// 解析逻辑见 `HealthExportService`(§3.2 失败回退红线: /// 抽不出 JSON → 用 30 天 + 空关键词兜底,流程不中断)。 enum HealthExportPrompts { // MARK: - 意图抽取 /// `intentExtraction(userPrompt:)` 把用户原话拼到模板末尾。 /// 期望输出形如: /// ```json /// {"time_range_days":30, /// "keywords":["体温","血压"], /// "symptom_keywords":["感冒","咳嗽"], /// "intent":"cold_consult", /// "intent_label_cn":"感冒就诊"} /// ``` static func intentExtraction(userPrompt: String) -> String { """ 你是健康数据助手。读用户的请求,只输出严格 JSON,不要解释、不要 markdown 围栏、不要任何前后缀文字。 字段说明(全部必填): { "time_range_days": int, // 回溯天数,默认 30,最大 365 "keywords": [string], // 指标关键词(中文,如「血压」「血糖」「体温」「肝功」),无则 [] "symptom_keywords": [string], // 症状关键词,无则 [] "intent": string, // 英文 snake_case 标签,如 "cold_consult" "intent_label_cn": string // 中文短语,会作为报告标题副题,如 "感冒就诊" } 规则: - 时间未指定 → 30 - 「最近一个月」→ 30,「最近三个月」→ 90,「最近半年」→ 180 - 关键词要中文,常见健康指标 / 症状词 - intent 简短,4-25 字符,小写下划线 示例 1: User: 我感冒3天了,要把最近一个月的健康情况给医生看 Output: {"time_range_days":30,"keywords":["体温","血压","脉搏"],"symptom_keywords":["感冒","咳嗽","咽喉痛","发烧"],"intent":"cold_consult","intent_label_cn":"感冒就诊"} 示例 2: User: 我最近血糖好像不稳,把上次体检前后的化验单整理一下 Output: {"time_range_days":90,"keywords":["血糖","糖化血红蛋白","胰岛素"],"symptom_keywords":[],"intent":"glucose_review","intent_label_cn":"血糖复查"} 现在请输出 JSON: User: \(userPrompt) Output: /no_think """ } // MARK: - 报告生成 /// `reportGeneration(userPrompt:intentLabelCN:dataJSON:)` 拼好后流式生成 Markdown。 static func reportGeneration(userPrompt: String, intentLabelCN: String, dataJSON: String) -> String { let labelLine = intentLabelCN.isEmpty ? "# 就诊摘要" : "# 就诊摘要 — \(intentLabelCN)" return """ 你正在帮患者撰写一份给社区医生看的就诊摘要。要求: - 严格输出 Markdown,标题用 # / ##,不要 markdown 围栏 - 只用「数据」中给出的信息,数据缺失就写「无记录」 - 不要给诊断意见、用药建议或「建议就医」之类的话 - 引用数值时保留单位 + 参考范围,异常项前加 ⚠️ - 全文中文,简洁,医生 30 秒内能扫完 - 不要复述「数据」二字,不要输出 JSON 结构(严格按以下 6 段): \(labelLine) ## 主诉 ## 患者背景 ## 近期症状(按时间倒序) ## 关键指标(异常项优先) ## 在服药与过敏 ## 患者疑问 数据: \(dataJSON) 患者原话:\(userPrompt) 现在请生成 Markdown(直接输出,不要思考过程,不要 标签): /no_think """ } }