捕捉隐形错误:我如何为肯尼亚的 HIV 项目构建重复检测智能体

Elasticsearch Agent Builder 黑客马拉松

catching-invis-errors-blog_(1).png

在肯尼亚的许多县级卫生部门,监测与评估 (M&E) 官员可能得花费整整一天的时间运行 Excel 数据透视表,仔细查看患者姓名,交叉引用样本 ID,而这样仍然只能捕捉到大约 44%的重复数据。其余 56% 的重复数据则悄无声息地滞留在系统中,不仅虚增了“美国总统艾滋病紧急救援计划”(PEPFAR)的数据看板,造成试剂资源的浪费,更削弱了临床医生赖以制定治疗决策的数据的可信度。

我之所以知道这一点,是因为我在工作中看到了这一点。我是内罗毕一家健康科技公司的解决方案架构师。我们建立并维护部署在肯尼亚所有 47 个县的卫生信息系统。重复的患者记录是那种没人会用幻灯片来展示,但每个人都能切身体会的问题。

当 Elasticsearch 智能体构建者黑客松 (Agent Builder Hackathon) 宣布举办时,我根本不需要到处去寻找参赛课题,因为这个问题已经在我的桌子上放了好几个月了。

重复是如何发生的(以及它们为何难以发现)

肯尼亚的 HIV 检测基础设施主要开展两项关键的实验室测试:HIV 暴露婴儿的早期婴儿诊断 (EID) 和接受抗逆转录病毒治疗的成人的病毒载量 (VL) 监测。这些检测在肯尼亚电子病历系统 (KenyaEM) 中下医嘱,在实验室进行处理,检测结果通过肯尼亚的健康信息交换系统传回医疗机构。

导致数据重复的场景既不光鲜又耗费巨大——例如,一位母亲带着婴儿到机构 A 做检测,然后又在机构 B 用一个稍有不同的名字再次检测;一名接受抗逆转录病毒治疗 (ART) 治疗的成年人跨县后重新登记;有人故意使用不一致的人口统计信息,以便在多个地点获取服务。

每个场景都会创建一个幽灵记录。如果将这种情况放大到 500 多个医疗机构,数据就变得非常现实:每年大约有 195,000 美元用于重复测试、浪费试剂和夸大的报告。手动检测每个案例大约需要两个小时。这样下去,积压的工作只会越来越多。

我希望有一种能够在几秒钟内扫描 1,000 条记录,并能用医疗工作者易于理解且可据以行动的语言解释其推理的方案。

系统:3 个各自负责特定任务的智能体

我在 Elasticsearch 8.11 (Serverless) 上使用 Elastic Agent Builder 构建了一个多代理系统,使用 Claude Sonnet 3.7 作为推理模型。与其让一个单一的代理尝试完成所有工作,我将工作分成了三个代理——检测代理、风险评估代理和行动推荐代理。每个代理都有狭窄的范围、特定的输入和定义的输出格式。

检测代理

检测智能体针对患者索引运行 ES|QL 查询,通过三个维度寻找重复数据:跨机构模式匹配(同一患者出现在多家医疗机构)、人口统计学分析(例如名字变异、不一致的性别标识以及部分 ID 匹配)以及时间异常检测(同一天在距离遥远的机构进行检测)。这是系统的搜索层。它只负责找出疑似候选病例,而不做最终的对错判定。

风险评估师

风险评估智能体接收这些候选病例,并利用加权信号为它们评出 0 到 100 之间的风险分值:

  • 跨馆访问:最高40分
  • 人口统计不一致:最高可达 30 分
  • 地理不可能性:高达 20 分
  • 时间异常:最多 10 分

病例分为四级:极高风险、高风险、中度风险或低风险。我稍后会解释为什么我没有使用二元分类。

行动建议智能体

行动建议智能体将风险分值转化为针对肯尼亚医疗背景量身定制的具体下一步行动:对于极高风险的病例,立即通知监测与评估 (M&E) 官员进行审核;对于中度风险的病例,在其下次就诊时进行标记提醒;而对于表现出系统性数据错误模式的医疗机构,则提供员工培训建议。这个智能体的存在,是因为单纯一个风险分数对医护人员毫无用处。他们需要知道要针对分数采取什么行动。

为什么我使用多因素评分而不是二元分类

在构建初期,我尝试了一种更简单的方法:直接分为重复或非重复数据。但它在遇到真实数据后就失效了。

问题在于合法的后续测试看起来很像数据重复。接受抗逆转录病毒治疗 (ART) 的患者本就应该每隔几个月到同一机构就诊一次。婴儿理应反复接受测试。二元分类法要么会把大量合法的就诊记录错误地标记为违规警报(导致医护人员忽略所有标记),要么会漏掉那些“”在同一天用稍微不同的名字在两家不同机构进行检测”的隐蔽欺诈病例。

而分层的方法让医护人员能够区分轻重缓急。一个风险评分为 87 的极高风险病例(特征表现为:同一天在不同机构进行检测,且性别标识前后不一致)会立即得到关注。一个风险评分为 22 分的低风险病例(特征表现为:在同一个医疗机构进行检测,预期随访间隔相同)会被归档。最终决定由监测与评估官员做出,但此时他们是依据确凿的证据链在开展工作,而不是凭直觉瞎猜。

权重校准需要多次与真实数据进行对比。我仍然不能完全确定它们是最佳方案。但结构是正确的,权重可以随着我们收集更多的实地数据而调整。

Elasticsearch 的工作使之成为可能

我在索引设计上投入的前期时间比系统其他任何部分都要多,而这正是我所做的最佳时间投资。

索引映射包括在索引时计算的派生字段:每个患者的跨机构标识总检测数以及就诊机构数量。关键人口统计字段既有关键字(精确匹配),又有文本(分析,模糊搜索)子字段,因此检测智能体可以根据它所追踪的信号在严格匹配和模糊匹配之间切换,例如对样本 ID 使用严格匹配,而对患者姓名使用模糊匹配,因为在现实中,“Wanjiku”和“Wanjiku Mary”很有可能是同一个人。

我还大量使用了 Elasticsearch 的聚合功能进行候选病例预筛选。系统在运行成对比较之前,会按医疗机构、检测类型和日期范围对记录进行分桶处理。这就是在大规模数据集上依然能保持检索可控的核心秘诀。如果能先缩小候选范围,就不需要将每条记录与其他记录进行比对。

ES|QL 对我来说很新鲜。我是在黑客马拉松上学习 ES|QL 的,它在大规模实时分析方面令人印象深刻。对我来说,最有效的架构是将用于模式检测和聚合的 ES|QL 与用于处理应用程序逻辑的 Python 进行结对配合。考虑到我是新手,这种分离使我的整个系统更容易推理。

代理实际发现的内容

我在来自肯尼亚 59 家医疗机构的 1,010 份真实匿名患者记录上测试了该系统。扫描在 10 秒内完成。

它发现了 131 名重复的病人,其中有 5 名病人于同一天在多个医疗机构进行检测,有 4 位病人故意在不同的医疗机构使用不一致的性别标识符。

让我感到惊讶的是同一天检测的案例。如果有人足够耐心,手动核查最终总会发现名字重复的情况。但是,要想敏锐地察觉到一名患者在同一天内、在地理位置相隔遥远的两家医疗机构进行了检测,并且其人口统计学信息(如性别或出生日期)还做了一点点微调,这种异常模式在数据中几乎处于完全“隐形”状态,除非你特意去检索。监测与评估官员告诉我,这些病例如果靠人工核查的话,需要数周的时间才能发现,前提是它们如果真的能被发现的话。

我意想不到的一课:可解释性就是产品

早期的系统原型只风险评分和建议。我把这些结果展示给监测与评估官员,但他们不信任系统输出的结论。

这不是技术上的失败;系统给出的分值是准确的。但是,医疗工作者在查看被标记的患者时需要了解为什么他们会被标记才会采取行动。是名字不匹配吗?还是地理上的不可能性?或是时间存在冲突?没有这些背景信息,系统就是一个黑盒,而在临床环境中,当涉及到患者的治疗时,黑盒会被忽视。

当我构建行动建议智能体以输出具体和引用证据的解释后,系统原型才成功转变成为了人们会实际使用的工具。我在内罗毕向一位监测与评估官员演示这个功能时,他说:“如果上个月有这个工具,我能节省三天的时间。”

这一教训并不仅限于医疗行业。如果你的 AI 系统给出的建议需要人类采取行动,那么解释和建议一样,都是产品的核心组成部分。

给出正确的智能体指令

每个智能体均在 Elastic Agent Builder 中内置,配有自定义指令,定义其领域专长、推理步骤和输出格式。我低估了这些指令质量的重要性。

早期版本由于指令模糊,产生的输出存在不一致的情况。检测智能体有时会解释原因,有时则不会。风险评估智能体有时会跳过一个评分因素。要获得可靠的、基于证据的输出,需要对所需的证据字段具体说明,并明确智能体应遵循的推理链。像对待代码一样对待自定义指令:要精确、测试边缘用例和并不断迭代。

下一步是什么?

这不是一个会被存档的黑客松演示。我们的计划是在未来 2–3 个月内在内罗毕县的五个医疗机构进行试点,培训监测与评估官员并收集实际运行数据,以完善风险权重。

在此之后,我们的路线图包括生物识别匹配集成和斯瓦希里语音名称模糊匹配,这在目前的现有方法中是一个真实的技术空白(比如对齐“Wanjiku”与“Wanjiku”非常简单,但要对齐“Njeri”与“Njery”则需要具备对当地语言的发音感知能力,这是标准的模糊匹配算法无法很好处理的)。最终,我的目标是让这套系统在患者于医院信息管理系统 (HMIS) 进行挂号登记时实现实时运行,在重复数据进入系统之前将其拦截,而不是事后处理。

从长远来看,我希望这套系统能连接到肯尼亚的健康信息交换系统,并将其扩展到所有 47 个县。Elasticsearch 的水平扩展性和模块化智能体设计意味着核心系统不需要重建;它只需要扩展。在全国范围内推广后的预期影响:每年节省 195,000 美元,重复测试减少 70%。更重要的是,临床医生在做出治疗决定时可以信任他们所查看的记录。

核心要点

如果你所处的业务领域正饱受着那种隐蔽、代价高昂且高度依赖人工的数据质量问题的折磨,那么借助 Elastic Agent Builder,并利用诸如用于模式检测的 ES|QL、用于分层分析的多智能体编排、以及用于特定领域推理的自定义指令等工具,你便能打造出一款能够直接解释问题,而不仅仅是查询问题的系统。整个系统的落成速度甚至比我预期的还要快。

在整个构建过程中,最让我感到满足的并不是获得了黑客松的奖项名次,而是亲眼看着每天都在从事这项工作的一线人员在大约十秒钟内就意识到这个工具真正懂他们所面临的难题。

Fredrick Kioko

解决方案架构师,

Fredrick Kioko 是一位常驻肯尼亚内罗毕的解决方案架构师,负责构建健康信息系统并致力于启动 Jamii Health Innovations。

GitHub · 演示 · LinkedIn

本文中描述的任何功能或功能性的发布和时间均由 Elastic 自行决定。当前尚未发布的任何功能或功能性可能无法按时提供或根本无法提供。

在本博文中,我们可能使用或提到了第三方生成式 AI 工具,这些工具由其各自所有者拥有和运营。Elastic 对第三方工具没有任何控制权,对其内容、操作或使用不承担任何责任或义务,对您使用此类工具可能造成的任何损失或损害也不承担任何责任或义务。请谨慎使用 AI 工具处理个人、敏感或机密信息。您提交的任何数据都可能用于 AI 训练或其他目的。Elastic 不保证您所提供信息的安全性或保密性。在使用任何生成式 AI 工具之前,您都应自行熟悉其隐私惯例和使用条款。

Elastic、Elasticsearch 及相关标志是 Elasticsearch B.V. 在美国及其他国家/地区的商标、徽标或注册商标。所有其他公司和产品名称均为其相应所有者的商标、徽标或注册商标。