OpenMed 多模态弃权原因(Abstention Reasons):PHI 安全的元数据级处理中止契约
OpenMed 多模态弃权原因Abstention ReasonsPHI 安全的元数据级处理中止契约【免费下载链接】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/openmedOpenMed 的图像、文档、波形与音频流水线在拒绝继续处理时需要向调用方说明处理为什么停止同时又绝不能把 OCR 文本、转录稿、像素数据或 DICOM 值带入日志与审计产物。AbstentionRecord正是为这条边界设计的稳定、纯元数据契约序列化形态仅包含 schema 版本、流水线阶段与一个稳定的原因码。读完本文你将掌握如何在 OpenMed 多模态流水线中构造、解析与聚合弃权记录理解其 fail-closed失败即拒绝的严格校验语义并能在自己的批处理任务中安全地记录为什么中止而不泄漏任何患者数据。为什么需要弃权记录而不是自由文本错误在多模态脱敏流水线中处理中断的原因千差万别容器格式不受支持、字节流损坏、资源超限、OCR 质量过低、模型对 PHI 判定的置信度不足……如果让各模块用自由文本记录这些原因日志里很容易混入原始内容——一段 OCR 出来的患者姓名、一句转录的对话、一个 DICOM 标签值都会让已脱敏的承诺失效。OpenMed 的做法是在 openmed/multimodal/abstention.py 中定义AbstentionRecord其模块 docstring 明确说明设计意图The boundary in this module deliberately accepts only a stage and a reason code. It has no free-text field, so callers cannot accidentally serialize OCR text, transcripts, DICOM values, file paths, URLs, or model prompts while explaining why processing stopped.即类型层面就禁止携带任何自由文本从结构上杜绝意外泄漏。快速上手构造并序列化一条弃权记录与文档中的示例一致直接从公开 API 导入即可使用from openmed.multimodal.abstention import ( AbstentionReason, AbstentionRecord, AbstentionStage, ) record AbstentionRecord( stageAbstentionStage.INFERENCE, reasonAbstentionReason.PHI_UNCERTAINTY, ) print(record.to_json())输出为确定性的、紧凑的 JSON{schema_version:1,stage:inference,reason:phi_uncertainty}从源码实现看openmed/multimodal/abstention.pyto_json()使用ensure_asciiTrue与separators(,, :)进行序列化字段顺序固定为schema_version→stage→reason保证同一记录在任何环境、任何时刻序列化结果完全一致——这一点对审计与去重至关重要。AbstentionRecord是一个dataclass(frozenTrue, slotsTrue)不可变且内存紧凑字段为字段类型说明stageAbstentionStage处理停止的流水线阶段reasonAbstentionReason该阶段合法的稳定原因码schema_versionint序列化契约版本当前仅接受1ABSTENTION_SCHEMA_VERSION 1严禁附加的字段弃权记录有意不包含message 或 context 字段。不要在此记录旁附加OCR 文本、转录稿、像素数据、DICOM 值文件路径、URL、提示词prompt上游提供商的错误原文运营层面的细节应放入独立的私有系统中并为其配置与 PHI 相匹配的保留与访问策略参见 docs/compliance/audit-envelopes.md、docs/security/audit-retention.md 等治理文档了解审计边界。阶段与允许的原因码一张封闭的契约表每个AbstentionStage只允许一组固定的原因码任何阶段-原因组合都必须落在表中否则构造即失败阶段允许的原因码preflightunsupported_media、resource_limit、provider_unavailabledecodemalformed_media、resource_limit、low_qualityinferenceresource_limit、low_quality、phi_uncertainty、speaker_uncertainty、temporal_instability、provider_unavailablepost_processresource_limit、low_quality、phi_uncertainty、speaker_uncertainty、temporal_instability这份表在源码中由_ALLOWED_REASONS常量精确实现openmed/multimodal/abstention.py每个阶段映射到一个frozenset。八个原因码的语义原因码典型触发场景unsupported_media容器/媒体类型不受支持如未知扩展名或无法识别的封装格式malformed_media字节流损坏、头部非法、结构不完整resource_limit超出内存、算力、页数/帧数等资源配额low_qualityOCR 置信度、分辨率、信噪比等质量指标不达标phi_uncertainty模型无法可靠判定某区域是否含 PHI宁可拒绝也不冒险speaker_uncertainty音频/视频中说话人归属不确定影响敏感信息归属判断temporal_instability时间信息不稳定如时间线推断不可靠provider_unavailable外部推断服务/提供商不可用尽早决策原则文档明确要求在能做出决定的最早阶段拒绝。例如不支持的容器格式在preflight阶段直接拒绝unsupported_media损坏的字节在decode阶段拒绝malformed_media低质量输出则取决于质量门quality gate实际运行的位置归入decode、inference或post_process。这样设计既节省算力也让审计者一眼看出问题发生的真实环节。仓库中的 openmed/multimodal/preflight.py 提供了preflight_asset等预检入口是preflight阶段弃权记录的主要来源openmed/multimodal/media_type.py 的detect_media_type/validate_media_type则支撑unsupported_media的判定。严格解析未知即失败fail-closedAbstentionRecord.from_json()要求 JSON 负载恰好包含三个字段schema_version当前必须为1stage必须是已文档化的阶段之一reason必须是该阶段允许的原因码之一以下情况一律失败关闭抛AbstentionValidationError它是ValueError的子类存在未知字段如多一个transcript字段字段值未知如stage: secret-stage-raw-ocr-textJSON 本身畸形not-json、[]等schema 版本不受支持如schema_version: 2字段缺失缺少任一必需字段阶段-原因组合非法出现重复键如{stage:preflight,stage:decode,...}实现上有两个值得注意的细节重复键检测from_json通过json.loads(payload, object_pairs_hook_strict_object)传入自定义钩子openmed/multimodal/abstention.py检测到重复键即抛错避免 JSON 标准行为后者覆盖前者带来的歧义。错误不回显提交值所有校验错误只命名契约中被违反的部分如stage is unsupported、reason is not valid for stage、payload fields are invalid绝不回显提交的原始值。这一点是 PHI 安全的关键——即使攻击者/调用方传入了含 PHI 的畸形负载错误信息也不会把它泄漏出去。对应的回归测试位于 tests/unit/multimodal/test_abstention.py其中test_invalid_payloads_do_not_echo_submitted_content专门断言当负载里塞入secret-transcript、raw-ocr-text、dicom-value等诱饵值时抛出的异常文本中不出现这些字符串。从源码看契约的层层把关AbstentionRecord.__post_init__在构造阶段就完成全部校验openmed/multimodal/abstention.pydef __post_init__(self) - None: stage _stage(self.stage) reason _reason(self.reason) if type(self.schema_version) is not int or ( self.schema_version ! ABSTENTION_SCHEMA_VERSION ): raise AbstentionValidationError(schema_version is unsupported) if reason not in _ALLOWED_REASONS[stage]: raise AbstentionValidationError(reason is not valid for stage) object.__setattr__(self, stage, stage) object.__setattr__(self, reason, reason)注意这里对schema_version使用type(...) is not int的严格类型检查连Truebool 是 int 子类都无法混入。from_dict同样要求负载必须是 Mapping 且字段集合与_REQUIRED_FIELDS {schema_version, stage, reason}完全相等openmed/multimodal/abstention.py。整条链路是from_json严格 JSON 解析→from_dict严格字段集合→ 构造函数阶段/原因/版本校验→ 得到不可变记录。任何一环失败都抛AbstentionValidationError调用方可以用统一的异常类型做降级处理。在批处理汇总中聚合弃权ProcessingSummaryAbstentionRecord不是孤立设计它与 OpenMed 的多模态批处理汇总体系深度集成。openmed/multimodal/processing_summary.py 定义了AssetProcessingResult当outcome_code为ABSTAINED时必须携带abstention: AbstentionRecord且不得携带output_digest反之非ABSTAINED的结果禁止携带弃权记录见__post_init__中的成对校验openmed/multimodal/processing_summary.py。summarize_processing_run会把一批结果聚合成ProcessingSummary其中abstention_counts以(stage, reason)为桶统计每个弃权组合的出现次数openmed/multimodal/processing_summary.py并按(stage.value, reason.value)排序保证确定性输出。render_processing_summary_markdown则把汇总渲染成 Markdown其中包含 Abstentions 表格| Stage | Reason | Count |可以直接落盘为批处理审计报告。这意味着一条弃权记录的生命周期是完整的构造 → 挂载到单个资产结果 → 聚合统计 → 渲染为审计摘要。整条链路中弃权记录是唯一解释中止原因的信息载体且始终只有三个字段。与提供商边界Provider Boundary的呼应多模态流水线在调用外部模型提供商时还有一层并行的弃权语义openmed/multimodal/provider_result.py 定义了ProviderResultOutcomesuccess/abstention/provider_unavailable/validation_failure与ProviderAbstentionCode。后者的 7 个取值与AbstentionReason高度一致unsupported_media、malformed_media、resource_limit、low_quality、phi_uncertainty、speaker_uncertainty、temporal_instability且同样遵循内容无关原则ProviderResultEnvelope只携带 provider_id、model_id、输入 digest、duration_ms、计数元数据等受约束字段abstention_code仅在结果为abstention时必需openmed/multimodal/provider_result.py。从中可以推断 OpenMed 的总体设计无论是内部流水线阶段还是外部提供商边界凡是拒绝处理都必须用稳定枚举码表达而不是自由文本从而保证日志、审计与遥测在任何环节都不会成为 PHI 泄漏通道。在 OpenMed 中使用弃权记录的最佳实践清单结合文档与源码落地时建议遵循以下约束只存三个字段schema_versionstagereason任何补充信息详细日志、上下文都放入独立且访问受控的私有系统中。尽早拒绝优先在preflight→decode→inference→post_process中最早能下结论的阶段生成弃权记录。只使用表内组合编写代码时以 openmed/multimodal/abstention.py 的_ALLOWED_REASONS与 tests/unit/multimodal/test_abstention.py 的VALID_RECORDS为准新增组合先评审契约。解析失败即拒绝from_json对任何未知字段、未知值、畸形 JSON、重复键、错误版本一律抛AbstentionValidationError上层应将该异常视为审计完整性事件处理而不是静默忽略。聚合后输出批处理场景用summarize_processing_runrender_processing_summary_markdown生成含 Abstentions 表格的审计摘要让哪些资产因什么原因在哪个阶段被拒一目了然。验证方式仓库自带完整的契约测试tests/unit/multimodal/test_abstention.py覆盖全部 17 个合法(stage, reason)组合的to_json → from_json往返一致test_every_stage_and_reason_round_trips序列化结果确定且仅含三个字段test_json_is_deterministic_and_metadata_only所有非法组合 fail-closedtest_invalid_stage_reason_combinations_fail_closed非法负载不回显提交内容test_invalid_payloads_do_not_echo_submitted_content畸形/不完整负载失败关闭test_malformed_or_incomplete_payloads_fail_closed。运行该测试文件即可验证契约行为符合本文描述openmed.multimodal包还会在导入时于 openmed/multimodal/init.py 公开导出ABSTENTION_SCHEMA_VERSION、AbstentionReason、AbstentionRecord、AbstentionStage与AbstentionValidationError方便从公共 API 直接使用。更多多模态处理细节可参考 docs/multimodal/processing-summaries.md 与 docs/multimodal/asset-manifests.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),仅供参考