每日一个开源项目(第129篇):OpenMed - 永不离开设备的医疗 NLP

引言

"临床数据永不离开设备。"

这是"每日一个开源项目"系列的第129篇文章 。今天的主角是 OpenMed------一个本地优先的医疗 AI 库,由 HuggingFace 研究员 Maziyar Panahi 开发,专门解决医疗场景下的隐私问题。

医疗 AI 的现状:绝大多数工具需要把患者数据发送到云端,换回结构化结果。这在合规层面是个持续的风险点------HIPAA、GDPR、各国的数据保护法规对患者数据的处理方式有明确约束,而"数据上云"本身就已经触碰了很多医疗机构的红线。

OpenMed 的设计方向是把处理能力搬到本地:1000 多个生物医学 NLP 模型,全部在设备上跑,不发出任何网络请求,支持从 Python 服务到 iOS App 的多种部署场景。

你将学到什么

  • OpenMed 的核心架构:为什么选择编码器 Transformer,而非生成式模型
  • 13 个临床 NLP 域:从疾病到基因组的 NER 覆盖
  • PII 脱敏的工程设计:如何覆盖全部 18 个 HIPAA Safe Harbor 标识符
  • 多平台支持:Python/MLX、Swift/OpenMedKit、Docker/FastAPI
  • v1.2.0 引入的零样本能力:ZeroShot NER 和关系抽取
  • 在 Apple Silicon 上的性能表现

前置知识

  • 了解基本的 NLP 概念(命名实体识别、Transformer)
  • 有 Python 使用经验
  • 对医疗数据隐私合规有基本了解(HIPAA、数据脱敏的背景)

项目背景

项目简介

OpenMed 是一套本地优先的医疗 AI 工具库,定位是"把临床文本变成结构化洞察,且数据全程不离开安全环境"。

它的核心不是生成式 AI,而是用编码器 Transformer(BERT、ELECTRA、DeBERTa 系列)做提取和分类。这个技术选型背后有具体原因:医疗场景里最常见的任务是"从文本里找到什么",而不是"生成新的文本"------识别病名、提取药物、定位患者 ID,这些任务用分类模型做更精准、更可控、也更容易审计。

arXiv 论文(2508.01630)报告在 12 个生物医学 NER 基准测试中 10 个达到 SOTA。

作者/团队介绍

  • 作者: Maziyar Panahi
  • 背景: HuggingFace 研究员,生物医学 NLP 领域,SpaCy 和 HuggingFace Transformers 社区贡献者
  • License: Apache-2.0
  • 最新版本: v1.5.5(2026年6月)

项目数据

  • ⭐ GitHub Stars: 2,800+
  • 🍴 Forks: 274+
  • 📦 HuggingFace 模型: 1,000+
  • 🌍 支持语言: 12 种
  • 📄 License: Apache-2.0

主要功能

核心作用

OpenMed 的工作流很直接:

markdown 复制代码
临床文本输入
      ↓
本地模型推理(BERT/ELECTRA/DeBERTa)
      ↓
    ┌─────────────────────────────────┐
    │  NER:识别疾病、药物、基因等实体  │
    │  PII 脱敏:检测并处理患者标识符   │
    │  关系抽取:实体间的语义关系       │
    └─────────────────────────────────┘
      ↓
结构化输出(数据全程不离开本地)

使用场景

  1. 临床文本结构化

    • 从病历、出院记录中抽取疾病名称、药物、解剖位置
    • 支持 13 个生物医学 NER 域:化学品、疾病、基因、蛋白质、物种、解剖、肿瘤学等
  2. 患者数据脱敏

    • 覆盖全部 18 个 HIPAA Safe Harbor 标识符
    • 支持遮蔽([NAME])、替换(Faker 合成假数据)、哈希、日期偏移四种处理方式
  3. iOS/macOS 医疗 App 开发

    • OpenMedKit Swift 包提供原生接口,PHI 数据不离开设备
    • v1.2.0 内置的 iOS Scan Demo:扫描 → OCR 审查 → 脱敏 → 临床抽取 → 导出,五步完整工作流
  4. 企业级医疗系统集成

    • Docker/FastAPI REST API,方便嵌入现有工作流
    • AWS SageMaker Marketplace 托管版本,sub-100ms 延迟端点

快速开始

安装

bash 复制代码
# CPU 版本
pip install openmed

# Apple Silicon(MLX 加速)
pip install openmed[mlx]

# CUDA GPU
pip install openmed[cuda]

基础 NER

python 复制代码
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 脱敏

python 复制代码
from openmed import deidentify

text = "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..."

批量处理

python 复制代码
from openmed import BatchProcessor

texts = [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

swift 复制代码
import OpenMedKit

let 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"}]

支持的 NER 模型

模型 检测域 参数量 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

项目详细剖析

架构设计:为什么是编码器,不是生成式 LLM

这是 OpenMed 最值得关注的技术选择。

生成式 LLM(GPT-4、Claude 等)在医疗文本问题上有一个根本性的问题:输出不可控。让生成式模型做 PII 检测,它可能会在某些情况下把患者姓名"生成"到输出里,或者幻觉出不存在的药物名称。

OpenMed 选择编码器 Transformer 做命名实体识别,本质上是一个分类问题:对每个 token 判断它属于什么类别。这类模型:

  • 输出是确定性的(给定输入,输出固定)
  • 不会幻觉(只做分类,不生成新 token)
  • 参数量小(33M-568M),本地推理可行
  • 可以精确审计(每个实体都有来源位置)

对医疗场景来说,这些特性比"能生成流畅文本"重要得多。

Privacy Filter 架构

OpenMed 的 PII 检测不只是跑一个 NER 模型,还有几层工程处理:

上下文感知检测 :在实体前后 100 个字符范围内做关键词增强。SSN: 后面跟着数字序列,置信度比单纯的数字序列高得多。

校验和验证:减少误报。

  • 美国社保号(SSN):格式验证
  • 印度 Aadhaar:Verhoeff 校验算法
  • 巴西 CPF/CNPJ:Luhn 校验
  • 意大利 Codice Fiscale:格式 + 字母校验
  • 德国 Steuer-ID:格式验证

Smart Entity Merging:解决子词分词器的分片问题。BERT 类模型会把 "O'Brien" 切成 "O", "'", "Brien",实体合并逻辑把这些片段重新拼回完整实体,避免输出残缺的 PII 检测结果。

三种 Privacy Filter 变体

  • 基础版:通用 PII 检测
  • Nemotron 微调版:更高精度
  • 多语言版(v1.4.0):支持 16 种语言的统一模型

多平台运行时

bash 复制代码
┌─────────────────────────────────────────────────┐
│                  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)

v1.2.0 版本引入了零样本接口,不再要求用预定义的实体类别:

python 复制代码
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
python 复制代码
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 微调:

  • 预训练数据:350K 段落的生物医学语料库
  • LoRA 微调:只更新不到 1.5% 的参数
  • 训练时间:单块 GPU,12 小时内完成
  • 碳排放:整个训练过程低于 1.2 kg CO₂e

这个数据对想在自己数据集上微调的用户有参考意义:不需要多卡集群,一块消费级 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 翻译

项目地址与资源

官方资源

参考标准

  • HIPAA Safe Harbor(18 个患者标识符)
  • OWASP 医疗数据安全
  • STRIDE 威胁建模(Privacy Filter 安全设计)

总结

OpenMed 解决的问题有明确的边界:医疗 NLP,且数据不能离开本地。

这个约束在很多行业是选择,在医疗行业经常是法规要求。OpenMed 把解法做成了库------编码器模型做分类、MLX 做本地加速、Swift 包做移动端原生集成、校验和逻辑减少误报、Smart Entity Merging 处理分词碎片。每一层都在处理医疗场景里真实存在的工程问题。

对于在做医疗 AI 应用的开发者,或者在研究临床文本处理的研究者,OpenMed 是目前开源生态里覆盖最全的本地化方案之一。即使不是医疗场景,它的 PII 脱敏能力和多语言支持,在金融、法律等同样有数据敏感性要求的领域也有直接的参考价值。


探索 PrimeSkills ------ 精选 AI Agent 与技能的市场,每一个都经过真实企业工作流验证,去掉浮夸,留下真正有用的。

欢迎访问我的个人主页,发现更多有价值的见解和有趣的产品。

相关推荐
冬奇Lab1 小时前
Agent 系列(19):Harness 完整体系——8 层防护框架全景
人工智能·llm·agent
米小虾1 小时前
Claude Fable 5 系统提示词被扒出来了:1586 行代码背后,藏着 AI 产品工程的终极哲学
人工智能·agent
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【77】执行取消
java·人工智能·spring
Teacher.chenchong1 小时前
AI-Agent2.0 科研全链路实战营:LLM+NotebookLM + 自动化编程 + 文献管理 + 论文写作,搭建本地科研智能体
人工智能·自动化
weberCd2 小时前
ChatGPT 实用技巧总结(国内)
人工智能·chatgpt
我爱cope2 小时前
【Agent智能体26 | 多智能体-多智能体工作流】
人工智能·设计模式·语言模型·职场和发展
设计师小聂!2 小时前
宝塔 Linux 面板保姆级教程
linux·mysql·开源·运维开发
吴佳浩2 小时前
炸裂!!!给 codeX 装上本地大脑:cc-switch_Ollama 接入全记录
人工智能·rust·openai
一拳小和尚LXY2 小时前
AI 模型 API 对接方案对比:统一网关 vs 直连厂商,2026 年选型指南
人工智能