OpenMed 多语言临床文本去标识化实战:lang 与 locale 驱动的端侧 PII 脱敏
【免费下载链接】openmedLocal-first healthcare AI: clinical NER & HIPAA PII de-identification that runs 100% on-device. 2,200+ medical models, 21 languages, Apple MLX + Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed
本篇技术指南讲解 OpenMed 如何对非英语临床文本执行完全端侧的 PII 去标识化:只需向deidentify/extract_pii传入lang=,框架便会自动为该语言挑选专用 PII 模型、语言特定正则模式(各国身份证号、电话格式等)以及 locale 感知的假数据生成器,同时通过locale=控制替换用的"本土化"假数据。读完本文,你将掌握如何运行时发现支持语言、处理西班牙语/德语/法语等多语言病历、校验并脱敏 DNI、NIR、Steuer-ID、Codice Fiscale、BSN、CPF、TCKN、Aadhaar 等国家级证件号,以及规避混合语言与日期歧义等常见陷阱。
何时使用本技能
只要源文本不是英语,或者替换结果必须"看起来像本地人生成"的数据,就应启用多语言去标识化。典型场景包括:
- 处理西班牙语、德语、法语、意大利语、葡萄牙语、荷兰语、印地语、泰卢固语、阿拉伯语、日语、土耳其语等语言的病历;
- 需要生成符合目标区域格式的假数据——例如一份德语病历应得到德语风格的假姓名和一个格式合法的 Steuer-ID 替代值,而不是美国 SSN;
- 需要识别并脱敏各国特有的国民证件号(DNI、NIR、Steuer-ID、Codice Fiscale、BSN、CPF、TCKN、Aadhaar 等)。
OpenMed 的多语言能力由 openmed/core/pii_i18n.py 统一承载:每种语言都有专属 PII 模型、语言特定正则模式与 locale 感知的替代值生成器,全部在设备端运行,无需上传任何数据。
运行时发现支持语言:不要硬编码
支持语言集合会随模型发布不断变化,因此正确做法是运行时查询,而非把某个数字写死在代码里:
import openmed from openmed.core.pii_i18n import SUPPORTED_LANGUAGES, get_patterns_for_language print(sorted(SUPPORTED_LANGUAGES)) # 运行时查询;该集合是唯一事实来源 # 查询某语言代码对应的默认 PII 模型: models = openmed.get_pii_models_by_language("es") # 查询语言特定正则模式(国民证件号、电话等): patterns = get_patterns_for_language("de")从源码结构看,OpenMed 的多语言覆盖相当广:openmed/core/pii_i18n.py中的LANGUAGE_NAMES与LANGUAGE_MODEL_PREFIX已为约 40 种语言代码注册了名称与模型前缀(涵盖阿萨姆语、孟加拉语、英语、法语、德语、意大利语、西班牙语、荷兰语、印地语、古吉拉特语、卡纳达语、马拉雅拉姆语、马拉地语、尼泊尔语、奥里亚语、旁遮普语、泰米尔语、泰卢固语、乌尔都语、阿姆哈拉语、葡萄牙语、阿拉伯语、波斯语、希伯来语、日语、土耳其语、印尼语、泰语、韩语、罗马尼亚语、俄语、中文、斯瓦希里语、祖鲁语、科萨语、瑞典语、丹麦语、挪威语、乌克兰语、捷克语、希腊语、越南语等),但具体哪些语言内置可用模型,必须以SUPPORTED_LANGUAGES的运行时结果为准。在openmed/core/language_pack_catalog.py中,SUPPORTED_LANGUAGES、LANG_TO_LOCALE、DEFAULT_PII_MODELS均由LANGUAGE_PACK_ADAPTERS(语言包适配器)统一提供,另有NATIONAL_ID_ONLY_LANGUAGES记录"仅有国民证件号规则、暂无完整模型"的语言。
同样的语言列表也通过 MCP 的openmed_list_pii_languages工具对外暴露,供 Agent 场景使用。
快速开始:以西班牙语为例
import openmed nota = ( "El paciente Carlos Hernández (DNI 12345678Z), nacido el 11/04/1979, " "vive en Calle Mayor 5, Madrid. Teléfono 612 345 678." ) result = openmed.deidentify( nota, lang="es", # 选择西班牙语 PII 模型 + ES 语言模式 method="replace", # 生成 locale 本土化的假值 locale="es_ES", # Faker locale(缺省时由 lang 经 LANG_TO_LOCALE 推导) ) print(result.deidentified_text) # El paciente [surrogate name] (DNI [surrogate]), nacido el [date], ...切换德语只需改语言代码:
befund = "Patientin Anna Müller, geb. 11.04.1979, Steuer-ID 12 345 678 901." result = openmed.deidentify(befund, lang="de", method="replace")底层机制是:lang="es"经 openmed/core/model_registry.py 的get_pii_models_by_language解析出西班牙语 PII 模型(非英语语言按pii_{lang}_前缀在注册表中匹配,英语走独立的通用路径),同时经get_patterns_for_language("es")组装西班牙语正则模式集;locale="es_ES"则通过openmed.core.anonymizer.locales的LANG_TO_LOCALE映射决定 Faker 假数据表。
推荐工作流
- 确认语言受支持:通过
SUPPORTED_LANGUAGES运行时查询,不要信任硬编码数量。 - 向
deidentify/extract_pii传lang=:这一参数同时完成两件事——经get_pii_models_by_language选择语言专属模型,经get_patterns_for_language选择国民证件号与格式的正则集。 - 在
method="replace"时设置locale=生成假数据:省略时,locale 由lang经LANG_TO_LOCALE推导(如pt→pt_PT)。可按需覆盖为区域变体:pt_BR(巴西葡萄牙语)、en_GB(英国)、以及海湾/马格里布阿拉伯语区域标签。 - 让重音归一化自动生效:对于基于无重音文本训练的模型(如西班牙语),
deidentify会在推理前自动去除变音符号,再把识别出的 span 映射回原始带重音文本,因此通常无需手动设置normalize_accents。 - 保持替代值稳定:跨文档需要一致替代时使用
consistent=True, seed=...。
语言特定的国民证件号:格式与校验
openmed.core.pii_i18n中内置了大量国家级证件号的格式正则 + 校验和验证器,即使模型对某些结构化 ID 把握不足,确定性规则仍能兜底捕获。文档整理的核心映射如下:
| 语言 | 证件号 | 验证器 |
|---|---|---|
| 法语 | NIR / INSEE | validate_french_nir |
| 德语 | Steuer-ID | validate_german_steuer_id |
| 意大利语 | Codice Fiscale | validate_italian_codice_fiscale |
| 西班牙语 | DNI / NIE | validate_spanish_dni、validate_spanish_nie |
| 荷兰语 | BSN | validate_dutch_bsn |
| 印地语 | Aadhaar | validate_aadhaar |
| 葡萄牙语 | CPF / CNPJ | validate_portuguese_cpf、validate_portuguese_cnpj |
| 土耳其语 | TCKN | validate_turkish_tckn |
这些验证器并非简单匹配外形,而是真实编码了各国的格式与校验算法。例如:
- 法国 NIR/INSEE(
validate_french_nir,见 pii_i18n.py):15 位字符,格式S AA MM DDD CCC OOO KK,校验规则为key = 97 - (前 13 位数字 mod 97);科西嘉省的2A、2B在计算校验和前分别归一化为19、18,首位必须是 1 或 2。 - 德国 Steuer-ID(
validate_german_steuer_id):恰好 11 位数字,首位不能为 0;前 10 位中恰好有一个数字出现 2 或 3 次,其余数字各出现一次(通过collections.Counter统计频次校验)。 - 意大利 Codice Fiscale:16 位字母数字混合结构——姓氏辅音 3 位、名字辅音 3 位、出生年 2 位、出生月 1 位字母(A–T 映射)、出生日 2 位(女性加 40)、市镇代码 4 位、校验字符 1 位。
除表中列举的证件外,pii_i18n.py还包含validate_uk_nhs_number、validate_australian_medicare、validate_ontario_health_card、validate_bc_phn等医疗健康证件验证器——源码 docstring 明确指出,NHS 号码、澳大利亚 Medicare 卡号、安大略省 OHIP、BC 省 PHN 等直接等同于患者健康标识符,应按 PHI 对待。所有语言特定模式经get_patterns_for_language与语言无关的通用模式(邮箱、URL、IP、MRZ、USCC、Aadhaar、印度健康 ID 等)合并后统一生效,并映射到 OpenMed 的CANONICAL_LABELS(ID_NUM、SSN),与其他标识符走相同的策略动作进行脱敏。
locale 替换数据的映射细节
lang与locale是两套独立机制,对应源码中两个不同模块的职责:
lang决定检测侧(模型 + 模式),由 openmed/core/pii_i18n.py 与 model_registry.py 负责;locale决定替换侧(假数据形状),由 openmed/core/anonymizer/locales.py 负责:该模块把 OpenMed 的 ISO 639-1 语言代码解析为最合适的 Faker locale。
值得注意的映射决策(源码 docstring 有明确记录):
- 葡萄牙语默认
pt_PT,如需巴西风格假数据须显式传locale="pt_BR"(对 CPF/CNPJ 场景尤其重要); - 阿拉伯语默认
ar_EG,区域标签ar-DZ、ar-MA会选择已安装的区域 Faker 后端,不可用时回退ar_EG并发出一次性警告;AR_REGION_LOCALES还登记了ar-SA、ar-AE、ar-JO、ar-PS等区域变体; - 中文解析为
zh_CN,使 PERSON/FIRST_NAME/LAST_NAME 使用"姓氏感知、仅汉字"的替代值生成器,而非拉丁回退; - 部分语言只有近似 locale:Faker 没有泰卢固语 locale,因此
te映射到en_IN并警告一次(见_APPROXIMATE_LOCALES);阿非利卡语af以nl_NL为运行时后端、阿姆哈拉语am以en_KE为后端,但其"概念 locale"的精选本土数据仍通过语言包提供; - 法语/葡萄牙语的非洲区域概念 locale(
fr_SN、fr_CI、fr_CM、pt_MZ、pt_AO)使用精选的各国本土假数据,未覆盖的 Faker 方法则委托给fr_FR/pt_PT(见CONCEPTUAL_LOCALE_LANGUAGES与FAKER_BACKEND_LOCALE); - 泰米尔语解析到原生
ta_IN,PERSON 替代值保留原文"首字母 + 名字"的父名首字母形态;越南语解析到原生vi_VN,姓名与地址假数据保留声调符号。
这些映射有测试约束兜底:locales.py的 docstring 记录了回归契约 OM-135——每个SUPPORTED_LANGUAGES语言码都必须在 Faker 中存在对应 locale(或为文档化的近似 locale),每个带验证器的证件号语言都必须出现在NATIONAL_ID_PROVIDERS中且生成的假值能通过该语言的验证器回环校验,仅文档化的近似映射允许发出UserWarning。
与其他 OpenMed 能力衔接
多语言去标识化不是孤岛,可与 OpenMed 的既有能力组合使用:
- 核心去标识化:
deidentifying-clinical-text技能覆盖的方法、阈值、keep_mapping、策略等,全部接受lang/locale参数; - 假数据生成:
generating-synthetic-surrogates技能讲解 locale 本土化假值与各语言自定义 provider; - 隐私策略:
configuring-privacy-policies技能中的policy=对任意lang生效; - 审计:
auditing-deidentification-runs技能会在无 PHI 审计报告中记录所用模型与语言; - 其他调用面:MCP 工具
openmed_deidentify/openmed_list_pii_languages,以及 REST 端点POST /pii/deidentify(两者均接受语言参数)。
上述技能文档分别位于 skills/deidentifying-clinical-text/SKILL.md、skills/generating-synthetic-surrogates/SKILL.md、skills/configuring-privacy-policies/SKILL.md、skills/auditing-deidentification-runs/SKILL.md。
边缘情况与陷阱
- 绝不要用英语模型处理其他语言:召回会显著下降。默认模型仅面向英语,务必显式传
lang=。 lang≠locale:lang选择检测模型与模式,locale决定替换假值形状。当替代值真实性重要时两者都要设(如lang="pt", locale="pt_BR")。- 部分 locale 是近似映射:如泰卢固语
te→en_IN(Faker 无泰卢固语 locale,会警告一次),如需更贴近区域的替代值请覆盖locale=。 - 日期顺序因语言而异:日优先语言(fr、de、it、es、nl、pt 等)会把
11/04/1979解析为 4 月 11 日;日期移位逻辑是语言感知的,移位日期时务必保持lang设置。 - 混合语言病历:如西班牙语病历中出现英语标题,可能降低召回;用
audit=True复核残余风险,必要时做二次处理。 - 日志安全:无论何种语言,日志中只记录偏移量、标签与哈希,绝不记录原始 PHI。
标准与合规参考
- HIPAA 去标识化标准 45 CFR 164.514(b)(美国),以及面向欧盟数据主体的 GDPR 与各成员国数据保护机构(DPA)要求;
- 各国证件号格式与校验规则由 OpenMed 验证器内置实现,不捆绑外部注册表;
- 核心源码入口:
openmed/core/pii_i18n.py(SUPPORTED_LANGUAGES、get_patterns_for_language、各国验证器)、openmed/core/model_registry.py(get_pii_models_by_language、get_default_pii_model)、openmed/core/anonymizer/locales.py(LANG_TO_LOCALE与 locale 近似映射)、openmed/core/language_pack_catalog.py(语言包目录与默认模型)。
需要进一步阅读时,可参考 skills/deidentifying-clinical-text/SKILL.md 掌握方法、阈值与策略配置,参考 skills/generating-synthetic-surrogates/SKILL.md 深入 locale 本土化假数据生成,并通过 openmed/core/anonymizer/locales.py 与 openmed/core/pii_i18n.py 直接查看完整的语言映射表与验证器实现。
【免费下载链接】openmedLocal-first healthcare AI: clinical NER & HIPAA PII de-identification that runs 100% on-device. 2,200+ medical models, 21 languages, Apple MLX + Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考