OpenMed 仓库工程指南深度解读:从模块组织到发布守门人的完整开发规范
2026/9/17 2:24:47 网站建设 项目流程

OpenMed 仓库工程指南深度解读:从模块组织到发布守门人的完整开发规范

【免费下载链接】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 仓库根目录下的 AGENTS.md 为核心,系统拆解一个面向医疗本地化 AI 项目(临床 NER 与 HIPAA PII 去标识化,100% 端侧运行)的工程纪律体系:目录如何分层、构建与测试如何跑、Ruff/swift-format 如何统一格式、隐私与本地优先如何内建为架构红线、PyPI 发布如何被守门人保护,以及提交与 PR 如何保持干净。读者完成后将掌握一套可直接复用的"可审计、可发布、可协作"的医疗 AI 仓库工程化模板。

一、为什么一份仓库指南值得成为开发契约

OpenMed 是一个 Apache-2.0 协议、以"本地优先(local-first)"为第一原则的医疗 AI SDK,核心业务是临床命名实体识别(NER)与 PHI/PII 去标识化,且所有推理路径均承诺"患者数据不出网络"。这类项目有一个天然矛盾:既要快速迭代 AI 能力,又不能在任何环节泄漏敏感数据或破坏发布可审计性

AGENTS.md 正是为解决这一矛盾而存在的开发契约。它并非普通的贡献说明,而是同时面向人类开发者与 AI 编码 Agent 的"仓库宪法",覆盖五个关键维度:

  • 代码落点:新能力应该放进哪个包;
  • 质量闸门:提交前必须跑哪些命令、过哪些检查;
  • 隐私红线:日志、缓存、审计工件中禁止出现什么;
  • 发布守门:PyPI 发布流程有哪些不可绕过的配置约束;
  • 协作纪律:分支命名、提交信息、PR 内容与文件跟踪的边界。

下文将逐节展开,并对照仓库中的 Makefile、pyproject.toml、.pre-commit-config.yaml 与 .github/workflows/publish.yml 等实际文件给出可验证依据。

二、模块组织:代码应该落在哪里

AGENTS.md 第一条规则是"结构即架构"。核心 Python 包代码位于openmed/下,并给出明确的落点矩阵:

能力类别落点目录说明
隐私与注册表存量代码openmed/core/保持现有隐私/注册代码,不迁移
全新能力clinical/eval/multimodal/structured/risk/interop/顶层包,新增能力优先按领域归位
后端适配器mlx/coreml/torch/对应 Apple MLX、CoreML 与 PyTorch 三种推理后端
REST 服务面service/含 gRPC/GraphQL 等接口层
Swift 代码与演示swift/OpenMedKit 及其 Demo
测试tests/unittests/integrationtests/fixtures三级测试体系
文档与示例docs/examples/用户文档与可运行示例
发布与维护脚本scripts/含 release、security、docs 等子目录

对照仓库实际结构,openmed/下确实存在 clinical/、eval/、multimodal/、structured/、risk/、interop/、mlx/、coreml/、torch/、service/ 等目录,与指南一一对应。这套规则的用意很直接:医疗领域能力按域隔离,后端实现按运行时隔离,任何人打开仓库都能在 10 秒内定位一个功能属于哪里

三、构建、测试与开发命令:一套可复现的环境

AGENTS.md 给出的命令全部围绕uv生态展开,核心命令如下:

# 安装可编辑包(含测试与 lint 依赖) uv pip install -e ".[dev]" # 模型相关工作额外叠加 Hugging Face 依赖 uv pip install -e ".[dev,hf]" # 提交 PR 前运行完整测试套件 .venv/bin/python -m pytest tests/ -q # 本地覆盖率 pytest --cov=openmed --cov-report=term-missing # 构建 wheel 与 sdist make build # 预览 / 严格构建 MkDocs 文档 make docs-serve make docs-build # Swift 包测试(OpenMedKit) cd swift/OpenMedKit && swift test

仓库实际把上述命令收口进了 Makefile:make install执行uv sync --frozen --extra dev(锁定 uv.lock 的冻结安装)、make test执行冻结环境下的 pytest、make docs-servemkdocs serve -a 127.0.0.1:8008起本地热重载文档服务。这种"命令 → Makefile 目标 → CI 同一入口"的做法,保证了本地与 CI 行为完全一致。

值得注意的是 docs/contributing.md 补充了 uv 不可用时的 pip 回退路径:创建普通虚拟环境后执行python3 -m pip install -e ".[dev]",但仓库默认且推荐的唯一标准环境是 uv 冻结环境(uv sync --frozen会严格校验uv.lock与 pyproject.toml 的一致性,对应 Makefile 的make lock-check目标)。

四、Lint 与格式化:单一事实来源

AGENTS.md 对格式化的要求是强制的:以仓库内检入的工具链为唯一事实来源,禁止使用编辑器自定义格式或替代 lint 配置。具体分工如下:

4.1 Python:Ruff 全权负责

Python 的 lint、导入排序与格式化全部由 Ruff 通过pyproject.toml中的[tool.ruff]段、.pre-commit-config.yaml 与 CI lint job 统一管控。

提交涉及 Python 的 PR 前必须依次执行:

make format # 应用规范的 Ruff 导入排序与格式化 make lint # Ruff lint 检查(等价于 ruff check .) make format-check # 只检查不改动(等价于 ruff format --check .)

pyproject.toml 中的关键约束:target-version = "py310"line-length = 88,lint 仅选择E9(运行时错误级语法问题)、F63F7F82I(导入排序)规则集,fixable仅开放I(导入),语法类错误保持不可自动修复,必须人工处理。格式化风格为双引号、空格缩进、LF 行尾。

此外,Ruff 的导入排序将openmed声明为 known-first-party,且黑名单排除examples/notebooksopenmed/service/proto/generated(生成代码不参与格式检查)。

4.2 Swift:swift-format 独立治理

Swift 包的格式化与 Python 完全隔离。OpenMedKit 使用 Apple 官方swift-format,配置与脚本为:

  • .swift-format(仓库根配置)
  • scripts/format_swift.sh:对Package.swiftswift/OpenMedKit/Package.swiftswift/OpenMedKit/Sourcesswift/OpenMedKit/Tests递归执行swift format format --in-place --recursive --parallel --configuration
  • scripts/lint_swift.sh:同一路径集上执行swift format lint --strict

对应的 Make 目标为make format-swiftmake lint-swift。凡是改动Package.swiftswift/OpenMedKit的 PR,都必须跑这两条命令。

4.3 策略变更的同步义务

AGENTS.md 特别强调:任何 lint 策略变更,必须同步更新.editorconfig、Ruff 配置、pre-commit 钩子、Swift 格式化脚本、Make 目标、文档与 CI。一次策略变更需要说清楚三件事——本地命令是什么、CI 闸门是什么、开发者预期工作流是什么。这与 docs/contributing.md 中"不要运行 Black、isort、flake8"的禁令互为表里。

4.4 pre-commit 钩子与安全扫描

.pre-commit-config.yaml 展示了完整的本地质量网:

  • pre-commit-hooksv6.0.0:尾随空白、EOF 修复、YAML/TOML 校验、大文件上限(3000KB)、合并冲突检测、调试语句检测、LF 行尾统一;
  • ruff-pre-commitv0.15.22:ruff-check --fix+ruff-format
  • bandit1.9.4:仅扫描openmed/下的 Python,severity=high、confidence=medium;
  • gitleaksv8.30.1:基于.gitleaks.toml配置与.secrets.baseline基线扫描密钥。

这意味着一次本地 commit 就会经历格式、静态安全(bandit)与密钥泄露(gitleaks)三层拦截,符合 CONTRIBUTING.md 中"pre-commit 钩子同时运行 Gitleaks 密钥扫描"的描述。

五、编码风格与架构红线:隐私优先的硬约束

5.1 基础编码规范

  • Python 3.10+,4 空格缩进,88 字符行长;
  • 函数与模块snake_case,类PascalCase,常量UPPER_SNAKE_CASE
  • 公共 API 必须携带 Google 风格 docstring。

这条 docstring 要求并非空话:docs/contributing.md 记录了配套的自动化闸门scripts/check_public_api_docstrings.py(纯 stdlibast解析、不导入运行时)与tests/unit/test_public_api_docstrings.py(运行时校验openmed.__all__顺序与 docstring 覆盖率,函数与类覆盖率必须保持 100%)。同时 pyproject.toml 中[tool.mypy]py.typed标记说明openmed是带类型标注的包,mypy 按固定文件清单做作用域化类型检查。

5.2 本地优先与无 PHI 架构红线

AGENTS.md 用一组"硬默认值"定义了医疗 AI 的架构底线:

  • 无强制网络调用:模型下载之后,所有路径不得产生强制性网络请求;
  • 无默认遥测:默认关闭一切遥测;
  • 日志/缓存/临时文件/审计工件中禁止原始 PHI
  • 审计报告使用偏移量、哈希、来源证明与风险评分,而非明文标识符;
  • 核心依赖必须许可协议兼容:不得捆绑 GPL、source-available、专有协议、DUA 门控数据,以及 UMLS、SNOMED CT、CPT、MIMIC、i2b2、n2c2 等受限资产;
  • 受限集成必须放在可选用户密钥或进程外桥接之后

对照 pyproject.toml 可以看到这套约束的工程化落地:interop-gplextra 被定义为空列表,明确注释"SDC Micro/R(GPL-2.0)与 MedCAT/CogStack(Elastic License 2.0)单独安装,本 extra 显式选择仅进程内子进程桥接、不引入受限代码";email-msg-gplextra 同样注释"extract-msg 为 GPL-3.0,仅通过隔离的 stdin/stdout 子进程桥接调用"。Hatch 构建配置(pyproject.toml 的[tool.hatch.build])则精确列出随 wheel 分发的 JSON 数据资产,从构建层面杜绝受限数据混入。

六、测试与发布闸门:不只 F1 的隐私度量

pytest 的收集规则是test_*.py*_test.py(配置在 pyproject.toml 的[tool.pytest.ini_options],内置integrationslowcontractfuzzdoctest_examples五个 marker)。外部或端到端用例打@pytest.mark.integration,昂贵检查打@pytest.mark.slow,打包的测试必须通过 mock 或合成 fixture 保持离线可用。

针对隐私场景,AGENTS.md 提出"聚合 F1 不够"的度量观:凡触及隐私相关路径,必须补充或维护以下维度的测试与 fixture:

  • 直接标识符召回率(direct-identifier recall);
  • 关键泄露(critical leakage);
  • 跨度完整性(span integrity);
  • 确定性安全清扫(deterministic safety sweeps);
  • 日期移位(date shifting);
  • 替身一致性(surrogate consistency);
  • 多语言标识符(multilingual IDs);
  • 量化模型召回率差异(quantized-model recall deltas)。

这与 docs/contributing.md 中"触碰日志、文本处理、服务请求、PII 抽取或去标识化代码时必须运行pytest tests/unit/test_no_raw_text_logging.py"的要求互为补充。另有一条数据红线:提交的金标数据必须是合成的,DUA 数据集仅限 eval 使用且永不入库

七、PyPI 发布守门人:不可绕过的配置契约

AGENTS.md 用最长的篇幅(全文近四分之一的体量)约束 PyPI 发布,原因在于发布是可审计性的最终出口。核心事实如下:

7.1 发布机制与测试要求

openmed的 PyPI 发布是标签驱动的,通过 .github/workflows/publish.yml 触发(推送v*标签)。改动该 workflow 之前,必须先读 docs/release/trusted-publishing.md,并运行两个回归测试:

pytest tests/unit/test_publish_workflow_version.py -q pytest tests/unit/release/test_provenance_workflow.py -q

7.2 密钥作用域与环境绑定

  • PYPI_API_TOKENsecret 作用域限定在 GitHub 的pypienvironment;
  • 禁止删除 publish job 的environment: pypi块,除非同一变更中同时迁移密钥并更新发布测试与文档;
  • 禁止回退到无 token 的 Trusted Publishing,除非 PyPIopenmed项目已配置匹配的 trusted publisher(ownermaziyarpanahi、仓库openmed、workflowpublish.yml、environmentpypi)。

对照 publish.yml 源码可见:publishjob 确实声明environment: name: pypi,并通过pypa/gh-action-pypi-publish@v1.14.1password: ${{ secrets.PYPI_API_TOKEN }}上传。

7.3 失败模式的正确归因

AGENTS.md 明确了两类容易误判的失败:

  • invalid-publisher:当pypa/gh-action-pypi-publishpassword为空时回退到 Trusted Publishing 而发布方缺失,会产生该错误。这属于发布阻断性配置回归,不是临时的 PyPI 故障;
  • GitHub OIDC/SLSA 证明中断:这是独立问题。证明证据可以 best-effort(best-effort),但包构建、版本检查、twine check、工件上传、PyPI 发布必须全部通过,发布才算完成。

7.4 发布流水线的全景

从 publish.yml 可以看到完整发布拓扑:

  1. provenance job:复用 provenance.yml,构建、attest、校验发行物,需要id-token: writeattestations: write
  2. npm-verify job:校验 Python 版本(从openmed/__about__.py读取)、npm 版本(js/openmedkit-web/package.json)与 tag 版本三方一致,并执行npm cinpm auditnpm testnpm pack --dry-run
  3. publish job:在pypienvironment 中上传 wheel/sdist;
  4. npm-publish job:在npmenvironment 中发布,且对已发布版本做不可变校验(比对 gitHead、tarball digest、目录内容),已存在则跳过;
  5. evidence job:Sigstore 签名 + 离线验证 + 附加到 tagged release,验证失败的 bundle 绝不允许附加;
  6. sbom job:生成 CycloneDX SBOM(sbom.cdx.json,对应make sbom目标调用scripts/security/generate_sbom.py)并附加到 release。

发布过程同时体现了"fail-closed 与 fail-open 的正确分界":provenance 证明是continue-on-error(best-effort),但签名 bundle 的验证步骤故意不continue-on-error——"无法验证的 bundle 绝不允许附加到 release";SBOM 生成则声明 fail-open,"任何 hiccup 不得阻断一次本应成功的发布"。

八、提交与 PR 纪律:让历史可审计

8.1 提交信息与分支

  • 近期历史使用简洁的命令式提交,常用fix:前缀;
  • 提交与 PR 保持聚焦,只改请求范围内的内容;
  • 必须使用仓库所有者的 Git 身份;
  • 禁止在 issue 文本、分支名、提交信息、PR 标题/正文、label 中出现 assistant/tool/vendor 名称、co-author 尾注、生成页脚或 worker 归属;尤其永远不要在分支名、PR 标题/正文、issue 标题/正文、label 中出现codexclaude
  • 未被明确要求时,不得指派 issue 或 PR。

CONTRIBUTING.md 补充了分支命名模板:<type>/issue-<number>-<short-kebab-slug>,如docs/issue-280-maintainers

8.2 PR 模板要素

PR 必须遵循 .github/PULL_REQUEST_TEMPLATE.md,包含:描述、变更类型、已运行的测试、适用的文档/CHANGELOG 更新、依赖变更理由、关联 issue,以及 UI/文档变更的截图或示例输出。

8.3 lint 变更后的 PR 评审流程

AGENTS.md 专门辟出一节规定"lint 基线落地后如何评审既有 PR",这是一个极具实操价值的细节:

  • 禁止在陈旧分支上开始评审——必须先将分支 rebase/merge 最新master
  • 更新后只在分支上运行规范格式化,且只提交属于该 PR 实际范围的文件
  • 禁止在更新master之前对陈旧分支做广域格式化(会产生无谓 churn,加大评审难度);
  • 预期重叠 PR 只携带少量、仅限其已触碰文件的格式化 follow-up 提交,不得吞下完整基线 diff;
  • 若更新 PR 产生了范围外的纯格式化改动,停下来询问,不得擅自评审或提交;
  • 批准/合并他人 PR 前,验证:分支对 CI 足够新、相关 lint 命令通过、diff 中无无关格式化 churn。

8.4 文件跟踪与提交安全

AGENTS.md 对 git 操作采取审慎态度:

  • 除非用户明确要求,不得将未跟踪文件加入 git;
  • 绝不 force-add 或提交被忽略的文件/目录;
  • 只 stage 已跟踪文件或用户明确批准跟踪的文件;
  • 当文件处于未跟踪、被忽略、看似私有、生成物或超出请求范围时,一律不动;对是否 stage/commit/push 存在任何疑虑,停下来询问用户

这条规则与仓库只读的协作模型高度一致,也避免了 AI Agent 误提交.venv/、密钥文件或生成产物。

九、OpenMedKit 与多模态工作:双端同步演进

最后,AGENTS.md 对 Swift/Python 双端演进与多模态能力给出方向性约束:

  • Swift 与 Python 表面应协同演进,除非计划明确限定单一平台;
  • OpenMedKit 的优先级:端侧文档摄入(document intake)、OCR、PII 脱敏、结构化抽取、任务包(task packs)、模型目录/下载/缓存 UX;后续才是姿态、音频、语音与传感器管线;
  • 任何处于边界或医疗设备风格的功能必须呈现免责声明,且不得自动触发临床决策;
  • Apple Foundation Models 路径必须仅限端侧,拒绝任何面向 PHI 工作流的云端回退。

这条约束在仓库结构中有清晰映射:swift/OpenMedKit 的 40 个 Swift 源文件与 swift/OpenMedDemo、swift/OpenMedScanDemo 演示工程对应端侧摄入与扫描场景,android/openmedkit 的 55 个 Kotlin 源文件则验证了 Android 端的对等实现(仓库中还有 swift-kotlin-parity.md 文档佐证双端一致性策略)。

十、给 AI Agent 与人类协作者的执行清单

综合全文,无论是人类开发者还是接入仓库的 AI Agent,提交代码前都应依次完成:

  1. 定位落点:按模块组织矩阵确认新代码放进正确的包;
  2. 锁定环境uv sync --frozen --extra dev(需要模型工作时叠加--extra hf);
  3. 格式化与静态检查make formatmake lintmake type-checkmake format-check(Swift 改动追加make format-swiftmake lint-swift);
  4. 完整性测试.venv/bin/python -m pytest tests/ -q,隐私路径追加专项测试(no-raw-PHI logging、直接标识符召回、跨度完整性等);
  5. 提交纪律:命令式信息 +fix:风格前缀,遵守仓库所有者身份与禁用词清单,只 stage 已批准文件;
  6. 发布守门:若涉及 publish.yml 改动,先读 trusted-publishing.md 并跑两个 workflow 回归测试,绝不破坏environment: pypi绑定。

这套清单的价值在于:它把"医疗 AI 项目最不能出错的三件事——隐私、可审计性、可协作性"全部转译成了可执行、可被 CI 强制、可被测试验证的工程动作。任何希望构建"安全第一"的 AI 仓库的团队,都可以把 AGENTS.md 作为一份高完成度的参考蓝本。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询