本项目是一个解决医院前台主索引建档与查询时,因生僻字、同音字、简繁体、间隔符及 OCR 误差导致档案匹配失败问题的辅助工具。它主要面向医院门诊前台、自助机运维及信息科人员,通过纯规则与离线匹配的方式,在用户输入回车瞬间提供相近档案候选提示,将原本需要肉眼比对或电话求助的流程缩短至秒级。项目采用 Python 开发,核心依赖 pypinyin 处理多音字与同音字,opencc 处理简繁转换,并结合 python-Levenshtein 与 jellyfish 计算文本相似度,最终通过 Click 与 Rich 提供命令行交互界面。
为什么我们需要处理主索引的边角案例
在医联体、跨院调阅、互联网医院以及家庭医生签约等场景中,同一名患者在不同医院或不同时期录入的主索引档案经常对不上。这些对不上的情况往往不是核心信息错误,而是一些边角案例。
常见的边角错位包括以下几种情况。
生僻字 读卡器或自助机 OCR 识别错误,例如将「䶮」识别为「龙」,导致系统里同时存在「王䶮」和「王龙」,人工窗口无法直接判断是否为同一人。
同音字与近音字 输入法联想或手误导致,例如「张丽」与「张莉」、「刘洋」与「刘杨」、「李鑫」与「李新」,实际可能是同一人。
简繁体差异 跨代际或跨地区录入差异,例如「陳曉東」与「陈晓东」、「張偉」与「张伟」。
少数民族姓名与间隔符 中点、全角空格、半角空格混用,例如「买买提·艾力」、「买买提 艾力」、「买买提艾力」。
OCR 与读卡器误差 字形相似导致识别错误,例如「梁」与「樑」、「户」与「戸」、「关」与「関」,以及数字 0 与字母 O、数字 1 与小写字母 l 的混淆。
手输笔误 身份证号一位手抖、姓名多打一个空格、姓名顺序错位等。
这些边角案例占真实前台工作量的比例虽然不大,但每一次都会让窗口卡住三十秒到五分钟,不仅让患者投诉,还会让前台多打一次电话给信息科求助。当前主流的做法是靠人工肉眼比对,或者干脆允许重复建档,等后期病案室再合并。后者会让医保对账、主数据治理、患者随访全部变难。
我们可以看一个典型的痛点场景。周一早上七点五十分,门诊大厅已经排了八十多人。自助机刷不出「王䶮」这位患者的档案,直接提示未建档。前台老师手输「王龙」,身份证号位数对不上,系统提示姓名不匹配。前台老师打电话给信息科,信息科建议先用拼音查一下。拼音查出来三个「wang long」。折腾四分钟后找到原档案,挂号窗口已经堆了五张卡。
这个小工具要做的事情,就是把上述肉眼比对、电话求助、二次录入这三步,在前台输入框回车那一刻,直接提示系统里有几个相近档案,请人工二次确认,并把候选档案并排展示,让前台一次性完成读卡和合并。
核心功能与匹配逻辑
本项目的核心在于一套纯规则加离线匹配的三级匹配机制。医院前台对响应时长、可解释性以及审计追溯三方面要求极高,因此我们设计了分层匹配逻辑。
L1 身份证精确匹配 直接比对身份证号,适用于证件读取正常且无篡改的场景,速度最快。
L2 拼音加生日加性别匹配 在身份证不可用或存在误差时,将姓名转换为拼音,结合出生日期和性别进行综合打分。
L3 加权模糊匹配 针对生僻字、同音字、简繁体等复杂情况,综合计算编辑距离、Jaro-Winkler 相似度以及 Jaccard 相似度,给出最终的综合得分。
在姓名归一化方面,我们处理了简繁互转、中点与全角空格归一以及空白折叠。在拼音转换方面,除了基础的姓名转拼音和拼音首字母,还特别内置了姓氏多音字锁定表,覆盖尉迟、单于、长孙、解、朴、尉、仇、翟等两百多个复姓和特殊姓氏,确保多音字在作为姓氏时能被正确锁定。同时基于 pypinyin 词表构建反向索引,快速给出近音候选。
模块设计与目录布局
项目结构清晰,按照功能职责进行了模块化拆分,方便后续扩展和维护。
normalize 目录 负责姓名归一化,包括简繁互转、中点与全角空格归一、空白折叠。
pinyin 目录 负责姓名转拼音、拼音首字母提取,以及基于词表构建反向索引给出近音候选。
match 目录 实现三级匹配机制,包含 L1 身份证、L2 拼音加生日加性别、L3 加权模糊匹配逻辑。
empi 目录 定义主索引数据模型,包含十万条 mock 数据生成器,支持生僻字、同音字、繁简、间隔符、OCR 五种变体注入,并使用 SQLite 内存存储。
scenario 目录 负责前台场景化数据生成,涵盖建档、读卡、手工输入三类场景,并区分简单、中等、困难三种难度。
report 目录 生成脱敏台账与 Markdown 格式的整改清单。
eval 目录 提供匹配质量度量,计算精度、召回率、F1 分数以及误合并率,并按难度分组统计。
cli 目录 基于 Click 和 Rich 实现的命令行入口,包含建档、查询、合并、审计、演示和报告生成等子命令。
使用指南与命令清单
项目提供了丰富的命令行工具,方便信息科和前台人员进行测试与日常使用。以下是快速开始的步骤。
cd healthcard-fuzzy-match-frontdesk pip install -r requirements.txt python -m src.cli.main --help python -m src.cli.main demo --pause python -m src.cli.main report python -m src.cli.main audit --output reports/audit_demo.md python -m src.cli.main lookup --name 尉迟恭 --id-card 110101199003078888 --birth-date 1990-03-07 --gender M pytest -q具体的子命令及其用途如下表所示。
子命令 | 用途说明 |
|---|---|
enroll | 前台建档,自动匹配现有主索引,提供绿色、黄色、蓝色不同级别的提示 |
lookup | 仅查询不建档,输出 Rich 格式的表格候选列表 |
merge | 人工二次确认合并,写入审计日志留痕 |
audit | 主索引健康度审计,统计变体占比和潜在重复数,输出 Markdown 报告 |
demo | 运行内置的边角案例演示,展示彩色面板效果 |
report | 一键生成端到端报告,包含审计、演示和台账数据 |
配置参数与阈值调整
项目通过环境变量文件进行配置,允许用户根据实际业务需求调整匹配阈值和变体注入比例。以下是核心配置项的说明。
配置项 | 默认值 | 说明 |
|---|---|---|
FMFD_L1_ID_CARD_EXACT | true | 是否启用 L1 身份证精确匹配 |
FMFD_L2_MIN_SCORE | 0.85 | L2 拼音加生日加性别匹配的最低阈值 |
FMFD_L3_MIN_SCORE | 0.70 | L3 加权模糊匹配的最低阈值 |
FMFD_L3_TOP_K | 5 | L3 匹配返回的候选档案数量上限 |
FMFD_NAME_LEV_WEIGHT | 0.50 | 姓名编辑距离在综合分中的权重 |
FMFD_NAME_JW_WEIGHT | 0.30 | 姓名 Jaro-Winkler 相似度在综合分中的权重 |
FMFD_NAME_JACCARD_WEIGHT | 0.20 | 姓名 Jaccard 相似度在综合分中的权重 |
此外,还可以控制各类变体注入的开关与比例,用于测试和评估匹配算法的鲁棒性。例如,可以设置生僻字注入比例为 0.10,同音字注入比例为 0.08,简繁体注入比例为 0.05 等。这些配置确保了工具在不同医院的数据质量下都能灵活适配。
数据安全与合规说明
在医疗场景下,数据安全与合规是重中之重。本项目在设计之初就严格遵循了数据隐私保护原则。
零真实数据存储 本工具不存储、不上传任何真实患者数据。所有的演示数据均为本地合成的 mock 数据,包含八百多个真实姓名和两百多个真实姓氏,但身份证号、手机号、生日均为合成数据。
内存数据库机制 主索引 SQLite 默认为内存数据库,进程退出即自动销毁。如果确需落盘,可以通过参数指定路径,但强烈建议不要将数据库文件提交到代码仓库。
严格脱敏台账 生成的脱敏台账只保留掩码处理后的身份证号、姓名拼音首字母、年龄段、性别、来源系统和创建年份,绝对不会出现完整姓名、完整身份证号或完整手机号。
人工合并审计留痕 所有的人工合并操作必须通过 merge 子命令进行交互式二次确认,并写入审计日志文件。日志中会记录操作人、合并原因和时间戳,确保每一次合并都可追溯。
辅助定位而非替代流程 本项目不替代院内正式的主索引合并流程,仅作为前台辅助提示与人工合并留痕工具,帮助信息科和前台人员更高效地处理边角案例。
技术选型与架构思考
在技术选型上,我们坚持使用纯规则加离线匹配的主路径,没有引入大语言模型。这主要是基于医院前台场景的三个硬性要求。
响应时长要求 前台操作需要极高的效率,系统响应时长必须控制在一秒以内。大语言模型的推理延迟无法满足这一要求。
可解释性要求 每一条匹配命中都必须能够清晰地说出原因,例如是因为拼音相同还是因为字形相似。大语言模型的输出具有不可控性,难以提供确定性的解释。
审计追溯要求 医疗数据的合并需要严格的审计留痕,谁合并了谁、为什么合并,都必须有明确的规则依据。大语言模型的黑盒特性无法提供可靠的审计支持。
因此,大语言模型仅在整改清单措辞润色等非关键环节作为可选辅助。核心匹配逻辑完全依赖 pypinyin、opencc、python-Levenshtein 和 jellyfish 等成熟的开源库,确保了系统的稳定性、可控性和离线部署能力。
项目地址: https://github.com/nexorin9/healthcard-fuzzy-match-frontdesk