
使用 OpenMedredact_dataset在本地对 CSV / JSONL / Parquet 数据集进行去标识化处理【免费下载链接】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本文是一份面向数据工程师、ML 工程师与 Agent 开发者的实战指南讲解如何用 OpenMed 对本地 CSV、JSONL/NDJSON、Parquet 数据集中的指定自由文本列做 HIPAA PII 去标识化生成一份独立的脱敏数据集与一份不含 PHI 的聚合摘要。读完本文你将掌握redact_datasetPython API 与openmed redact-datasetCLI 的完整用法、strict_no_leak等策略的选择方法、摘要字段的含义以及如何在不泄露原始单元格内容的前提下验证召回率与残留泄露。前置条件与安装redact_dataset是 OpenMed 处理层openmed/processing/batch.py提供的公开 API并已通过 openmed/init.py 导出为顶层函数可直接from openmed import redact_dataset使用。它底层调用 openmed/core/pii.py 中的deidentify完成单单元格去标识化。首次使用需要安装带模型运行时的 OpenMedpython -m pip install openmed[hf]安装后模型推理完全在本地进行数据不出网符合 OpenMed Local-first / 100% on-device 的设计原则详见 README.md 与 getting-started.md。核心工作流程SKILL 文档给出的标准流程共六步每一步都服务于同一个目标源数据留在本地、自由文本列显式声明、输出写入不同路径、绝不推断列、绝不打印源值与脱敏值。确认输入为 CSV、JSONL/NDJSON 或 Parquet 之一redact_dataset会按文件后缀推断格式见下节确认哪些列包含自由文本——不要通过扫描或打印取值来猜测选择策略与语言当召回率是主导安全需求时优先使用strict_no_leak写入新路径绝不覆盖输入文件源码层面有硬性校验见下文只检查result.summary——它只包含聚合计数与比率在发布输出前用代表性合成数据或经批准的评价基准验证召回率与残留泄露。格式推断与输出路径的源码级保证在 openmed/processing/batch.py 中redact_dataset首先做三项硬性校验_infer_dataset_format按后缀判定.csv/.jsonl/.ndjson/.parquet其余后缀直接抛ValueError未传output_path时由_default_output_path生成stem.redactedsuffixJSONL 统一为.jsonlif input_path.resolve() destination.resolve(): raise ValueError(output_path must not overwrite the input dataset)——输出路径与输入路径相同会直接报错从根上杜绝覆盖源文件。三种格式的处理路径各不相同同一函数内的分支CSVcsv.DictReader逐行流式读取要求存在表头_validate_text_columns校验所选列必须存在非文本列原样保留JSONL/NDJSON逐行json.loads每行必须是对象非文本字段原样保留Parquet通过pyarrow可选依赖未安装会提示pip install pyarrow按batch_size默认 512分批读取且要求所选文本列必须是 string/large_string/null 类型输出保留原始 schema。Python APIredact_dataset完整可运行示例以下示例可直接复制运行来源于 SKILL 文档补充了参数说明import csv from pathlib import Path from openmed import redact_dataset source Path(synthetic-notes.csv) destination Path(synthetic-notes.redacted.csv) with source.open(w, newline, encodingutf-8) as handle: writer csv.DictWriter(handle, fieldnames[record_id, note]) writer.writeheader() writer.writerows( [ { record_id: SYNTH-001, note: ( Taylor Example called 212-555-0198 about a metformin refill. ), }, { record_id: SYNTH-002, note: ( Send the synthetic follow-up to demo.patientexample.test. ), }, ] ) result redact_dataset( source, text_columns[note], output_pathdestination, policystrict_no_leak, langen, ) print(result.output_path) print(result.summary.to_dict()) # Aggregate counts only; no cell contents.注意redact_dataset对 CSV 的文本编码默认utf-8可通过encoding参数调整示例使用newline打开文件以规避 Windows 换行问题。完整参数表redact_dataset的完整签名来自 openmed/processing/batch.py参数类型默认值说明pathstr \| Path必填输入数据集路径须为.csv/.jsonl/.ndjson/.parquettext_columnsSequence[str]必填要透传deidentify的自由文本列名至少一个重复/空名会被_normalize_text_columns去重过滤output_pathstr \| Path \| NoneNone目标路径默认stem.redactedsuffix不得等于输入路径policystr \| NoneNone去标识化策略配置文件名称如strict_no_leak、hipaa_safe_harbormethodstrmask去标识化方法透传给deidentifymodel_namestrOpenMed/OpenMed-PII-SuperClinical-Small-44M-v1PII 检测模型confidence_thresholdfloat0.7触发脱敏的最低置信度configOpenMedConfig \| NoneNone可选的 OpenMed 配置对象langstren语言提示透传给deidentifykeep_yearboolTrue日期脱敏时是否保留年份date_shift_daysint \| NoneNone可选的固定日期偏移天数use_safety_sweepboolTrue启用确定性的结构化标识符扫描encodingstrutf-8CSV/JSONL 文本编码batch_sizeint512Parquet 每批处理的行数须为正数返回对象DatasetRedactionResult与DatasetRedactionSummaryredact_dataset返回DatasetRedactionResult仅含两个字段openmed/processing/batch.pyoutput_path脱敏后数据集路径summaryDatasetRedactionSummary聚合摘要to_dict()输出以下PHI-free字段openmed/processing/batch.py字段含义input_format输入格式csv/jsonl/parquettext_columns本次脱敏的自由文本列total_rows处理的总行数processed_cells实际经过去标识化的单元格数空值/空串跳过见_redact_dataset_rowredacted_cells输出与输入不一致发生脱敏的单元格数total_spans检测到的 PII 片段总数per_label_counts按实体标签聚合的计数如{PERSON: 2, PHONE: 1, EMAIL: 1}residual_span_count脱敏后实体表面文本仍残留在结果中的片段数_update_redaction_summary中逐实体比对surface in deidentified_textresidual_leakage_estimate残留泄露率估算 residual_span_count / total_spans设计上摘要故意不包含原始输入值、脱敏单元格值或实体表面文本docstring 明确写明 counts and rates only因此可安全打印与记录。CLIopenmed redact-dataset对于已有数据集可用等效 CLI源自 SKILL 文档openmed redact-dataset notes.csv \ --text-columns note,comment \ --policy strict_no_leak \ --output notes.redacted.csvCLI 子命令定义于 openmed/cli/main.py除--text-columns逗号分隔外还支持--text-column可重复参数每传一次脱敏一列两者可组合使用。完整参数参数默认值说明path位置参数—输入.csv/.jsonl/.ndjson/.parquet--text-column可重复单个自由文本列多次传递--text-columnsNone逗号分隔的列列表--output/-ostem.redactedsuffix输出路径--policyNone策略配置文件名称--methodmaskmask/remove/replace/hash/shift_dates--modelOpenMed/OpenMed-PII-SuperClinical-Small-44M-v1PII 检测模型--confidence-threshold0.7最低置信度--langen语言提示--encodingutf-8CSV/JSONL 编码--batch-size512Parquet 分批行数--keep-year/--no-keep-yearTrue是否保留日期年份BooleanOptionalAction--no-safety-sweep—关闭确定性结构化标识符扫描CLI 同样遵循不覆盖输入、只输出聚合摘要的原则测试 tests/unit/processing/test_redact_dataset.py 验证了 CLI 输出的审计摘要不含任何测试数据中的 PHI。策略选择为什么推荐strict_no_leakSKILL 明确建议当召回率是主导安全需求时优先使用strict_no_leak。从源码看这一策略与 OpenMed 的仲裁arbitration机制直接挂钩openmed/core/arbitration.py 中arbitration_mode(strict_no_leakTrue)返回MODE_HIGH_RECALL_UNION高召回并集即同时启用多个检测器并把它们的识别结果取并集宁可多脱敏也不放过可疑实体openmed/core/pipeline.py 中加载策略后resolved_policy.strict_no_leak、threshold_profile、arbitration_mode、safety_sweep_mandatory会被合并进处理管线策略名称与阈值配置联动。换言之strict_no_leak是以召回率为第一优先级的安全档位它通过并集仲裁把漏检概率压到最低代价是可能产生更保守的脱敏结果。与之相对HIPAA 场景常用的hipaa_safe_harbor如 openmed/compliance/safe_harbor.py 定义则侧重合规专家豁免检查。选择哪种策略取决于你的发布目标是最大限度减少泄露还是满足合规专家审查流程。底层原理从redact_dataset到deidentify的调用链redact_dataset对每个非空单元格调用_deidentify_dataset_cellopenmed/processing/batch.py其内部执行from openmed.core.pii import deidentify后调用deidentify(text, method..., model_name..., confidence_threshold..., keep_year..., date_shift_days..., config..., lang..., use_safety_sweep..., policy...)——即所有去标识化语义都由 openmed/core/pii.py 的deidentify承担。deidentify支持的方法也是--method的合法取值包括mask默认替换为[NAME]、[EMAIL]、[PHONE]等占位符aadhaar_mask将有效 Aadhaar 值渲染为XXXX XXXX NNNN其余实体用普通占位符remove直接移除 PII 文本replace替换为逼真的假数据hash替换为一致的哈希值可用于实体关联分析format_preserve结构化标识符保留形状与分隔符的合成值shift_dates随机偏移日期并保持时间间隔。此外deidentify还内置智能合并smart merging用正则把被切碎的实体合并回完整单元如把01与/15/1970合并成01/15/1970并在脱敏前执行确定性的结构化标识符安全扫描safety sweep——这正是use_safety_sweepTrue默认开启的意义。redact_dataset的keep_year/date_shift_days参数也直接透传给该函数在deidentify中date_shift_days在未提供patient_key时作为固定偏移量。安全规范Safety checks无论使用 API 还是 CLI都应遵守以下约束源自 SKILL 文档并结合源码印证模型推理与文件处理必须运行在用户可控的基础设施上保持本地化不要打印输入行、检测到的实体表面文本、可逆映射或可能包含源文本的异常载荷batch.py的日志只记录error_type不记录异常消息文本见 openmed/processing/batch.py源路径与输出路径保持分离并受访问控制输出路径硬校验不可覆盖输入把聚合摘要当作证据而不是合规证明——它只是统计指标不能替代专家审查绝不把真实临床数据或受限评价语料提交到版本库。仓库配套示例离线数据集演练SKILL 文档指向 examples/datasets_walkthrough.py这是一个面向首次运行的离线演练脚本它从仓库内置的合成 golden fixtureopenmed/eval/golden/fixtures/multilingual.json中的golden-multilingual-en-ssn加载一条可再分发的合成样本无需 DUA 或外部数据集通过offline_model_loading()上下文管理器默认设置HF_HUB_OFFLINE1与TRANSFORMERS_OFFLINE1强制离线只有显式设置环境变量OPENMED_EXAMPLE_ALLOW_DOWNLOAD1才允许首次运行下载模型依次调用extract_pii与deidentify(methodmask)输出检测实体数、脱敏前后文本并与捆绑的期望输出比对是否一致。直接运行python examples/datasets_walkthrough.py模型未缓存时会提示Set OPENMED_EXAMPLE_ALLOW_DOWNLOAD1 to allow first-run downloads此时按提示设置环境变量后再运行即可。单元测试佐证行为即契约tests/unit/processing/test_redact_dataset.py 用假deidentify隔离了数据集层逻辑验证了三个关键契约CSV非文本列id、age原样保留只有note被脱敏为Patient [PERSON] called [PHONE]摘要字段与期望完全一致total_rows2、total_spans4、per_label_counts{EMAIL:1,PERSON:2,PHONE:1}、residual_leakage_estimate0.0JSONL非文本字段id、status保留每行对象结构不变Parquetpyarrow可用时保留 schemabatch_size1分批仍输出完整数据CLIredact-dataset子命令输出 PHI-free 审计摘要摘要中不包含任何测试数据里的 PHI_assert_summary_has_no_fixture_phi。这些测试同时印证了本文开头的流程约束显式列名、独立输出路径、聚合摘要不含单元格内容。小结redact_dataset把本地数据集去标识化收敛为一个可复现的原子操作显式声明自由文本列 → 选择策略与语言 → 写入独立输出路径 → 只消费聚合摘要 → 发布前验证召回与残留。从 Python API、CLI 到底层deidentify的智能合并与安全扫描再到仓库内的离线演练脚本与单元测试你可以在此基础上安全地构建自己的临床数据发布流水线。相关能力还可进一步参考 batch-processing.md、deidentifying-clinical-text.md 与 deidentifying-multilingual-text.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),仅供参考