OpenMed 多语言临床关系抽取实战:基于 CMeIE 44 谓词与印地语子集的确定性关系解码
【免费下载链接】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 提供一套确定性(deterministic)的多语言临床关系抽取能力:在中文(zh)与印地语(hi)两种语言上,从已经抽取好的 NER 实体跨度(spans)出发,抽取"疾病—治疗""病因""并发症"等临床关系,全程不运行也不训练第二个 NER 模型。候选层基于字符偏移(character offsets)而非空白分词,因此无需额外分词器即可覆盖无空格书写的汉语与天城文(Devanagari);随后这些带类型的有向边会被送入与其它关系后端共享的受限 span-graph 解码器完成筛选。读完本文,你将掌握extract_relations()的调用方式、CMeIE 44 个中文谓词与印地语 8 个关系族的规范标签体系、断言(assertion)传播规则,以及如何在per_language粒度上评测中印关系抽取的 strict / relaxed F1。
一、核心思路:不新增 NER,只做"跨度之上"的关系解码
多语言关系抽取的关键设计原则记录在 multilingual-relations.md 中,并在源码 openmed/clinical/relations/multilingual.py 的模块 docstring 里再次强调:
版本化注册表把 44 个 CMeIE 谓词和一个聚焦的印地语子集映射到 OpenMed 规范关系标签。抽取复用已有 NER 跨度,构造与书写体系无关(script-agnostic)的字符偏移候选,并把选择工作委托给共享的 span-graph 解码器。
这意味着:
- 输入只有两样东西:原文文本 + 一批带
label与字符偏移start/end的 NER 跨度; - 不做第二个命名实体识别、不做词级 tokenize;
- 中英文之间不存在共享的空格边界假设,天然适配中文(字间无空格)与印地语(Devanagari 连续书写)。
最小可用示例
原文档给出的最小示例可以直接运行(依赖openmed.clinical包):
from openmed.clinical import extract_relations text = "肺炎使用阿莫西林治疗。" spans = [ {"label": "CONDITION", "start": 0, "end": 2}, {"label": "MEDICATION", "start": 4, "end": 8}, ] relations = extract_relations(text, spans, language="zh") print(relations[0].to_dict())输出保留关系的两个参数(head / tail)及其原始字符偏移,to_dict()返回确定性的字典表示。由 multilingual.py 可知每个关系对象MultilingualRelation携带:type、head、tail、score、language、source_relation、assertion_status,以及一条固定的advisory提示——关系抽取是辅助性支持(assistive support),临床使用前必须经过人工验证。
extract_relations()的完整签名与参数含义(见 multilingual.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
text | — | 原始临床文本 |
spans | — | 已有 NER 跨度(含字符偏移) |
language | — | zh(CMeIE 清单)或hi(印地语子集) |
min_score | 0.5 | 确定性候选的最低得分门槛 |
asserted_only | True | 为真时剔除 refuted(否定)与 conditional(条件/假设)关系 |
语言代码经过归一化:_language_code()会把"zh-CN"、"zh_CN"等写法折叠为"zh"(见 multilingual.py),所以传入language="zh"或language="hi"之外的注册语言会抛出ValueError并列出受支持语言。
二、版本化注册表:CMeIE 44 谓词与印地语子集
注册表版本由MULTILINGUAL_RELATION_REGISTRY_VERSION标记,当前为1(源码 multilingual.py 与单测 test_multilingual_relations.py 均断言其为1)。版本号机制保证:未来谓词集演进不会破坏基于旧版本抽取的下游管线。
2.1 中文:完整覆盖 CMeIE 44 个谓词
中文注册表保留 CMeIE 官方 schema 中全部 44 个不同谓词,并映射为稳定的 lower-snake-case 规范标签。注意 CMeIE 定义了 53 个"主语-谓语-宾语"schema,原因在于部分谓词允许多种实体类型配对(如drug_treatment的宾语既可以是药物也可以是其他治疗),但去重后的不同谓词只有 44 个。注册表只包含标签与类型兼容性信息——OpenMed 不捆绑 CMeIE 语料,数据边界与评测格式以官方 CBLUE 基准为准。
完整映射表(与 multilingual.py 中CMEIE_RELATION_MAPPING的插入顺序一致):
| CMeIE predicate | Canonical label | CMeIE predicate | Canonical label |
|---|---|---|---|
| 预防 | prevention | 内窥镜检查 | endoscopic_examination |
| 病理分型 | pathology_type | 病史 | history |
| 阶段 | stage | 筛查 | screening |
| 相关(导致) | causes | 遗传因素 | genetic_factor |
| 就诊科室 | care_department | 多发群体 | prevalent_population |
| 相关(转化) | transforms_to | 发病机制 | pathogenesis |
| 辅助治疗 | adjuvant_treatment | 发病率 | incidence |
| 相关(症状) | associated_symptom | 病理生理 | pathophysiology |
| 化疗 | chemotherapy | 发病年龄 | onset_age |
| 鉴别诊断 | differential_diagnosis | 药物治疗 | drug_treatment |
| 放射治疗 | radiation_treatment | 多发地区 | prevalent_region |
| 临床表现 | clinical_manifestation | 发病部位 | affected_body_site |
| 手术治疗 | surgical_treatment | 发病性别倾向 | sex_predisposition |
| 治疗后症状 | post_treatment_symptom | 转移部位 | metastasis_site |
| 实验室检查 | laboratory_test | 死亡率 | mortality |
| 侵及周围组织转移的症状 | tissue_invasion_symptom | 外侵部位 | external_invasion_site |
| 影像学检查 | imaging_test | 传播途径 | transmission_route |
| 病因 | etiology | 预后状况 | prognosis |
| 辅助检查 | auxiliary_examination | 多发季节 | prevalent_season |
| 高危因素 | high_risk_factor | 预后生存率 | survival_rate |
| 组织学检查 | histological_examination | 并发症 | complication |
| 风险评估因素 | risk_assessment_factor | 同义词 | synonym |
对应的实体类型边界由源码CMEIE_ENTITY_TYPES定义(疾病、症状、检查、药物、部位、手术治疗、其他治疗、预后、流行病学、社会学、其他),见 multilingual.py。
2.2 印地语:聚焦合成临床 fixture 覆盖的关系族
印地语子集覆盖了随仓库发布的合成临床 fixture 所涉及的关系族,共 8 个:
| Hindi relation | Canonical label |
|---|---|
| दवा उपचार | drug_treatment |
| शल्य उपचार | surgical_treatment |
| रोकथाम | prevention |
| नैदानिक अभिव्यक्ति | clinical_manifestation |
| कारण | etiology |
| जटिलता | complication |
| प्रयोगशाला जांच | laboratory_test |
| इमेजिंग जांच | imaging_test |
2.3 类型兼容性约束
每个规范关系标签都绑定"主语标签集合 → 宾语标签集合"的兼容矩阵(见_TYPE_COMPATIBILITY,multilingual.py)。几个有代表性的约束:
drug_treatment:主语为疾病类(CONDITION),宾语仅限MEDICATION;affected_body_site:宾语仅限BODY_SITE;surgical_treatment:宾语为PROCEDURE或OTHER;sex_predisposition:宾语为GENDER或OTHER;onset_age:宾语为AGE或OTHER;causes、associated_symptom、complication等疾病间关系的宾语为疾病/微生物/其他条件实体。
这些约束会在解码阶段以SpanGraphConstraints.type_compatibility的形式传入共享解码器,从结构上杜绝"疾病—药物"被错误标成causes这类非法配对。
三、候选构造:字符偏移、cue 与句内窗口
3.1 不依赖空白分词的候选层
build_relation_candidates()(candidate.py)明确注释:"构建有界图候选,无需词级分词(word tokenization)"。它对每个实体对计算字符距离(_character_distance),并用RelationCandidateRule中的cues(触发词)与实体标签过滤。关键参数(candidate.py):
max_character_distance:默认96个字符,超出即不生成候选;max_sentence_distance:默认0,即只在同一句内生成候选;传正数可开启有界的文档级配对;- 每个规则要求至少一个 cue,且 head/tail 标签集合非空。
单测 test_multilingual_relations.py 验证了中文候选生成的偏移保持性:对"肺炎使用阿莫西林治疗。",节点偏移精确保持为(0, 2)与(4, 8),且drug_treatment候选的character_distance元数据为2。
3.2 每种语言的 cue 触发词
_CUES_BY_LANGUAGE(multilingual.py)为中文与印地语分别维护触发词表;某个谓词若无专属 cues,则回退到源谓词本身(cues = cue_mapping.get(canonical_relation, (source_relation,)))。中文若干代表性 cues:
| 关系 | 中文 cues |
|---|---|
prevention | 预防、防止、疫苗 |
drug_treatment | 药物治疗、使用、服用、给予、用药 |
surgical_treatment | 手术治疗、手术、切除术、切除 |
clinical_manifestation | 临床表现、表现为、症状为 |
etiology | 病因、由于、引起、所致 |
complication | 并发症、并发 |
laboratory_test | 实验室检查、化验、检测 |
imaging_test | 影像学检查、影像、CT、MRI |
印地语侧对应रोकथाम / बचाव / टीका(预防)、दवा से उपचार / इलाज(药物治疗)、लक्षण(临床表现)、के कारण(病因)、सीटी / एमआरआई(影像学检查)等。
3.3 共享 span-graph 解码器
候选边(typed edges)随后进入openmed.core.decoding.decode_span_graph(),约束包括:
allowed_edge_labels:仅注册表中的规范关系标签;type_compatibility:上文的类型兼容矩阵;min_edge_score:来自extract_relations(min_score=…)。
测试 test_multilingual_relations.py 用patch(..., wraps=decode_span_graph)断言extract_relations恰好调用一次共享解码器,且对"阑尾炎需要手术切除。"正确解码出surgical_treatment——这证明多语言关系抽取与其它关系后端走的是同一套解码逻辑,只是候选与约束不同。
四、断言传播:否定、假设与不确定性如何被处理
4.1 语言对应的 ConText cue 包
中文抽取使用中文 ConText cue 包,印地语抽取使用印地语 cue 包(经resolve_span_context(..., language=code)解析,见 multilingual.py)。缺失 cue 时默认视为 recent(近期)、certain(确定)、affirmed(肯定);尤其重要的一点是:英文风格的记录标记不会否定一条中文或印地语关系——对应 fixture 明确声明 "An English record marker must not negate a Chinese relation" 且为zero_tolerance 陷阱。
4.2 断言状态与默认过滤
断言状态在 assertion_filter.py 定义并复用同一套 ConText 轴:
| 状态 | 触发条件 | 默认输出 |
|---|---|---|
confirmed | 两参数均被肯定 | 保留 |
possible | 任一参数不确定(uncertain) | 保留,供复核 |
conditional | 任一参数为假设/条件(hypothetical) | 默认剔除 |
refuted | 任一参数被否定(negated) | 默认剔除 |
状态优先级为 refuted > conditional > possible > confirmed。当asserted_only=True(默认)时,refuted 与 conditional 关系被从事实集中剔除;用asserted_only=False可以取回全部关系并查看其assertion_status。测试 test_multilingual_relations.py 验证:对"未见肺炎,使用阿莫西林治疗。",默认返回空元组(关系被正确否定),而asserted_only=False时保留的关系标记为refuted。
RelationAssertion还映射 FHIRverificationStatus(confirmed→confirmed、refuted→refuted、conditional/possible→provisional),并支持生成不含原文、只含偏移与内容哈希的审计条目(to_audit_entry(),见 assertion_filter.py),便于对接审计追踪与 FHIR 导出。
五、评测与金标准:合成 fixture 与 per_language F1
5.1 合成 fixtures
多语言关系的金标准 fixtures 全部为合成数据(metadata.synthetic: true),存放于:
- relations_zh.jsonl
- relations_indic.jsonl
每条 fixture 的结构(以relation-zh-drug-treatment为例):
{ "id": "relation-zh-drug-treatment", "schema_version": 1, "language": "zh", "text": "肺炎使用阿莫西林治疗。", "entities": [ {"id": "condition", "start": 0, "end": 2, "label": "CONDITION", "text": "肺炎"}, {"id": "medication", "start": 4, "end": 8, "label": "MEDICATION", "text": "阿莫西林"} ], "relations": [ {"id": "relation", "type": "drug_treatment", "head": "condition", "tail": "medication", "scope": "sentence"} ], "traps": [], "metadata": {"synthetic": true, "category": "relation_gold", "schema_version": 1, "registry_version": 1} }fixture 还支持zero_tolerance 陷阱(traps):例如relation-zh-english-no-assertion的 trap 断言"英文记录标记不得否定中文关系",任何违反都会直接判定失败(RELATION_TRAP_KINDS包括assertion与temporal,见 openmed/eval/suites/relations.py)。
5.2 评测入口与 per_language 指标
run_relation_benchmark()与ModelScorecard在relation_extraction.per_language下报告strict 与 relaxed F1(两者均在 openmed/eval/init.py 导出;strict/relaxed 的差异定义于 openmed/eval/relation_metrics.py,即关系参数匹配的严格与宽松模式)。这意味着中文与印地语的性能不会被聚合进一个笼统的关系分数里隐藏掉——任何回归都能在语言粒度上被精确定位。
金标准加载与评分链路:load_multilingual_relation_fixtures()读取上述两个 jsonl →score_relation_fixtures()按语言分组打分 → 输出metrics.by_language[zh|hi].strict.f1等指标(见 openmed/eval/suites/relations.py)。仓库内的提交级测试 test_multilingual_relations.py 断言:
- 金标准覆盖语言恰为
["hi", "zh"]; - 两种语言的strict F1 均不低于 0.60的下限;
- 所有 fixture 均为合成数据,且文本中不得出现
mimic / i2b2 / n2c2 / snomed / umls等受保护语料标记(同一文件),从测试层面杜绝了把真实受保护语料混入金标准的可能。
六、典型应用场景与注意事项
6.1 适用场景
- 中文电子病历的"疾病—治疗/检查"关系抽取:复用已有中文 NER 输出(CONDITION、MEDICATION、PROCEDURE、LAB_TEST 等标签),零额外模型成本获得 44 类关系;
- 印地语临床文本:覆盖 8 个高频关系族,适合资源受限的本地化部署;
- 本地优先(local-first)管线:整个流程确定性、无云端依赖,符合 OpenMed 医疗数据不出网络的部署形态。
6.2 注意事项
- 辅助性质:
MultilingualRelation.to_dict()自带 advisory 字段,明确提示"临床使用前必须验证抽取结果"; - 语言边界:仅支持
zh与hi;其他语言调用relation_type_mapping()会抛出ValueError(可用available_multilingual_relation_languages()查询注册语言,见 multilingual.py); - 句内默认:
max_sentence_distance=0默认只配对同一句内的实体,跨句关系需显式提升该窗口; - 语料边界:注册表只携带标签与类型兼容信息,不包含 CMeIE 语料本体,评测请以官方 CBLUE 基准的数据边界为准。
6.3 快速自检命令
如需在本地快速验证多语言关系抽取,可直接运行单元测试套件:
python -m pytest tests/unit/clinical/test_multilingual_relations.py -v它会覆盖注册表映射完整性(44 个中文谓词 + 8 个印地语关系)、字符偏移保持、共享解码器复用、非英语上下文断言、中文否定传播以及 per_language strict F1 下限等关键行为。
【免费下载链接】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),仅供参考