跳转到内容

FHIR:把患者时间线变成可计算资源

同一个化验值在 FHIR Bundle 里可能同时有 effectiveDateTimeissuedmeta.lastUpdated 和不同状态。把其中任意一个字段当成“检测时间”,都可能把过期结果送进一条看似正确的资格判断。

FHIR 不是“医疗版 JSON”,而是一套资源、元素、引用、搜索与实现约束的互操作标准。Patient 表示主体,Condition 表示问题,Observation 表示测量或简单断言,DiagnosticReport 汇总诊断报告,MedicationRequest 表示用药请求;把所有内容塞进 Observation 会丢失语义。S01S02

医疗互操作经历了从文档和消息标准到资源化 API 的演进。FHIR 的资源与 REST 风格降低了应用集成门槛,SMART App Launch 又在其上定义 OAuth 2.0 授权和 EHR 启动。S03 但“能取到资源”不代表“能正确形成时间线”–事件发生时间、记录时间、状态、单位、修订版本和 encounter 都可能不同。

Agent 常犯三种错:只取第一页、把无效/取消结果当有效、按字符串比较不同单位。更严重的是 bearer token 权限过大或日志记录了完整资源。

对每条资源提取:患者、资源类型/id/version、临床有效时间、记录时间、状态、编码系统、数值/单位、来源引用。排序前先定义“这个任务需要哪个时间”–入排标准通常关心样本采集或事件发生时间,而不是服务器更新时间。

查询遵循最小化原则:限定 patient、日期、code、status 和 _count,处理 pagination,保留 ETag/versionId。SMART scope 也应最小化,例如只读应用不申请写 scope。FHIR Security 页明确安全是实现共同责任,标准不替部署者完成授权、审计和同意管理。S13

方案 定位 取舍
FHIR R4 交换与应用接口 生态成熟;需 profile 和本地映射 S01
SMART App Launch 应用授权/启动 管 token/scope;不是 ABAC 全方案 S03
OMOP CDM 观察性研究分析 适合队列分析,不是事务型 EHR API S05
MedAgentBench FHIR 环境 Agent 执行评测 可学习任务设计,不能当生产 FHIR S32
Terminal window
python3 labs/run_lab.py --lab 06

实验从一个 FHIR Bundle 中抽取有效 Observation,完成 mg/dL 到 g/L 的受控换算,按 effectiveDateTime 形成时间线,并忽略 entered-in-error。扩展任务是故意加入另一患者资源,验证 patient scope 拦截。

先跑一次看哪些资源被纳入,再只加入一条另一患者的 Observation,最后确认失败来自 patient scope,而不是模型碰巧没有使用它。这个顺序把“数据访问正确”与“回答看起来合理”分开验证。

怎样查询一个协议需要的患者事实

Section titled “怎样查询一个协议需要的患者事实”

协议要求确认过去 14 天 ANC。运行时不应该请求“这个患者所有 Observation”,而是由 TrialCriterion 生成受控 QueryPlan:patient scope、LOINC/本地 code 集、日期上下界、允许状态和需要字段。FHIR adapter 检查 scope 后执行分页查询,保存响应 Bundle 的 server、timestamp 与每个 resource version,再将最小必要字段转换成 Evidence。

如果服务器返回三条记录:一条 final、一条 preliminary、一条 entered-in-error,选择规则来自 criterion/evidence policy,而不是模型随意决定。若 final 使用本地代码、preliminary 使用标准 code,术语映射也必须进入可审计变换。数据不足时 adapter 返回结构化 no_evidencemapping_unknown,不要把空数组交给模型猜原因。

meta.lastUpdated 表示资源版本更新时间,不是临床事件发生时间;Observation 可能用 effectiveDateTimeeffectivePeriod 等表达有效时间,issued 又是结果可用时间。Condition 的 onsetrecordedDate 也不同。患者时间线要按任务选择临床时间,同时保留记录时间和不确定性。

状态语义同样重要。Observation finalamended 可被纳入,entered-in-error 通常排除;DiagnosticReport、MedicationRequest 又有不同状态机。不能写一个全局 status == final 规则。FHIR resource/profile 版本升级时,adapter contract tests 必须重跑。S01S02

引用也不能只保存 Reference.reference 字符串。生产环境可能使用绝对/相对 URL、contained resource、版本化历史和 identifier reference。解析器应在受控 server context 内解析,禁止把任意 URL 当可访问地址,以免 SSRF 或跨租户读取。

SMART App Launch 处理应用启动和 OAuth 2.0 scope。S03 它回答“应用拿到了什么 token”,但 MedAgent Forge 还要回答“这个 Agent 当前任务能用 token 做什么”。因此 token 放在 tool gateway,不进入模型上下文,gateway 把用户授权、患者 scope、purpose 和 tool risk 一起决策。即使 token 技术上能读更多资源,TaskContext 仍可限制到当前患者和指定 code/date。

对系统级批处理更要谨慎。system/*.read 不意味着 Agent 可遍历全库,批任务需要独立 service identity、批准的 cohort 定义、网络和审计策略。教学 demo 只使用合成 Bundle,不模拟万能 token。

FHIR 是交互边界,OMOP 是分析模型,Evidence 是 Agent 决策合同。把 FHIR 全量 ETL 到 OMOP 可能适合队列研究,但一次实时筛选不应等待整库转换;反过来,直接在 FHIR API 上跑复杂大队列分析也可能低效。MedAgent Forge 可以用 OMOP 进行初筛 cohort,再用 FHIR 获取当前、版本明确的证据,最终都转成 Evidence。

测试至少覆盖分页、空结果、429/5xx、超时、token 过期、不同 patient、resource 修订、缺单位、未知 code、effectivePeriod、contained reference 和 bundle 中重复 resource。contract test 对接 HAPI FHIR sandbox 或受控 mock,TaskPackage 再测试 Agent 是否在 adapter 错误时正确恢复/升级。单元测试通过不意味着具体医院 profile 已支持。

  • 示例只覆盖少量 R4 字段,不是通用 FHIR 客户端。
  • 单位转换应使用受控体系和经过验证的库;实验硬编码只教学。
  • profile、术语绑定和扩展随机构不同,生产必须验证 CapabilityStatement。
  • token、resource id 和 narrative 可能含敏感信息,不应直接进入 trace。

完整的来源类型、用途与边界见教材来源注册表

  • S01 HL7 FHIR R4
  • S02 FHIR Observation
  • S03 SMART App Launch
  • S13 FHIR Security
  • HL7 FHIR R4:从资源、搜索和引用开始读,避免把 FHIR 缩减成 JSON 格式约定。
  • FHIR Observation:核对测量、状态和时间语义;本地 profile 仍需单独验证。
  • SMART App LaunchFHIR Security:分别理解 OAuth/scope 和实现方仍需承担的授权、审计责任。