Prompt 调试日记——让 LLM 输出可信医疗建议有多难
一、工具调用稳定了,然后我以为大功告成
上篇博客结尾我写道:工具调用的参数完整性改善了,Output Parser 的格式解析成功率到了 92%,三类主要失败模式都有了对应的处置。
然后我做了一件事:把系统给了同学用,让他随便问几个用药问题,看看效果。
他问了这个:"我在吃阿司匹林,最近胃不太好,可以吃布洛芬吗?"
图谱返回了正确的结果——布洛芬和阿司匹林存在 DDI(叠加胃肠道损伤风险),布洛芬对胃溃疡患者是 CONTRAINDICATION(HIGH 级禁忌)。两条高危冲突。
但 LLM 给出的回复是这样的:
"您好!根据我的分析,阿司匹林和布洛芬同属非甾体抗炎药(NSAIDs),联用可能增加胃肠道副作用风险。鉴于您提到胃部不适,建议您在服用布洛芬前咨询医生或药师的意见。如果您的胃部症状持续,也建议及时就医。希望您早日康复!"
同学看完问我:"这是在建议我去问医生,还是在说可以吃?"
我没有办法回答他,因为这个回复两个意思都有——它既没有说"不能吃",也没有说"可以吃",它只是说"建议咨询医生"。对于两条 HIGH 级冲突,这个回复是完全不及格的。
这就是这篇博客的起点。 工具调用稳定只是解决了"系统能不能正确获取信息"的问题,"系统能不能正确表达结论"是完全独立的另一个问题。
二、在开始改 Prompt 之前,我先搞清楚问题在哪里
我把这个失败案例反复看了几遍,想弄清楚 LLM 的回复为什么会是这样。
图谱返回给 LLM 的信息是准确的:
知识图谱检索发现以下冲突,请严格按照风险等级作出决策:
冲突 1:【高风险· 必须阻断】
类型:药物相互作用
涉及:阿司匹林 ↔ 布洛芬
机制:两药均为 NSAIDs,联用显著增加胃肠道出血风险
建议:避免联用
冲突 2:【高风险· 必须阻断】
类型:用药禁忌
涉及:布洛芬 ↔ 胃溃疡
机制:NSAIDs 损伤胃黏膜保护屏障
建议:胃溃疡患者禁用
决策规则:存在任意【高风险·必须阻断】冲突时,最终结论必须为 blocked,
不得使用模糊或建议性措辞。
LLM 收到的是两条明确的 HIGH 级冲突,加上"必须为 blocked"的指令。但它输出的仍然是温和的建议措辞。
分析下来,问题出在三个地方:
问题一:决策规则是"告诉"LLM 应该做什么,但没有"告诉"LLM 不应该做什么。 "最终结论必须为 blocked"这条约束只说了必须输出 blocked,但没有明确禁止"同时输出温和建议"。LLM 的默认行为是友善的、建议性的,没有明确禁止它就会这么做。
问题二:LLM 有根深蒂固的"医疗免责"习惯。 训练数据里充斥着"建议咨询医生"这类措辞,对于医疗类问题,LLM 倾向于用这句话来规避风险——哪怕它已经有了明确的图谱证据,它仍然会加上这句话作为"保险"。这个习惯在训练时就固化了,光靠 Prompt 压制需要非常精确的措辞。
问题三:action_type: BLOCK 这个字段约束了结构,但没有约束语言风格。 Output Parser 保证了 JSON 格式正确,action_type 字段确实是 "BLOCK",但 conflict_rule 和 ui_directives.alert_title 这些自然语言字段里的措辞,仍然是 LLM 自由生成的。
弄清楚问题在哪里,才能有针对性地改。
三、第一版 System Prompt 和它的所有问题
在开始记录迭代过程之前,先把第一版 System Prompt 的核心部分展示出来(简化版,省略了工具调用规范那一块,上篇博客已经详细写过):
你是一个医疗用药安全助手,帮助医生和患者检测用药冲突。
## 工作流程
1. 理解用户描述,提取药物名称和患者状态
2. 调用 query_drug_graph 工具查询冲突
3. 根据工具返回结果,给出用药安全建议
## 输出要求
- 如果发现高危冲突,输出 action_type: BLOCK
- 如果需要更多信息,输出 action_type: CLARIFY
- 如果没有发现冲突,输出 action_type: PASS
- 所有回复必须严谨、专业
## 注意事项
- 请勿替代专业医疗建议
- 在信息不足时应建议用户咨询医生
现在看这个 Prompt,问题非常明显:
- "给出用药安全建议"——"建议"这个词给了 LLM 太多自由度
- "必须严谨、专业"——没有定义什么是严谨、专业的医疗场景输出
- "请勿替代专业医疗建议"——这条本来是好的,但它和"发现高危冲突必须阻断"产生了逻辑冲突:LLM 要同时"阻断"和"不替代医疗建议",就会产生"我阻断了,但我说去问医生"这种两边都兼顾的模糊输出
接下来记录每一轮迭代。
四、迭代记录
第一轮迭代:把"建议"改成"判断",并明确禁止模糊措辞
改了什么:
- 3. 根据工具返回结果,给出用药安全建议
+ 3. 根据工具返回结果,作出用药安全判断,并严格按照风险等级执行对应动作
+ ## 禁止措辞列表
+ 在存在【高危·必须阻断】冲突的情况下,以下措辞被明确禁止:
+ - "建议您咨询医生"
+ - "请在医生指导下使用"
+ - "如有疑虑请就医"
+ - 任何以"建议"、"可能"、"也许"开头的句子
效果: 有改善,但不稳定。对于同一个测试用例,有时候输出是干脆的阻断,有时候仍然出现"建议"措辞,但被包装成了"根据图谱数据,我们建议避免联用"。
分析: "禁止措辞列表"的方式是穷举,而 LLM 可以用无穷多种变体来表达同一个意思。穷举是防不住的。需要从正面约束"应该说什么",而不是从负面穷举"不该说什么"。
二轮迭代:加入"多冲突整合"指导原则
核心改动: 在模板里加入了多冲突场景的整合要求:
### 多冲突整合规范
当存在多条冲突时,conflict_rule 不得逐条罗列,
而必须整合为一段连贯的风险描述,说明:
1. 核心风险点是什么(最严重的那条冲突)
2. 多条冲突是否存在叠加效应
3. 在当前患者状态下,综合风险如何
示例(布洛芬 + 阿司匹林 + 胃部不适的场景):
"患者当前存在双重用药风险:布洛芬与阿司匹林联用本已显著增加胃肠道出血
风险;而患者本身的胃部症状提示可能存在消化道基础病变,进一步放大了这一
风险。在此情况下加用布洛芬属于高危决策,应当阻断。"
效果: 这次 conflict_rule 的质量跳了一个台阶。LLM 开始真正"整合"而不是"拼接",多条冲突之间的关联关系也能被正确描述。
但解决旧问题的同时,引出了一个更隐蔽的新问题。
新问题:LLM 在"整合"时开始发挥——会在图谱证据之外加入训练数据里的额外知识,说一些图谱没有返回的内容。
比如对于布洛芬 + 阿司匹林的案例,LLM 在整合描述里加了一句:"此外,布洛芬可能降低阿司匹林的心脏保护作用,对于有心血管风险的患者需特别注意。"
这句话在药理上是正确的——布洛芬确实可能竞争性抑制阿司匹林的血小板抑制作用。但这条信息不在我们的知识图谱里,是 LLM 从训练数据里"召唤"出来的。
这正是我们在架构决策时最想避免的情况:LLM 输出了图谱无法溯源的内容。在医疗场景里,这是个危险的行为——不是因为这句话是错的(它是对的),而是因为这类自发生成的内容没有经过知识图谱的审核,可能会引入错误信息而没有任何提示。
第三轮迭代:CLARIFY 场景——追问的措辞质量
CLARIFY 场景是另一类问题:当图谱返回 needs_clarification 状态码(关键患者信息缺失)时,Agent 需要输出追问。
追问的质量要求很高:既要让用户明白"为什么需要这个信息",又不能让用户觉得"系统在搪塞我",更不能让用户感受到压力(比如追问方式让患者觉得自己"病得很严重")。
第一版的追问效果:
测试用例:"我想吃华法林,可以吗?"(没有提供任何患者信息)
LLM 输出的追问:"为了提供准确的用药安全评估,请提供以下信息:1. 您目前是否正在服用其他药物?2. 您是否有肝肾功能问题?3. 您是否处于妊娠期或哺乳期?4. 您是否有出血性疾病史?5. 您目前是否正在服用抗生素?"
问题显而易见:一次性追问了五个问题。没有用户愿意回答五个问题。而且这几个问题对用户来说显得很突然,没有解释"为什么要问这些"。
改动: 在 CLARIFY 场景的输出规范里加了两条约束:
### CLARIFY 场景追问规范
1. 每次只追问一个最关键的缺失信息,不得一次性追问多个问题
优先级顺序:妊娠期/哺乳期 > 肝肾功能 > 当前其他用药 > 过敏史
2. 追问必须包含简短的"为什么问这个"的解释,让用户理解问题的必要性
格式:[简短原因说明],[具体追问]
追问示例(正确):
"华法林在妊娠期使用存在特殊风险,请问您目前是否处于妊娠期?"
追问示例(错误):
"请提供以下信息:1. 是否妊娠 2. 是否有肝病 3. ..."
效果: 追问质量明显改善,用户反馈"知道系统为什么在问这个",不再觉得被审问。
五、把迭代过程整理成最终版 System Prompt 结构
三轮迭代下来,System Prompt 的结构变成了这个样子:
## 角色定义
[你是谁,能做什么]
## 工作流程
[ReAct 循环,Tool Calling 规范——上篇博客的内容]
## 各场景输出规范
### BLOCK 场景
- alert_title 格式
- conflict_rule 要求(整合多冲突、证据边界)
- 禁止行为
- 输出示例
### PASS 场景
- 简洁输出要求
- 免责声明处理
### CLARIFY 场景
- 单一追问优先级
- 追问格式(原因 + 问题)
### FALLBACK 场景
- 触发条件
- 固定措辞模板
## 证据使用规范
[图谱边界,固定免责声明]
## 终止条件
六、一个关于"过度自信"和"过度保守"的对称性观察
做完这三轮迭代之后,我注意到一个规律,觉得值得单独说一下。
LLM 在医疗场景下有两种对称的失败模式:
过度自信(Overconfident): 超出图谱证据范围,自发引入额外药理知识,给出比图谱支持的更强的结论。"根据药理原理,这两种药联用还会影响XXX……"
过度保守(Overcautious): 即使图谱给出了明确的 HIGH 级冲突判断,仍然用"建议"、"可能"、"咨询医生"来软化输出,不敢给出清晰结论。
这两种失败模式的根因都指向同一件事:LLM 没有清晰的"我被授权说什么"的边界感。 过度自信是因为边界不清晰导致的越界,过度保守是因为边界不清晰导致的退缩。
在修 Prompt 的过程中,帮助最大的思维方式转变是:不是在告诉 LLM"怎么回答",而是在告诉 LLM"在这个系统里你扮演什么角色、你的权限边界在哪里"。
一旦从这个角度来写,很多规范就自然变得清晰了:
- 图谱给出的事实,你有权限描述并传达
- 图谱没有覆盖的药理知识,你没有权限自发引入
- HIGH 级冲突的阻断结论,你有权限(也有义务)明确输出
- 替代医生做出治疗决策,你没有权限这样做
更多推荐



所有评论(0)