为 FHIR 患者快照代理添加向量搜索和嵌入式 Python 功能
在我的第一篇文章中,我介绍了 FHIR 患者快照代理的基础版本:这是一个基于 Streamlit 和 Python 的应用程序,它从 InterSystems IRIS for Health 中检索 FHIR 资源,并利用大型语言模型(LLM)生成简明扼要的患者摘要。
本文作为后续文章,将介绍我是如何通过添加两项针对 InterSystems 的功能来扩展该项目的:
- 源上下文向量搜索
- 用于 IRIS 兼容审查的嵌入式 Python 组件
目标是让该项目作为临床摘要原型更具实用性,同时保持设计足够精简,以便于理解和复现。
项目回顾
FHIR 患者快照代理(FHIR Patient Snapshot Agent)是一款基于人工智能的 FHIR 患者数据摘要工具。
该应用程序可检索所选患者的结构化资源:
- 患者
- 病情
- 用药请求
- 过敏与不耐受
- 观察
- 就诊
- 护理计划
Python 层将这些资源整合为一个紧凑的患者背景。用户随后可以生成以下任一内容:
- 确定性摘要,或
- 由大型语言模型(LLM)生成的针对特定角色的摘要
该 LLM 集成通过兼容 OpenAI 的聊天补全 API 使用 Nebius Token Factory。演示中使用的模型为:
meta-llama/Llama-3.3-70B-Instruct该项目为开源项目:
在线演示:
为何要添加向量搜索?
该应用的第一个版本已经显示了生成的患者快照以及所使用的源FHIR资源。
然而,即便是简短的患者病历,也可能包含许多规范化的部分:
- 当前病情
- 用药情况
- 过敏史
- 观察结果
- 就诊记录
- 护理计划
- 缺失信息
- 来源与资源参考
对于审稿人而言,快速提出以下问题会很有帮助:
medications allergies labs或者:
encounters care plans该应用现已在 Streamlit 界面中新增了“源上下文向量搜索”部分。生成快照后,用户可对标准化后的患者上下文进行搜索,并查看最相关的段落。
向量搜索的实现方式
在此原型中,我对归一化的患者快照段落采用了轻量级的本地向量化方法。
具体实现如下:
- 将标准化后的患者上下文划分为命名片段。
- 将每个片段转换为令牌频率向量。
- 将用户的查询转换为相同的向量表示形式。
- 使用余弦相似度对片段进行排序。
- 在用户界面中显示相关性最高的源上下文部分。
该实现刻意设计得简洁且透明:
app/vector_search.pyStreamlit 用户界面调用此模块并显示排序后的匹配结果:
app/web_ui.py这并非旨在取代生产环境中的嵌入模型,而是为了清晰地演示向量搜索的工作流程:
- 对源数据进行归一化
- 将临床上下文部分向量化
- 比较查询向量与上下文向量
- 返回可追溯的源文本段落
在生产环境中,可以将这一概念迁移到 IRIS Vector Search 中,利用基于 FHIR 生成的临床上下文的持久化向量实现。
嵌入式 Python 组件
我还添加了兼容 IRIS 的 ObjectScript 类,其中包含嵌入式 Python 方法,位于以下路径下:
src/FHIR/Snapshot/该代码库包含:
src/FHIR/Snapshot/EmbeddedPythonDemo.cls src/FHIR/Snapshot/EmbeddedVectorSearch.cls这些类演示了如何在 IRIS 类方法中实现 Python 逻辑。
嵌入式 Python 示例包括:
- 提取数值观测值
- 将文本分词为简单的向量表示
- 计算余弦相似度
示例方法:
ClassMethod NormalizeObservationValue(value As %String) As %String [ Language = python ] ClassMethod Vectorize(text As %String) As %String [ Language = python ] ClassMethod CosineSimilarity(leftVectorJson As %String, rightVectorJson As %String) As %String [ Language = python ]包含这些组件是为了使该项目能够作为面向InterSystems的应用程序进行评审,而不仅仅是一个外部Python应用程序。
IPM / ZPM 元数据
该项目还包含一个名为 module.xml 的文件,其中包含包元数据和文件复制条目。
虽然主应用程序的运行环境仍是 Python 和 Streamlit,但包元数据使得在 InterSystems 生态系统背景下更容易审查该代码库。
相关文件:
module.xml观察可视化
我还在 Streamlit 用户界面中添加了简单的观察数据可视化功能。
该应用从标准化患者上下文中提取FHIR观察数据的数值,并按观察类别分组显示图表,例如:
- 生命体征
- 实验室
- 问诊/社会史
这支持了 InterSystems 社区关于为医生提供自定义可视化功能的构想:
目标并非创建一个完整的临床仪表盘,而是展示如何将FHIR观察资源转换为紧凑的可视化摘要,并将其与生成的文本快照并列呈现。
在线演示模式
该在线演示托管在 Render 上:
由于公开托管的应用程序无法访问本地 localhost 上的 IRIS FHIR 服务器,因此在线演示使用了从本地 IRIS for Health FHIR 服务器配置中捕获的“患者 1”上下文。
完整的实时 FHIR 工作流仍在本机 InterSystems IRIS for Health 上运行。
对于本地开发,流程如下:
InterSystems IRIS for Health FHIR Server -> Python FHIR client -> normalizer -> deterministic or LLM summary -> Streamlit UI安全框架
该应用仅用于摘要生成。
它不具备以下功能:
- 诊断
- 推荐治疗方案
- 替代临床判断
每份生成的摘要均包含明确的安全说明及来源资源的可追溯性。用户应参照所列的FHIR资源,对所有生成的内容进行核对。
开发过程中发现的错误报告
在审查 InterSystems Vector Search 演示材料时,我在 LlamaIndex 演示中针对本地 HuggingFace 嵌入的备用路径中发现并报告了一个可重现的问题:
该问题与 llama_demo.ipynb 中的本地嵌入路径有关:其中 LangchainEmbedding 被直接使用而未被导入,且即使选择了本地 all-MiniLM-L6-v2 路径,嵌入维度仍被设置为 OpenAI 嵌入的默认值。
我的收获
这一扩展使该项目更像是一个 InterSystems 应用程序,而非简单的 LLM 封装。
最有用的新增功能包括:
- 将 IRIS for Health 用作 FHIR 源系统
- 保持源资源的可追溯性
- 添加针对特定角色的 LLM 摘要
- 添加源数据上下文向量搜索
- 添加嵌入式Python构建产物
- 添加观察结果可视化
- 提供在线演示
虽然结果仍是一个小型原型,但现在已能展示更完整的工作流:
FHIR data -> normalized clinical context -> visual review -> vector search -> LLM summary链接
GitHub 仓库:
https://github.com/vinogrannia/fhir-patient-snapshot-agent在线演示:
YouTube 演示:
首篇文章: