本项目是一个解决医院前台主索引建档与查询时因生僻字、同音字、简繁体、间隔符及 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_EXACTtrue是否启用 L1 身份证精确匹配FMFD_L2_MIN_SCORE0.85L2 拼音加生日加性别匹配的最低阈值FMFD_L3_MIN_SCORE0.70L3 加权模糊匹配的最低阈值FMFD_L3_TOP_K5L3 匹配返回的候选档案数量上限FMFD_NAME_LEV_WEIGHT0.50姓名编辑距离在综合分中的权重FMFD_NAME_JW_WEIGHT0.30姓名 Jaro-Winkler 相似度在综合分中的权重FMFD_NAME_JACCARD_WEIGHT0.20姓名 Jaccard 相似度在综合分中的权重此外还可以控制各类变体注入的开关与比例用于测试和评估匹配算法的鲁棒性。例如可以设置生僻字注入比例为 0.10同音字注入比例为 0.08简繁体注入比例为 0.05 等。这些配置确保了工具在不同医院的数据质量下都能灵活适配。数据安全与合规说明在医疗场景下数据安全与合规是重中之重。本项目在设计之初就严格遵循了数据隐私保护原则。零真实数据存储 本工具不存储、不上传任何真实患者数据。所有的演示数据均为本地合成的 mock 数据包含八百多个真实姓名和两百多个真实姓氏但身份证号、手机号、生日均为合成数据。内存数据库机制 主索引 SQLite 默认为内存数据库进程退出即自动销毁。如果确需落盘可以通过参数指定路径但强烈建议不要将数据库文件提交到代码仓库。严格脱敏台账 生成的脱敏台账只保留掩码处理后的身份证号、姓名拼音首字母、年龄段、性别、来源系统和创建年份绝对不会出现完整姓名、完整身份证号或完整手机号。人工合并审计留痕 所有的人工合并操作必须通过 merge 子命令进行交互式二次确认并写入审计日志文件。日志中会记录操作人、合并原因和时间戳确保每一次合并都可追溯。辅助定位而非替代流程 本项目不替代院内正式的主索引合并流程仅作为前台辅助提示与人工合并留痕工具帮助信息科和前台人员更高效地处理边角案例。技术选型与架构思考在技术选型上我们坚持使用纯规则加离线匹配的主路径没有引入大语言模型。这主要是基于医院前台场景的三个硬性要求。响应时长要求 前台操作需要极高的效率系统响应时长必须控制在一秒以内。大语言模型的推理延迟无法满足这一要求。可解释性要求 每一条匹配命中都必须能够清晰地说出原因例如是因为拼音相同还是因为字形相似。大语言模型的输出具有不可控性难以提供确定性的解释。审计追溯要求 医疗数据的合并需要严格的审计留痕谁合并了谁、为什么合并都必须有明确的规则依据。大语言模型的黑盒特性无法提供可靠的审计支持。因此大语言模型仅在整改清单措辞润色等非关键环节作为可选辅助。核心匹配逻辑完全依赖 pypinyin、opencc、python-Levenshtein 和 jellyfish 等成熟的开源库确保了系统的稳定性、可控性和离线部署能力。项目地址 https://github.com/nexorin9/healthcard-fuzzy-match-frontdesk