《猫猫钓游记》可爱+收集+钓鱼游戏试玩
2026-06-30
2026-07-03 0
这是"每日一个开源项目"系列的第129篇文章。今天的主角是 OpenMed——一个本地优先的医疗 AI 库,由 HuggingFace 研究员 Maziyar Panahi 开发,专门解决医疗场景下的隐私问题。

医疗 AI 的现状:绝大多数工具需要把患者数据发送到云端,换回结构化结果。这在合规层面是个持续的风险点——HIPAA、GDPR、各国的数据保护法规对患者数据的处理方式有明确约束,而"数据上云"本身就已经触碰了很多医疗机构的红线。
OpenMed 的设计方向是把处理能力搬到本地:1000 多个生物医学 NLP 模型,全部在设备上跑,不发出任何网络请求,支持从 Python 服务到 iOS App 的多种部署场景。
OpenMed 是一套本地优先的医疗 AI 工具库,定位是"把临床文本变成结构化洞察,且数据全程不离开安全环境"。
它的核心不是生成式 AI,而是用编码器 Transformer(BERT、ELECTRA、DeBERTa 系列)做提取和分类。这个技术选型背后有具体原因:医疗场景里最常见的任务是"从文本里找到什么",而不是"生成新的文本"——识别病名、提取药物、定位患者 ID,这些任务用分类模型做更精准、更可控、也更容易审计。
arXiv 论文(2508.01630)报告在 12 个生物医学 NER 基准测试中 10 个达到 SOTA。
OpenMed 的工作流很直接:
临床文本输入
↓
本地模型推理(BERT/ELECTRA/DeBERTa)
↓
┌─────────────────────────────────┐
│ NER:识别疾病、药物、基因等实体 │
│ PII 脱敏:检测并处理患者标识符 │
│ 关系抽取:实体间的语义关系 │
└─────────────────────────────────┘
↓
结构化输出(数据全程不离开本地)
临床文本结构化
患者数据脱敏
[NAME])、替换(Faker 合成假数据)、哈希、日期偏移四种处理方式iOS/macOS 医疗 App 开发
企业级医疗系统集成
安装:
# CPU 版本
pip install openmed# Apple Silicon(MLX 加速)
pip install openmed[mlx]# CUDA GPU
pip install openmed[cuda]
基础 NER:
from openmed import analyze_text# 疾病识别
result = analyze_text(
"Patient started on imatinib for CML.",
model_name="disease_detection_superclinical"
)
# 输出:{entities: [{text: "CML", label: "DISEASE", start: 30, end: 33}], ...}# 药物识别
result = analyze_text(
"Prescribed metformin 500mg twice daily for type 2 diabetes.",
model_name="pharma_detection_superclinical"
)
PII 脱敏:
from openmed import deidentifytext = "Patient John Smith (DOB: 1985-03-15, SSN: 123-45-6789) was admitted..."# 遮蔽模式
result = deidentify(text, method="mask")
# "Patient [NAME] (DOB: [DATE], SSN: [SSN]) was admitted..."# Faker 替换(保持文本可读性,同时完全匿名化)
result = deidentify(text, method="replace")
# "Patient Michael Johnson (DOB: 1972-08-22, SSN: 987-65-4321) was admitted..."
批量处理:
from openmed import BatchProcessortexts = [record1, record2, record3, ...]processor = BatchProcessor(
operation="extract_pii",
model_name="pii_superclinical_large",
on_progress=lambda p: print(f"{p:.0%} complete")
)
results = processor.run(texts)
Swift/iOS:
import OpenMedKitlet analyzer = OpenMedNER(model: .diseaseDetectionSuperClinical)
let result = try await analyzer.analyze("Patient presents with hypertension and T2DM")
// result.entities: [{text: "hypertension", label: "DISEASE"}, {text: "T2DM", label: "DISEASE"}]
| 模型 | 检测域 | 参数量 | HuggingFace 下载量 |
|---|---|---|---|
disease_detection_superclinical | 疾病/症状 | 434M | 104K |
pharma_detection_superclinical | 药物/化合物 | 434M | — |
pii_superclinical_large | PII 标识符 | 434M | — |
chemical_detection_electramed | 化学品 | 33M | 117K |
anatomy_detection_electramed | 解剖部位 | 109M | — |
genomic_detection_pubmed | 基因/基因组 | 109M | 103K |
oncology_detection_multimed | 肿瘤学实体 | 568M | 102K |
这是 OpenMed 最值得关注的技术选择。
生成式 LLM(GPT-4、Claude 等)在医疗文本问题上有一个根本性的问题:输出不可控。让生成式模型做 PII 检测,它可能会在某些情况下把患者姓名"生成"到输出里,或者幻觉出不存在的药物名称。
OpenMed 选择编码器 Transformer 做命名实体识别,本质上是一个分类问题:对每个 token 判断它属于什么类别。这类模型:
对医疗场景来说,这些特性比"能生成流畅文本"重要得多。
OpenMed 的 PII 检测不只是跑一个 NER 模型,还有几层工程处理:
上下文感知检测:在实体前后 100 个字符范围内做关键词增强。SSN: 后面跟着数字序列,置信度比单纯的数字序列高得多。
校验和验证:减少误报。
Smart Entity Merging:解决子词分词器的分片问题。BERT 类模型会把 "O'Brien" 切成 ["O", "'", "Brien"],实体合并逻辑把这些片段重新拼回完整实体,避免输出残缺的 PII 检测结果。
三种 Privacy Filter 变体:
┌─────────────────────────────────────────────────┐
│ OpenMed 运行时 │
├──────────────┬──────────────┬───────────────────┤
│ Python/MLX │ Swift │ Docker/FastAPI │
│ │ OpenMedKit │ │
│ • CPU │ • macOS │ • REST API │
│ • CUDA │ • iOS │ • 批量处理端点 │
│ • Apple MLX │ • iPadOS │ • 模型生命周期管理│
│ │ │ /models/loaded │
│ 24-33x │ PHI 不离 │ /models/unload │
│ vs CPU PyTorch│ 开设备 │ keep_alive 控制 │
└──────────────┴──────────────┴───────────────────┘
↑ ↑
共享 MLX 模型文件(含 8-bit 量化版)
Swift 和 Python 路径共享同一套 MLX 模型文件,这意味着同一个医院系统可以用 Python 服务跑服务端推理,同时用 OpenMedKit 在 iPad 上跑本地推理,模型文件不需要维护两套。
v1.2.0 版本引入了零样本接口,不再要求用预定义的实体类别:
from openmed import zero_shot_ner# 不用预训练的医疗 NER 模型,用自定义的类别标签
result = zero_shot_ner(
text="The patient's creatinine level was 2.3 mg/dL, suggesting CKD.",
labels=["LAB_VALUE", "UNIT", "CONDITION"]
)
# 能识别 "2.3 mg/dL" 为 LAB_VALUE,"CKD" 为 CONDITION
from openmed import extract_relations# 抽取实体间的语义关系
relations = extract_relations(
text="Metformin was prescribed for type 2 diabetes.",
entity_pairs=[("DRUG", "DISEASE")]
)
# [{drug: "Metformin", relation: "prescribed_for", disease: "type 2 diabetes"}]
对于不在预定义 NER 模型覆盖范围内的临床实体,零样本接口提供了一个灵活的出口。
OpenMed 的模型训练用了领域自适应预训练(DAPT)加 LoRA 微调:
这个数据对想在自己数据集上微调的用户有参考意义:不需要多卡集群,一块消费级 GPU 加几个小时就能完成。
| 版本 | 时间 | 核心变化 |
|---|---|---|
| v0.x | 2025年下半年 | 初期开发,基础 NER |
| v1.0.0 | 2026年4月 | 首个稳定版,MLX 后端,Swift 包 |
| v1.2.0 | 2026年4月 | 零样本 NER/分类/关系抽取,iOS Scan Demo |
| v1.4.0 | 2026年5月 | 多语言 Privacy Filter,16 种语言 |
| v1.5.0 | 2026年5月 | 阿拉伯语/日语/土耳其语 PII,247 个模型 |
| v1.5.2 | 2026年5月 | 安全加固,trust_remote_code 默认 False |
| v1.5.5 | 2026年6月 | 批量 PII,REST 生命周期管理,13 个 README 翻译 |
OpenMed 解决的问题有明确的边界:医疗 NLP,且数据不能离开本地。
这个约束在很多行业是选择,在医疗行业经常是法规要求。OpenMed 把解法做成了库——编码器模型做分类、MLX 做本地加速、Swift 包做移动端原生集成、校验和逻辑减少误报、Smart Entity Merging 处理分词碎片。每一层都在处理医疗场景里真实存在的工程问题。
对于在做医疗 AI 应用的开发者,或者在研究临床文本处理的研究者,OpenMed 是目前开源生态里覆盖最全的本地化方案之一。即使不是医疗场景,它的 PII 脱敏能力和多语言支持,在金融、法律等同样有数据敏感性要求的领域也有直接的参考价值。
探索 PrimeSkills —— 精选 AI Agent 与技能的市场,每一个都经过真实企业工作流验证,去掉浮夸,留下真正有用的。
欢迎访问我的个人主页,发现更多有价值的见解和有趣的产品。