我一直觉得,医疗场景是 Agent 最不该急着落地、但一旦落地价值最实的行业。原因不复杂:医生每天要处理的信息量早已超出人脑能高效消化的范围,而诊断推理链条又长又严谨,恰好是 LLM 这类系统相对擅长辅助的领域。但这里有一个前提——它只能做辅助,不能做替代。这篇内容,我基于实际参与过的医疗场景 Agent 诊断辅助系统架构设计,把核心思路、模块划分、落地过程中踩过的坑和排查方法完整拆一遍,适合正在做垂直行业 AI 落地的架构师、算法工程师,也适合医疗信息化方向的产品和技术负责人参考。
1. 医疗场景到底需要什么样的诊断辅助系统
1.1 先给系统划定边界:辅助工具不是自动驾驶
医疗场景最大的特点,我说直白一点:容错率极低,责任链条非常清晰,数据敏感度又高。这和电商推荐、内容生成完全不是一个量级的约束。所以做医疗 Agent,第一原则不是功能多强、覆盖面多广,而是边界是否清晰、输出是否可控、决策是否可追溯。
我们在最开始设计时也有过一段弯路。当时团队里有人提了一个很吸引人的想法:做一个输入症状、直接输出诊断结果的问答系统,听起来很酷,但很快就发现这条路走不通。原因其实不复杂——真实临床场景下,患者不会照着教科书描述症状,主诉经常是模糊的、混杂的、非典型的。假设一个患者说“最近总是头晕,站起来眼前发黑,血压好像有点高”,这个描述里既没有明确的持续时间,也没有既往病史,更没有检验指标,如果系统直接给出一个自以为是的“最可能诊断”,医生根本没法用,也不愿意信。
所以后来我们给这个系统定下了非常明确的身份:它不是一个能独立下诊断的“自动驾驶系统”,而是给医生提供结构化信息整理、鉴别诊断参考、证据链归纳的“辅助驾驶工具”。系统可以主动帮医生梳理病情线索、提出排查方向、给出检查建议,但最终诊断结论必须由医生确认,系统内不设“最终诊断”按钮。这个定位一开始可能让人觉得保守,但后来整个项目的落地推进,全靠这个边界守得稳。
1.2 诊断辅助的三个核心能力拆解
把边界划清楚之后,接下来要回答的是:这个系统到底要具备什么核心能力,才能让医生觉得有用,而不是又一个添乱的“AI玩具”?
我拆下来,核心能力集中在三块:
第一块是临床逻辑深度。医疗诊断不是一个简单的症状到疾病的映射关系。同样一个“胸痛”,可能是心肌梗死,也可能是肋间神经痛,还可能是反流性食管炎。系统需要理解的不只是症状本身,还要结合病程演变、既往史、用药史、检验指标动态变化,构建一个有时间轴的临床逻辑链。比如一个患者的肌钙蛋白在几个小时内持续升高,同时伴有典型胸痛和心电图改变,这个信息组合的权重远大于患者随口说的一句“胸口不舒服”。
第二块是证据链构建。医生在临床决策时,最反感的就是“黑盒给结论”。所以系统的每一个判断,都必须能追到依据——是哪条指南、哪个检验指标变化、哪段既往病史支撑了这个考虑方向。换句话说,系统给医生的不应该是一句“可能是冠心病”,而应该是“根据患者胸痛性质、肌钙蛋白动态升高、既往高血压病史,结合某版指南建议,优先排查急性冠脉综合征,建议完善心电图和心梗三项”。
第三块是多源信息整合。一份病历里面,有医生书写的非结构化文本,有检验检查的结构化数值,有影像报告的结论描述,还有历史住院记录的时序数据。这些来源的信息常常不在同一个系统里,医生需要自己来回切换、人工拼接。Agent 系统最有价值的地方之一,就是能把来自不同数据源的信息拉到同一个上下文里,按时间轴和临床维度重组,变成一个医生可以直接审阅的结构化视图。
打个比方大家就明白了。这套系统做的事情,有点像给医生配了一个能力很强的住院总助手——他提前把病人资料全部翻过一遍,整理出一个按时间线排好的摘要,把关键异常指标用红黄绿标出来,然后给出“可以考虑排查什么、为什么、下一步建议做什么”。这个助手不会直接拍着胸脯说“病人就是某某病”,但他能极大节省医生整理信息的时间,减少遗漏。
2. 系统架构的核心设计思路
2.1 总体分层:从数据接入到临床应用的解耦设计
整体架构上,我们分了五层,每一层职责单一,可以独立升级改造。这也是后期维护时痛苦最少的选择。
最底下是数据接入层。医疗场景的数据源非常分散,EMR(电子病历)、LIS(检验系统)、RIS(影像系统)、超声报告、病理报告,各有各的接口规范和数据库。这一层要做的事情就是把不同格式的数据统一成一套内部标准结构,比如把“肌钙蛋白I 0.05ng/mL”这种可能在不同系统里字段名完全不同的数据,全部规范化成统一指标名、统一单位、统一参考范围。别小看这一层的工程量,医疗数据标准化是整个项目里最琐碎但最关键的底座。
上面一层是知识层。包含医学知识图谱、临床指南库、药品说明书库、既往脱敏病历库。知识层的定位不是简单存文件,而是把这些知识结构化,让上层 Agent 可以按需精准取用。例如知识图谱中记录“胸痛”这个症状与几十种疾病之间的关联关系、每种关联的权重、对应的支持证据来源。指南库则按疾病领域拆分,每条指南片段带标签和版本号,方便后续溯源。
再往上是Agent编排层,这是整个系统的核心中枢。它接收来自医生工作站的结构化输入,把任务拆解成多个子任务,分发给不同的 Agent,统一管理上下文状态和任务流转,最后汇总各 Agent 的输出做一致性校验。这里类似一个项目总监的角色,不亲自写代码,但知道什么时候把任务派给谁,也知道怎么把各部分产出拼成完整的交付物。
上面两层靠近用户:应用层和展示层。应用层对接具体场景,比如门诊医生工作站插件、病房会诊辅助界面、病历质控后台。展示层解决“怎么让医生舒服地看”的问题,设计原则是:关键信息醒目,参考内容弱化,所有 AI 生成内容都可编辑可留痕。
2.2 为什么选择多 Agent 编排而不是单一大模型对话
这是架构设计里被问得最多的问题,也是我们最开始反复权衡的决策点。
最初我们确实做过一个原型:把全部能力塞进一个大模型的 system prompt 里,通过多轮会话完成从主诉收集到鉴别诊断到检查建议的全流程。当时觉得这样最简单,上下文不用切来切去,而且大模型本身具备很强的对话连贯性。
但实际跑起来之后问题暴露得很明显。第一,上下文窗口再大也是有限的,当患者信息很多时,最早的关键信息会被逐渐“挤丢”。第二,职责不分,所有的指令混在一个超级提示词里,互相干扰。例如让同一个模型既做严谨的事实抽取,又做发散性的鉴别诊断推理,还要兼顾病历写作风格,模型很难在一条回复里同时把三件事都做到位。第三是维护成本高,临床反馈经常是“主诉抽取还好,但鉴别诊断那块建议质量下降了”,如果是单一大模型,我们根本没法只优化某一个特定环节,因为参数是全局共享的。
多 Agent 架构天然解决了这些问题。我们把临床任务拆成几个明确分工的角色:
- 主诉解析 Agent:负责把患者零散的语言描述转成结构化病史元素。
- 鉴别诊断推理 Agent:基于结构化病史和多源指标,生成候选诊断列表并给出鉴别分析。
- 检查建议 Agent:根据候选诊断和临床指南,推荐下一步排查手段。
- 病历文书 Agent:把会话过程自动组织成符合规范的门诊病历或出院小结草稿。
- 风险预警 Agent:负责识别危险信号,触发转人工或紧急提示。
每个 Agent 有独立的提示模板、独立的工具集、独立的评价数据。这让系统可以像一支各有专长的医疗团队一样协作。某个环节出了问题,我们只需要针对那个 Agent 单独调整和测评,不会牵一发动全身。实测下来,多 Agent 方案在信息完整度、单模块优化空间和故障隔离范围上,都全面优于单一大模型。
编排层还有一个职责我想单独强调:上下文管理。各 Agent 之间不是简单的互相独立,它们共享一个统一的“案例上下文容器”,里面包含患者的结构化信息摘要、时间轴、当前已采集的证据列表、已生成的部分报告。每个 Agent 只读取与自身任务相关的字段,避免了职责交叉,同时又能保证所有 Agent 基于同一份患者信息推理,不会各说各话。
3. 关键模块拆解与实操要点
3.1 患者主诉解析 Agent:从自然语言到结构化病史
这是整个系统最前置也最容易翻车的环节。为什么这么说?因为后面所有推理的质量,都取决于这一层结构化的信息是否完整、准确。就像医生问诊,问得越清楚,诊断越有把握;系统解析得越准,鉴别诊断 Agent 的可信度才越高。
真实场景中的患者描述是什么样的呢?举个例子:“大夫,我最近总觉得心慌,有时候一阵阵的,干活儿一累就明显,晚上睡不着觉,之前查过心电图说有点问题,但是我那会儿没当回事。”这段描述里,信息是碎片化的,夹杂了诱因、情绪状态、既往模糊的检查结果,还有患者的主观态度。主诉解析 Agent 要做的,是从这段话里抽取以下结构化元素:
- 主诉:心悸(待明确性质、持续时间)
- 病程:近期
- 诱发因素:劳累时加重
- 伴随症状:眠差(待确认与心悸是否相关)
- 既往相关检查:心电图异常史(时间不详)
- 待采集信息:心悸发作时的性质、有无胸痛、有无晕厥、家族史、近期用药
这背后我们走的是“规则抽取优先、模型理解兜底”的混合策略。先跑一套基于医学词典和正则表达式的实体识别,把化验指标、症状词、药物名、时间单位抓出来;然后在此基础上用 LLM 做语义级的要素补全和逻辑组织。如果把所有解析任务全交给 LLM 裸跑,很容易出现输出结构不稳定或漏字段的问题。
这里有个实操细节供参考:Agent 的输出必须是有固定 Schema 的 JSON,而不是自由文本。每个字段附带结构化记录的置信度和来源片段,例如“心悸:来源原文‘总觉得心慌’,置信度 0.95”。这样即使用户看到输出有疑问,也能直接追溯到原始描述,而不是对着一个黑盒结构干瞪眼。
注意:最忌讳的就是让主诉解析 Agent 自行脑补患者没提过的信息。假设患者没说胸痛,系统绝对不能为了“让逻辑更完整”而加上“无胸痛”这个阴性症状,因为患者可能是没说,也可能是问诊阶段还没问到。Agent 只能对显式信息做结构化,对未提及信息标记为“待确认”。
3.2 鉴别诊断推理 Agent:如何生成可解释的候选排序
鉴别诊断是整个系统的核心模块,也是最难做好的模块。我先把我们最终落地的三段式思路讲清楚。
第一跳,候选召回。系统拿到结构化病史后,先通过医学知识图谱做疾病召回。比如患者有“心悸”“劳累诱发”“心电图异常史”,图谱就会沿着症状节点关联出心律失常、冠心病、甲状腺功能亢进、焦虑障碍、贫血等候选疾病。这一步的核心目标是“不遗漏”,宁可多召回一些概率很低的病,也不能漏掉高风险的病。我们比较关注 Top20 召回率,要求常见病基本都能覆盖到,这是后面排序的前提。
第二跳,规则与统计排序。这一步用可解释的权重规则,对候选疾病做初排序。排序因子包括:患者年龄性别的基础流行病学概率、症状匹配度、危险信号权重、既往病史关联度。为什么不用 LLM 直接排序?因为 LLM 排序的结果难以解释,而且很容易被训练语料里的“常见病偏差”所影响。用显式规则做排序,每一个权重调整都有迹可循,也方便临床医生理解和参与调整。
第三跳,LLM 生成鉴别分析。排序完成后,LLM 拿到 Top N 候选疾病和对应的证据列表,用自然语言生成鉴别分析文本。这段文本不是凭空写的,而是严格围绕给定的证据列表来组织。例如:“患者中年男性,劳累后心悸,心电图提示异常,结合高血压病史,首先考虑心律失常可能。冠心病需排除,建议完善动态心电图和心脏超声。甲亢可引起心悸,建议检测甲状腺功能。”
三段式最大的好处是:每一跳都负责一个明确且可控的任务,模型只负责最终的语言组织和表达,而关键的事实判断工作由图谱和规则来完成。这样既保证了可解释性,也极大地降低了模型幻觉对最终结果的影响。
在这个模块里还要特别提一个设计——危险信号分级。我们要求鉴别诊断 Agent 输出候选列表时,每个诊断必须配一个信号等级:
| 等级 | 含义 | 系统行为 |
|---|---|---|
| 红色 | 需立即排除的高危诊断(如急性心梗、主动脉夹层) | 显著标注,建议医生优先关注 |
| 黄色 | 常见或需重点排查的诊断 | 常规显示,进入鉴别分析 |
| 绿色 | 低概率但不典型的可能 | 折叠展示,防止误伤注意力 |
这个分级机制既防止了系统漏掉高危信号,也避免了所有可能性平铺在界面上、医生什么都看不清的问题。
3.3 医学知识检索设计:RAG 不是万能的
现在大家做垂直领域应用,基本言必称 RAG。但我可以负责任地说,医疗场景直接拿通用 RAG 方案,效果大概率会让人失望。
我们最开始尝试过把指南 PDF 直接切片做向量化,再用相似度检索召回。测试下来有三个特别典型的问题。第一,PDF 解析质量极差,指南里大量内容在表格里,切片后表格结构全丢,检索命中的文本往往不完整。第二,语义相似度检索在医学语境下很容易召回“语义像但内容不对”的片段。比如查询“胸痛伴随呼吸困难”,检索结果可能返回“胸痛患者的呼吸困难评估”这类相关描述,但也可能返回“心源性呼吸困难鉴别”这种关联太泛的内容。第三,检索返回的文本片段零散,Agent 很难从中组织出结构化的诊断逻辑,结果质量自然不稳定。
后来我们换成了**“先图谱定位、再文本取证”两阶段检索方案**。第一阶段,系统根据结构化症状和指标,在知识图谱中定位到对应的疾病节点和相关关系。例如症状“心悸”节点关联到“心律失常”“甲亢”“贫血”等疾病节点,同时连接着“动态心电图”“甲状腺功能检查”等诊疗节点。第二阶段,针对图谱定位出的关键节点,去指南库中精准提取对应的原文片段作为证据附件,这时提取的文本就不是泛泛相似了,而是有明确目的、按图索骥式的取证。
这个方案的直接效果是:检索相关性显著提升,而且每一段检索文本都有对应的图谱路径,方便最终生成时做引用溯源。如果你也在做医疗类的 Agent,我强烈建议把知识图谱前置,而不是一上来就做纯向量库。
实操心得:医疗知识图谱的构建初期不需要追求大而全。先把一个科室、一种疾病领域的核心关系建模清楚,比做一张“全科图谱”但每个节点都缺斤短两要实用得多。我们是从心血管领域起步的,关系只覆盖症状、疾病、检验、药物、检查五类节点和十几条关系边,但每一条关系都经过临床顾问逐条审核,可信度非常高。
3.4 病历文书生成与辅助记录
医生日常最耗时的工作,往往不是诊断推理本身,而是写病历。一份规范的门诊病历,要写清楚主诉、现病史、既往史、体格检查、辅助检查、初步诊断和处理意见,还要符合医疗机构内部的文书规范。这也是 Agent 最能直接产生效率价值的地方。
病历文书 Agent 的逻辑是:在整段诊疗会话过程中持续记录,将主诉解析 Agent 的结构化结果、鉴别诊断 Agent 的分析结论、医生手动录入的补充信息一并汇总,按院内病历模板自动生成草稿。它的输出不是“文本框填空”,而是按章节结构生成的完整文本,医生在界面里直接审阅、修改、确认。
这里有一个很重要的设计约束:所有检查结果和数值指标的引用,必须原文摘录,不允许 LLM 转述。实践中我们发现,如果让模型用自己的话描述检验数值,很容易在生产报告中引入细微偏差。比如患者肌钙蛋白数值“0.05ng/mL”,模型可能会在生成时表述为“轻度升高”,但如果这个数值其实处在临界区间,“轻度”这个形容词就可能误导。因此我们做了硬性约束:指标值必须是结构化数据源的原文,模型能写的只是描述性语境,不能改动数值本身。
另一个约束是模板字段的可追溯性。病历文书 Agent 在生成每个段落时,都会附带内容来源标记。比如“现病史”段落引用的是主诉解析 Agent 的结构化字段,“初步诊断”段落引用的是鉴别诊断 Agent 的候选列表和医生的确认结果。这样做的好处是,一旦出现病历质量争议,可以快速定位每一个字段是从哪一步来的,而不是面对一个大模型生成的文本无从追查。
这块上线后收到的反馈相当正面。医生普遍反映,整理信息的时间明显减少,以前一份门诊病历要写几分钟,现在主要是审改 AI 草稿,几十秒就能完成。
4. 落地过程中的典型问题与排查实录
4.1 幻觉问题:多策略约束生成
幻觉在医疗场景不是“效果不好”的问题,而是“可能误导诊疗方向”的问题。我们在真实测试中的一次失误值得拿出来复盘。
当时在脱敏演示环境里,系统接诊了一个“心悸伴晕厥”的案例。鉴别诊断 Agent 生成的文本里,把“低钾血症”列入了重点排查建议,理由是“低钾血症可导致心律失常甚至晕厥”。从医学逻辑上讲,这句话本身没有错,低钾血症确实是心悸和晕厥的诱因之一。但问题在于——这位患者的血钾是正常值 4.2mmol/L,系统因为知识图谱里“晕厥-低钾”这条关系被触碰到了,生成了这个排查建议,却没有严格对照当前患者的结构化化验数据。这是一个典型的“知识关系正确但个体不适用”的幻觉案例。
这次事件之后,我们建立了一套多策略约束机制:
第一,强制证据绑定。鉴别诊断 Agent 生成的每一个候选疾病,必须在知识图谱和当前患者的化验指标之间有明确的关联路径,并且关联所使用的证据必须来自患者数据,不允许来自模型记忆。如果一个诊断建议找不到患者数据支撑,就会被自动剔除。
第二,结构化数值闭环。患者的所有检验指标,在推理链路里不是作为一段文本上下文存在的,而是作为结构化数据对象,Agent 只能通过工具调用去查询“当前患者血钾是多少”,查询返回的结果才是它可用的证据。这从机制上切断了模型凭记忆“编造”检验值的路径。
第三,事实类输出锁定。对主诉、现病史、诊断、检查建议这类事实性极强的输出,我们把模型温度调到极低,同时限制模型只能使用给定工具结果,不能自由发挥。经验是:医疗场景事实类任务,宁可让模型说“信息不足”而拒绝作答,也比给它一个看似合理实则存疑的回答更安全。
4.2 置信度与拒答机制:不硬答同样是一种能力
医疗 Agent 最危险的其实不是答错,而是“不知道自己不知道”还硬答。所以我们在系统架构里单独设计了置信度评估和拒答机制。
每个 Agent 在输出关键结论时,都需要附带一个内部一致性评分。评分逻辑并不是模型给自己打一个“感觉分数”,而是基于实际证据覆盖度计算:患者的症状元素被候选诊断解释了多少、医生的关键未回答信息是否影响当前判断、被触发的鉴别关系是否有足够的化验指标支持。当这些证据覆盖度低于某个阈值时,系统不会强行生成诊断建议,而是转入追问流程或转人工。
我做了一张规则表,可以比较直观地表达这个机制:
| 触发条件 | 系统行为 |
|---|---|
| 证据覆盖充分,候选诊断清晰 | 输出建议并附证据链 |
| 关键信息缺失(如缺少持续时间、既往史) | 触发追问,补齐信息后再推理 |
| 存在红色危险信号且信息不足 | 无 |