AI+医疗进阶:多智能体系统怎么协作做诊断、总结与质控?
很多团队第一次做 AI+医疗多智能体,思路都差不多:
-
一个 Agent 读影像
-
一个 Agent 写报告
-
一个 Agent 做质控
-
最后再来一个 Agent 汇总
看起来很完整,但真实系统很快会暴露三个问题:
-
Agent 变多了,错误不一定变少,只是更难定位了
-
诊断、总结、质控之间如果没有共享中间结构,后面的 Agent 只能复述前面的幻觉
-
医疗场景需要的是可审计链路,不是"几个提示词接起来就能跑"
所以这篇文章不讲空泛的"多智能体很有前景",而是从工程实现角度拆开:
-
哪些医疗任务真的适合多智能体
-
系统应该怎么拆角色,而不是怎么凑角色
-
关键公式怎么定义协作收益、路由代价与质控一致性
-
怎样把影像分析、报告生成和质控做成一个可复现的 pipeline
-
落地时最容易踩的坑是什么
如果你正在做影像辅助诊断、病历总结、病理报告结构化或者院内质控流,这套思路比"直接上一个大模型"更接近真实可用系统。
一、为什么医疗 AI 会需要多智能体,而不是单个大模型?
先把问题说清楚。
医疗任务通常不是单步映射,而是一个多阶段决策链:
-
输入可能来自多源:DICOM 影像、检查申请单、历史病历、化验指标、既往报告
-
输出也不止一种:分类结果、分割掩码、病灶摘要、结构化 findings、最终 impression、风险提示、质控结论
-
每一步的容错率不一样:病灶漏检、术语误写、模板错配、结论越界,风险完全不同
如果把这些都压到一个模型里,短期确实省事,但会出现几个典型问题:
1)上下文过载
模型要同时看影像特征、文本上下文、医院模板、质控规则,提示词会越来越长,最后谁都没学好。
2)错误不可定位
一旦最终输出错了,你很难判断:
-
是视觉识别错了
-
是摘要阶段漏了证据
-
还是最终结论生成时写过头了
3)系统无法审计
医院更关心的是:
-
结论基于什么证据得出
-
哪一步做了规则拦截
-
谁触发了人工复核
单体模型往往只能给你一个"结果",很难给你一条可核查的责任链。
所以多智能体的价值,不是把单模型替换成多个模型,而是把一个高风险任务拆成:
-
可约束的子任务
-
可审计的中间结果
-
可插入质控的关键节点
这才是医疗系统需要的协作方式。
二、哪些医疗任务适合多智能体?
不是所有任务都适合。
如果任务本身很单纯,比如单病种二分类、一个标准公开集上的分割 benchmark,多智能体通常是过度设计。
更适合多智能体的是下面三类。
1)多模态诊断链路
例如胸片报告生成。
输入包括:
-
X-ray 图像
-
患者基本信息
-
检查目的
-
历史报告
输出包括:
-
异常发现列表
-
器官级描述
-
impression
-
质控标记
这里天然可以拆分成视觉、证据汇总、文本生成、术语规范化、质控几个角色。
2)长流程临床总结
例如住院病程总结、出院小结、肿瘤 MDT 讨论摘要。
这类任务的难点不是生成一句话,而是:
-
从长上下文里抽取关键事实
-
做时间线归纳
-
去掉互相矛盾的信息
-
保证结论不越界
单 Agent 可以做,但稳定性一般。多 Agent 更适合把"抽取""对齐""总结""审校"分开。
3)强规则约束的质控系统
例如影像报告质控。
质控往往不是一个生成任务,而是多个规则和模型共同参与:
-
左右侧一致性
-
模板字段完整性
-
结论与 findings 是否矛盾
-
是否出现高风险术语但缺少证据
这种场景非常适合让一个规则 Agent 和一个语义审校 Agent 一起工作。
三、一个实用的医疗多智能体架构应该怎么拆?
我更推荐下面这个 5 角色架构,而不是"想到什么就加一个 Agent"。
1. Orchestrator:编排 Agent
职责:
-
接收原始输入
-
根据任务类型决定走哪条子链路
-
记录每一步调用日志
-
决定何时触发人工复核
它不是"最聪明"的 Agent,而是最重要的系统控制点。
如果没有它,多智能体系统很容易退化成一堆互相调用的 prompt。
2. Perception Agent:感知 Agent
职责:
-
影像编码与病灶候选检测
-
OCR / 表格读取 / 文档版面理解
-
从原始输入中提取结构化证据
在影像任务里,这一层往往不是 LLM,而是视觉模型:
-
2D/3D CNN
-
ViT / Swin Transformer
-
DETR 系列检测器
-
U-Net 系列分割器
-
医疗多模态 encoder
输出不是自然语言,而应该是结构化证据:
json
{
"lesions": [
{"type": "nodule", "location": "right upper lobe", "score": 0.91},
{"type": "effusion", "location": "left pleura", "score": 0.63}
],
"quality": {"motion_artifact": 0.12, "coverage_ok": true}
}
3. Evidence Agent:证据整理 Agent
职责:
-
合并多来源证据
-
去重、冲突消解、时间对齐
-
生成后续报告用的 evidence table
这一层很关键,因为它决定后面的生成是否有"事实底座"。
如果省掉这层,Report Agent 通常会直接拿原始输入拼文本,幻觉概率会明显升高。
4. Report Agent:报告生成 Agent
职责:
-
根据 evidence table 写 findings
-
生成 impression
-
做术语标准化与模板适配
注意:这层不应该自行"脑补"证据。
比较合理的 prompt 约束是:
-
只允许使用 evidence table 中出现的信息
-
缺少证据时输出 uncertain / recommend review
-
findings 和 impression 分开生成,不能一步到位
5. QA Agent:质控 Agent
职责:
-
检查 findings 与 impression 是否一致
-
检查左右侧、数量、部位、时序是否冲突
-
检查高风险结论是否有足够证据支撑
-
输出 pass / reject / manual_review
真正上线时,QA Agent 通常不是一个模型,而是:
-
规则引擎
-
小模型分类器
-
LLM 语义审查器
三者混合。
四、怎么形式化定义"多智能体协作收益"?
如果只是说"多智能体更稳",这件事很难评估。
比较工程化的做法,是把系统目标写成一个联合优化问题。
设整个医疗任务输入为 xxx,最终输出为 yyy,由 NNN 个 Agent 串并联协作完成。
第 iii 个 Agent 的输出记为:
z_i = A_i(x, z_{\
其中:
-
AiA_iAi:第 iii 个 Agent
-
ziz_izi:第 iii 个 Agent 的中间输出
-
z<iz_{<i}z<i:之前所有 Agent 的中间结果
系统最终目标不是只最大化准确率,而是同时优化:
\\max ; \\mathcal{J} = \\lambda_1 \\cdot U_{task} - \\lambda_2 \\cdot C_{sys} - \\lambda_3 \\cdot R_{unsafe}
其中:
-
UtaskU_{task}Utask:任务效用,比如诊断准确率、报告质量、质控通过率
-
CsysC_{sys}Csys:系统代价,比如推理延迟、调用成本、人工复核成本
-
RunsafeR_{unsafe}Runsafe:不安全风险,比如漏报、错报、越界结论、未触发复核
-
λ1,λ2,λ3\lambda_1, \lambda_2, \lambda_3λ1,λ2,λ3:不同目标的权重
这个公式有一个很实际的意义:
医疗多智能体的最优点,通常不是"Agent 越多越好",而是在收益和代价之间找到平衡。
例如:
-
增加一个 QA Agent 可能让报告错误率下降
-
但也可能让平均延迟从 3 秒涨到 8 秒
-
如果它只减少了极少量低风险错误,那这个 Agent 可能不值得加
所以是否拆 Agent,应该由目标函数决定,而不是由"系统看起来更高级"决定。
五、公式怎么落到实验指标上?
上面的联合目标必须映射到可测指标,不然只能停留在 PPT。
1)任务效用 UtaskU_{task}Utask
对于不同任务,可以拆成不同指标。
影像诊断类
U_{task}\^{diag} = \\alpha_1 \\cdot \\text{AUC} + \\alpha_2 \\cdot \\text{F1} + \\alpha_3 \\cdot \\text{Sensitivity}
其中:
-
AUC 衡量整体区分能力
-
F1 衡量精确率和召回率平衡
-
Sensitivity 在漏诊成本高的医疗任务里通常权重更高
报告生成类
U_{task}\^{report} = \\beta_1 \\cdot \\text{FactCC} + \\beta_2 \\cdot \\text{RadGraphF1} + \\beta_3 \\cdot \\text{ClinicallyCorrect}
其中:
-
FactCC:事实一致性
-
RadGraphF1:医学实体与关系抽取一致性
-
ClinicallyCorrect:临床正确率,通常需要医生或规则辅助评估
2)系统代价 CsysC_{sys}Csys
C_{sys} = \\gamma_1 \\cdot T_{latency} + \\gamma_2 \\cdot C_{api} + \\gamma_3 \\cdot C_{review}
其中:
-
TlatencyT_{latency}Tlatency:端到端延迟
-
CapiC_{api}Capi:模型调用成本
-
CreviewC_{review}Creview:人工复核成本
3)不安全风险 RunsafeR_{unsafe}Runsafe
可以定义为:
R_{unsafe} = \\eta_1 \\cdot P_{miss} + \\eta_2 \\cdot P_{hallucination} + \\eta_3 \\cdot P_{inconsistency}
其中:
-
PmissP_{miss}Pmiss:漏检/漏报概率
-
PhallucinationP_{hallucination}Phallucination:幻觉率
-
PinconsistencyP_{inconsistency}Pinconsistency:findings 与 impression 或多步骤之间不一致的概率
这时你就能明确解释实验结果了。
比如:
-
如果加入 Evidence Agent 后,RadGraphF1 上升,说明证据结构化确实改善了实体关系表达
-
如果加入 QA Agent 后,PinconsistencyP_{inconsistency}Pinconsistency 显著下降,说明它对报告一致性有效
-
如果再加一个额外 Summary Agent,指标没有提升但延迟变高,那它在当前系统里就是冗余的
这比只说"我们方法效果更好"要扎实得多。
六、训练和实现时,最关键的不是 Agent 提示词,而是中间表示
这是多智能体医疗系统最容易被忽略的一点。
很多失败案例都不是因为 LLM 不够强,而是因为 Agent 之间传递的是自由文本。
一旦中间结果是自由文本,就会出现:
-
字段缺失
-
术语不统一
-
时间关系模糊
-
下游 Agent 解析失败
-
QA Agent 无法对齐前面输出
更稳的做法是:
Agent 之间尽量传结构化状态,而不是传散文。
例如定义统一状态对象:
json
{
"study_id": "cxr_000123",
"patient_context": {
"age": 64,
"sex": "M",
"history": ["smoking", "copd"]
},
"visual_evidence": [
{"finding": "nodule", "location": "RUL", "confidence": 0.91},
{"finding": "pleural_effusion", "location": "left", "confidence": 0.63}
],
"text_evidence": [
{"source": "prior_report", "content": "stable right upper lobe nodule"}
],
"draft_report": {
"findings": "...",
"impression": "..."
},
"qa_flags": []
}
这会直接影响系统鲁棒性。
如果你把多智能体系统理解成"多个 prompt 连在一起",最后大概率还是会被 prompt 漂移打回原形。
七、一个可复现的落地方案:以胸片报告生成 + 质控为例
下面给一个更接近实战的 pipeline。
数据集选择
如果你想复现一个公开可做的版本,可以用:
-
MIMIC-CXR:大规模胸片与配套报告
-
CheXpert:多标签胸片分类
-
OpenI:规模较小,但适合原型验证
-
RadGraph:用于医学报告实体关系标注评测
推荐任务拆分
Stage 1:Perception Agent
输入:胸片图像
输出:病灶候选标签与定位证据
可选模型:
-
DenseNet121 / EfficientNet:做多标签分类 baseline
-
Swin Transformer:做更强图像编码
-
Grounding/DINO 类检测器:如果需要局部证据
训练建议:
-
图像 resize 到 320 或 384
-
多标签 BCE loss
-
类别不平衡时用 positive class weighting
-
patient-level split,不能 image-level split
多标签损失可以写成:
\\mathcal{L}*{cls} = - \\sum*{c=1}\^{C} \\left\[ y_c \\log p_c + (1-y_c) \\log(1-p_c) \\right\]
其中:
-
CCC:病灶类别数
-
yc∈{0,1}y_c \in \{0,1\}yc∈{0,1}:第 ccc 类真实标签
-
pcp_cpc:模型预测概率
如果类别极不平衡,可以加权为:
\\mathcal{L}*{wcls} = - \\sum*{c=1}\^{C} w_c \\left\[ y_c \\log p_c + (1-y_c) \\log(1-p_c) \\right\]
其中 wcw_cwc 用于提升少数类权重。
Stage 2:Evidence Agent
输入:
-
图像预测结果
-
历史报告摘要
-
检查申请信息
输出:标准化 evidence table
这一步不一定要训练模型,也可以先用:
-
规则模板
-
术语词典映射
-
小模型做冲突消解
例如把 "right upper lobe nodule" 和 "RUL pulmonary nodule" 统一映射到同一个 ontology code。
Stage 3:Report Agent
输入:evidence table
输出:findings 和 impression
实现建议:
-
findings 与 impression 分开生成
-
生成时强制引用 evidence id
-
不允许输出 evidence 中不存在的新病灶
可以把报告生成目标写成条件概率:
P(r \\mid E) = \\prod_{t=1}\^{T} P(r_t \\mid r_{\ 其中: EEE:evidence table rtr_trt:第 ttt 个 token TTT:报告长度 但实际系统不要只看语言模型似然,更要加事实约束。 一种常见做法是在训练或重排序时加入一致性奖励:
\\mathcal{L}*{report} = \\mathcal{L}*{NLG} + \\lambda \\mathcal{L}_{fact}
其中: LNLG\mathcal{L}_{NLG}LNLG:标准生成损失 Lfact\mathcal{L}_{fact}Lfact:事实不一致惩罚 λ\lambdaλ:事实约束权重 如果实验里发现 BLEU 提高但 RadGraphF1 没提高,通常说明模型只是"更会说话",不是"更忠于证据"。 检查项建议至少包括: 左右侧一致性 findings 与 impression 一致性 高风险术语是否有证据支持 是否遗漏主病灶 是否输出超出适应范围的结论 可以定义一个质控风险分数:
S_{qa} = \\sum_{k=1}\^{K} a_k \\cdot f_k
其中: KKK:质控规则数 fkf_kfk:第 kkk 个规则触发值,取 0/1 或连续分数 aka_kak:对应规则权重 最终决策为:
\\text{decision} =
\\begin{cases}
\\text{pass}, \& S_{qa} \< \\tau_1 \\
\\text{manual review}, \& \\tau_1 \\le S_{qa} \< \\tau_2 \\
\\text{reject}, \& S_{qa} \\ge \\tau_2
\\end{cases}
这个公式很适合上线系统,因为它天然支持可解释审计: 为什么被拦截 哪条规则触发 风险分数是多少 都能直接记录。 下面给一个更偏工程实现的伪代码结构。 实现时我建议再补三层基础设施: 日志层:记录每个 Agent 的输入摘要、输出摘要、耗时、版本号 缓存层:Perception Agent 的视觉特征尽量缓存,别每次重新编码 审计层:把 evidence id、规则命中、人工复核结果全部落库 医疗系统里,基础设施往往比"再加一个 fancy Agent"更值钱。 多智能体系统最容易犯的错误,是只看最终文本质量。 这会把很多真正重要的问题藏起来。 更合理的评估应该分层做。 Perception Agent: AUC F1 Sensitivity / Specificity mAP(如果是检测) Dice / HD95(如果是分割) Evidence Agent: 实体抽取 F1 术语标准化准确率 冲突消解准确率 Report Agent: BLEU / ROUGE 只做参考 FactCC / RadGraphF1 更关键 医生打分或临床一致性评估更关键 QA Agent: 风险样本召回率 错误拦截率 误拦截率 人工复核工作量变化 真正要看的是端到端: 最终报告临床可用率 高风险错误率 平均延迟 单例成本 人工复核率 至少要做下面三组: 去掉 Evidence Agent 去掉 QA Agent 把多 Agent 改成单 Agent 直接生成 这样你才能知道: 哪个 Agent 真有贡献 哪个 Agent 只是增加复杂度 如果没有消融,很多"多智能体提升"其实只是换了更大的底座模型。 不是 Agent 越多越高级,越多只意味着链路更长、延迟更高、排错更难。 如果中间结果全部是自然语言,系统迟早会在规模化后崩掉。 医疗数据如果没按患者级划分,实验结果通常会虚高。 医疗报告生成最怕"语言流畅但事实错误"。 上线后如果没有人工复核回写机制,QA Agent 永远学不到真实错误分布。 更稳的做法是在输入层、证据层、报告层都做局部质控,而不是最后统一拦截。 这个问题也得说。 如果你当前项目满足下面任意一种情况,我建议先别上: 标注数据还很乱,标签体系没统一 单模型 baseline 还没跑稳 你还不知道系统真正的错误来自哪一层 没有日志、缓存、版本管理这些基础设施 这时候强上多智能体,大概率只是把问题从一个模型扩散到四个 Agent。 先把 baseline 跑明白,再决定哪里需要拆,是更省时间的路线。 如果你是从 0 到 1 做系统,我建议按下面顺序推进: 先验证: 数据是否可用 指标能否达到最低要求 错误主要来自哪里 目标: 让生成建立在结构化证据上 降低幻觉和术语漂移 目标: 把高风险错误挡在系统外面 建立人工复核入口 比如: 多专科协作 历史纵向病程建模 多轮自检与重写 这个顺序更像工程系统的自然演化,而不是论文 demo 的一步到位。 医疗多智能体系统最核心的价值,不是"多个模型一起说话",而是三件事: 把复杂任务拆成可约束的子任务 把中间过程变成可审计状态 把高风险输出拦截在最终落地之前 从这个角度看,多智能体不是一个花哨架构,而是一种风险管理工具。 如果你现在正做 AI+医疗落地,我的建议是: 先别急着堆 Agent 先定义清楚状态对象和评估指标 让每个 Agent 只负责一个清晰子目标 把公式直接映射到实验和上线指标上 这样做出来的系统,才更像能进真实流程的医疗 AI,而不是一个演示效果不错的研究原型。 数据集优先选 MIMIC-CXR + RadGraph,先做胸片报告生成原型 严格使用 patient-level split Perception Agent 先从多标签分类 baseline 做起 Evidence Agent 优先做结构化表,而不是自由文本摘要 Report Agent 强制基于 evidence table 生成 QA Agent 同时使用规则检查和语义一致性检查 指标不要只看 BLEU,至少补 FactCC / RadGraphF1 / 风险错误率 记录端到端延迟、人工复核率和被拦截原因 如果你要自己落地一个 demo,目录结构可以这样起: 这个结构的好处是后面你要替换任意一个 Agent,不会把整套系统拆坏。 如果后面你愿意继续做这条线,下一篇我会接着写: AI+医疗实战:病理图像 + 文本怎么做长上下文记忆与诊断建模? 它会更偏病理多模态、长上下文和 memory 设计,也更接近现在很多医疗 MLLM 的热点方向。 仅从工程经验看,病理场景比胸片更能体现多智能体和长上下文设计的价值。
Stage 4:QA Agent
八、代码实现思路:不要先写 Agent,对象和状态机先定好
from dataclasses import dataclass, field
from typing import List, Dict, Any
@dataclass
class MedicalState:
study_id: str
images: List[str]
patient_info: Dict[str, Any]
visual_evidence: List[Dict[str, Any]] = field(default_factory=list)
text_evidence: List[Dict[str, Any]] = field(default_factory=list)
evidence_table: List[Dict[str, Any]] = field(default_factory=list)
draft_findings: str = ""
draft_impression: str = ""
qa_flags: List[Dict[str, Any]] = field(default_factory=list)
decision: str = "pending"
class PerceptionAgent:
def run(self, state: MedicalState) -> MedicalState:
# 1. 图像预处理
# 2. 分类 / 检测 / 分割模型推理
# 3. 输出结构化证据
return state
class EvidenceAgent:
def run(self, state: MedicalState) -> MedicalState:
# 1. 合并视觉证据与文本证据
# 2. 做术语标准化、去重、冲突消解
return state
class ReportAgent:
def run(self, state: MedicalState) -> MedicalState:
# 1. 先生成 findings
# 2. 再生成 impression
return state
class QAAgent:
def run(self, state: MedicalState) -> MedicalState:
# 1. 规则检查
# 2. LLM 语义一致性检查
# 3. 输出 pass / review / reject
return state
class Orchestrator:
def __init__(self):
self.pipeline = [
PerceptionAgent(),
EvidenceAgent(),
ReportAgent(),
QAAgent(),
]
def run(self, state: MedicalState) -> MedicalState:
for agent in self.pipeline:
state = agent.run(state)
if state.decision == "reject":
break
return state
九、评估怎么做,才不会把系统评估做偏?
1)单 Agent 级评估
2)系统级评估
3)消融实验
十、部署时最容易踩的 6 个坑
1)把 Agent 数量当作先进性指标
2)中间状态不结构化
3)忽略 patient-level split
4)用 BLEU 当主指标
5)不做人工复核闭环
6)把质控放在最后一层才做
十一、什么时候不该上多智能体?
十二、一个我更推荐的迭代顺序
第一步:单模型 baseline
第二步:加 Evidence 层
第三步:加 QA 层
第四步:最后才考虑更复杂的多 Agent 协作
十三、结论
可复现要点清单
代码仓设计建议
medical-multiagent/
├── data/
├── configs/
├── models/
│ ├── perception/
│ ├── report/
│ └── qa/
├── agents/
│ ├── orchestrator.py
│ ├── perception_agent.py
│ ├── evidence_agent.py
│ ├── report_agent.py
│ └── qa_agent.py
├── schemas/
│ └── state_schema.py
├── eval/
│ ├── eval_perception.py
│ ├── eval_report.py
│ └── eval_system.py
└── app/