Clawvard
Clawvard

Product

EvaluateModel ServiceLearning & EvolutionCampus

Developers

DocsResearchGitHub

Legal

PrivacyTerms

Community

XREDnoteTikTok
© 2026 Clawvard LimitedPowered by AWS Cloud Computing
←Back to Courses

🧑‍💼 Productivity

Redact PII Before Sharing

Drop a folder of mixed customer data (TXT / CSV / PDF / images) and get back a redacted/ folder with identical layout — names, emails, phones, ID numbers, credit cards and addresses replaced with stable placeholders, plus a side-by-side diff.html and an auditable report.json. Fully local, zero LLM, zero external key. The compliance gate to run before feeding AI, outsourcing, or sharing with research partners.

💰 Free🔌 No commercial API

Everything below is a skill document. Hit copy, paste it to your agent, and it has learned the skill.

microsoft/presidio / SKILL.md

客户数据脱敏 / Redact PII Before Sharing

你现在运行 redact-pii 技能。目标:丢一文件夹混合输入(TXT / CSV / PDF / 图片),就地脱敏出一个结构完全一致的 redacted/——所有姓名、邮箱、手机号、身份证、信用卡、地址、医保号都替换成稳定占位符;外加一份 diff.html 左右对照页和一份 report.json 审计明细。全程本地,零 LLM,零远端 API,零商业兜底转发。

底层是 Microsoft Presidio 的四个官方 pip 包(MIT 协议,Microsoft 维护,PyPI 稳定发布)。本技能不再包一层 wrapper —— 直接调用上游 4 个引擎;课程的价值是 agent-ready SOP + zh-CN 自定义 recognizer + 统一占位符 / 报告契约。

这门课做什么(边界写在第一屏)

  • ✅ 做:把一文件夹混合的 .txt / .md / .json / .csv / .tsv / .pdf / .png / .jpg 一次脱敏,输出同名同结构的 redacted/;同一字面值跨文件保留同一占位符 id,方便下游分析关联。
  • ✅ 覆盖语种:默认同时加载 spaCy en_core_web_lg 与 zh_core_web_lg,对中文环境额外加载本课的 zh-CN custom recognizer(大陆手机号 / 身份证 / 统一社会信用代码 / 中文姓名 + 上下文)。
  • ❌ 不做:扫描件之外的复杂文档结构还原(多栏 PDF、含公式、图表抽提)—— 那是 parse-docs 课程的领域。我们只负责把扫描件 PNG/JPG 里被 OCR 出来的 PII 文本盖上黑框。
  • ❌ 不做:任何调用 LLM / 商业 API 的兜底。Presidio 的可选 LLM recognizer 增强仅在本文末尾「Optional 增强」小节里描述,默认关闭,需要用户显式 opt-in 才能开。
  • 🔒 铁律:SOP、参考脚本 redact.py、popularTasks 默认执行路径不联网,不允许调任何商业 LLM SDK、任何 LLM 兜底端点、任何远端推理服务、任何兼容性转发层;本地 LLM HTTP 网关也禁用。具体被禁用的产品名见本文末尾 Optional 小节(默认 off)。

前置条件

  • Python ≥ 3.10(python3 --version 检查)
  • 本地 tesseract OCR + 中英语言包(图片 / 扫描件路径需要)
    • macOS:brew install tesseract tesseract-lang
    • Ubuntu/Debian:sudo apt-get install tesseract-ocr tesseract-ocr-eng tesseract-ocr-chi-sim
    • Windows:官方 installer + 勾选中文语言包
  • 首次跑会拉两份 spaCy 模型,合计约 1.2 GB,下载一次即可,全程本地、无需任何 API key

安装(一次到位)

强烈建议在 venv 里装,避免和系统 Python 打架(Ubuntu 24+ 的 PEP 668 会拒绝直接安装):

python3 -m venv .pii_venv
source .pii_venv/bin/activate
pip install --upgrade pip
pip install presidio-analyzer presidio-anonymizer presidio-image-redactor presidio-structured
pip install pandas pypdf Pillow click
# `click` is a transitive of spaCy that some pip resolvers skip in mixed
# installs — install it explicitly so `python -m spacy download …` below
# doesn't crash with ModuleNotFoundError on a fresh venv.
python -m spacy download en_core_web_lg
python -m spacy download zh_core_web_lg

不做 wrapper 的理由:四个包都是 Microsoft 官方维护、MIT、PyPI 稳定发布;组合用法是 Presidio docs 第一章示例代码。课程价值 = 「agent-ready SOP + zh-CN recognizer YAML + 统一报告格式」,而不是再包一层 npm/pip。redact.py 是参考编排脚本(≈ 180 行),随技能一起发布在 public/skills/redact-pii/redact.py,agent 把它当模板复用 / 改写即可。

工作流程(agent 执行步骤)

1. 注册 zh-CN custom recognizer

Presidio 默认对中文 PII 识别率一般:zh_core_web_lg 的 NER 会把人名和地名 / 机构名混在一起,且没有大陆手机号 / 身份证 / 统一社会信用代码的内置 recognizer。本课提供一份可复制的 zh_cn_recognizers.yaml(位于 public/skills/redact-pii/zh_cn_recognizers.yaml):

# zh_cn_recognizers.yaml — paste into SOP verbatim
supported_languages: [zh, en]
recognizers:
  - name: CN_MOBILE_PHONE
    supported_language: zh
    supported_entity: CN_MOBILE_PHONE
    patterns:
      - name: cn_mobile
        regex: "(?<![0-9])1[3-9]\\d{9}(?![0-9])"
        score: 0.95   # > 0.85 so we win overlap ties against built-in DATE_TIME
  - name: CN_ID_CARD
    supported_language: zh
    supported_entity: CN_ID_CARD
    patterns:
      - name: cn_id_18
        regex: "(?<![0-9])[1-9]\\d{5}(?:19|20)\\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx](?![0-9Xx])"
        score: 0.95
    context: [身份证, 身分证]
  - name: CN_USCC
    supported_language: zh
    supported_entity: CN_USCC
    patterns:
      - name: cn_uscc
        regex: "(?<![A-Z0-9])[0-9A-HJ-NPQRTUWXY]{2}\\d{6}(?=[0-9A-HJ-NPQRTUWXY]*[A-HJ-NPQRTUWXY])[0-9A-HJ-NPQRTUWXY]{10}(?![A-Z0-9])"
        score: 0.9
  - name: CN_PERSON_NAME
    supported_language: zh
    supported_entity: PERSON
    patterns:
      - name: cn_name_context
        regex: "[\\u4e00-\\u9fa5]{2,4}"
        score: 0.35
    context: [姓名, 客户, 联系人, 收件人, 申请人, 先生, 女士]

为什么这套设计:

  • CN_PERSON_NAME 基础 score = 0.35(低于默认 0.5 阈值),单凭 regex 不会自动替换;命中后由 spaCy NER 或 context 关键词把分数抬上去,才进 anonymizer 这一步。这样既覆盖「客户:张三」「收件人 李雷」也避免把「今天天气真好」误标。
  • CN_USCC regex 显式要求 9 位组织机构代码段至少含一个字母,避免和纯数字 18 位身份证撞车(身份证由 CN_ID_CARD 以更高 score 接住)。
  • score_threshold=0.5 是默认阈值;低于阈值的命中仍然写进 report.json 并在 diff.html 用红色标 low-confidence, review needed,但不自动替换 —— 避免误脱敏。

注册方式两选一(参考脚本走 Python;YAML 路径见 Presidio 官方文档 AnalyzerEngineProvider):

from presidio_analyzer import AnalyzerEngine, RecognizerRegistry, PatternRecognizer, Pattern
from presidio_analyzer.nlp_engine import NlpEngineProvider

config = {"nlp_engine_name": "spacy", "models": [
    {"lang_code": "en", "model_name": "en_core_web_lg"},
    {"lang_code": "zh", "model_name": "zh_core_web_lg"},
]}
nlp_engine = NlpEngineProvider(nlp_configuration=config).create_engine()
registry = RecognizerRegistry(supported_languages=["en", "zh"])
registry.load_predefined_recognizers(languages=["en", "zh"])
# add the four zh-CN recognizers from zh_cn_recognizers.yaml (see redact.py for the Python form)
analyzer = AnalyzerEngine(nlp_engine=nlp_engine, registry=registry,
                          supported_languages=["en", "zh"])

2. 用四入口分发文件

把输入文件按后缀路由:

扩展名 引擎 备注
.txt / .md / .json presidio-analyzer + presidio-anonymizer 自动检测 CJK → 选 zh,否则 en
.csv / .tsv presidio-structured (PandasAnalysisBuilder) 列级类型推断 + 同字面值跨行同 id
.pdf (文本层) analyzer + anonymizer + pypdf 重写 content stream 保留原排版、字体、坐标
.pdf (扫描件) 先 pypdf.PdfReader 判断有无文本层;无 → 按页 rasterize 后走 image-redactor 复杂多栏 / 含公式 PDF 改用 parse-docs
.png / .jpg / .jpeg / .tif presidio-image-redactor tesseract OCR + 黑框覆盖

3. 统一占位符策略

用 OperatorConfig("replace", {"new_value": f"<{entity_type}_{stable_id:03d}>"}),相同字面值(不论出现在哪个文件、哪一列)复用同一 stable_id:

import hashlib
ids = {}            # {(entity_type, sha16(value)): "<ENT_NNN>"}
counters = {}       # {entity_type: int}

def allocate(entity_type: str, value: str) -> str:
    h = hashlib.sha256(value.encode("utf-8")).hexdigest()[:16]
    key = (entity_type, h)
    if key in ids:
        return ids[key]
    counters[entity_type] = counters.get(entity_type, 0) + 1
    ids[key] = f"<{entity_type}_{counters[entity_type]:03d}>"
    return ids[key]

这样下游分析(外包团队 / 研究伙伴)即便看不到原 PII,也能用 replacement_id 做关联分析(同一客户的多笔工单依然能聚合)。

4. 一键跑参考脚本

python redact.py --input ./customer-export \
                 --output ./redacted \
                 --report ./redacted/report.json

redact.py 在 public/skills/redact-pii/redact.py,本地把它拷到工作目录或直接 python /path/to/skill/redact.py。

5. 自检(务必跑)

  • report.json.summary.total_findings > 0,否则说明 recognizer 没装上(最常见原因:忘了把 CN_* recognizer 注册进 registry,或没下载 zh_core_web_lg)。
  • 抽样 5 条 low_confidence: true 的命中人工二次确认 —— 这些是 score < 0.5 没被自动替换的,是真 PII 还是误报?
  • 用一份只含中文姓名 + 大陆手机号 + 大陆身份证的小 .txt 跑一次 sanity check —— 必须命中至少 3 类不同的 entity_type,否则 zh-CN recognizer 没生效。

产出物(用户拿到的就是这些)

redacted/
├── <same-name>.<same-ext>     # 每个原文件一份脱敏副本(同名同后缀)
├── diff.html                   # 自包含单文件,左右对照 + entity 计数 chip
└── report.json                 # auditable findings(含 score / offset / replacement_id)

report.json schema(节选):

{
  "summary": {
    "total_files": 4,
    "total_findings": 677,
    "by_entity": {"PERSON": 156, "EMAIL_ADDRESS": 78, "CN_MOBILE_PHONE": 15, "...": "..."},
    "low_confidence_review_needed": 15,
    "score_threshold": 0.5
  },
  "findings": [
    {"file": "support-chat.txt", "entity_type": "CN_MOBILE_PHONE",
     "score": 0.85, "start": 142, "end": 153,
     "original_hash": "sha256:…", "replacement_id": "<CN_MOBILE_PHONE_001>",
     "low_confidence": false}
  ]
}

diff.html 自包含(inline CSS + 内嵌 base64 image,无 CDN)、左右对照、顶部 entity 类型计数 chips、底部 attribution。浏览器双击可直接打开。

铁律 / 反模式

  • 不要写入用户系统 Python:始终在 venv(或 pipx)里安装。
  • 不要默认开 LLM recognizer。Presidio 支持外挂语义抽取做更细的实体识别,但那是 BYO key、增加成本、增加风险面;本课程的承诺是「零 LLM、零远端 API」。如果用户显式要开,让他在 SOP 之外另起一份脚本(具体怎么挂见本文末尾 Optional 小节),且要让他完全清楚 key 走哪儿、数据被发到哪儿。
  • 不要假设默认 recognizer 已经够好。中文环境下若没注册 zh-CN custom recognizer,大陆手机号 / 身份证 / 统一社会信用代码会零命中 —— 演示翻车第一名。
  • 不要伪造内容:脱敏不是改写。如果某份文件转出来零命中,把那份文件名列给用户让他自己看,不要替它编 PII。
  • 不要把 redact.py 当 wrapper 二次打包再发布到 npm / PyPI。它是参考脚本,用户随手改 ≤ 50 行就能改成自己业务需要的形态。

Optional · LLM recognizer 增强(默认 off)

Presidio 0.7+ 官方支持挂 Azure OpenAI / Anthropic LangExtract 做更细的实体抽取(适合「医生病历摘要里识别出'家庭住址'类高语义实体」这种 regex 抓不到的场景)。如果用户明确知道自己在做什么、能承担 BYO key 成本、且数据可以离开本地,可以这样起一份独立脚本:

# Optional — only if the user explicitly opts in. NOT part of the default SOP.
pip install presidio-analyzer[llm]
# Configure provider via env vars per Presidio docs; do not ship secrets in the SOP.

注意几点(这一节是写给用户读的,不是写给 agent 自动开的):

  • 这条路径会把数据发去第三方 LLM provider,与本课「零 LLM、零远端」的默认承诺不一致。
  • BYO key 路径由用户全权管理;课程不提供远端中转、不提供 Clawvard SDK 兜底、不替用户管 key。
  • 如果你的数据出于合规原因不能离开本地,不要启用这条路径。

学习完成后

告诉用户:

我已经学会了 redact-pii。给我一个混合 CSV / TXT / PDF / 图片的文件夹,我在本地用 Microsoft Presidio 一次脱敏成同名同结构的 redacted/,附左右对照 diff.html 和审计明细 report.json,每条命中含 entity 类型、score、原始位置、稳定占位符 id。全程本地、零 LLM、零外部 key、不联网。


课程主页与更多示例:clawvard.school

What you get

diff.html
Open ↗

客户数据脱敏前后对照看板:四类典型输入(工单 CSV、客服对话、简历 PDF、证件样式图)左原文(红框标 PII),右脱敏副本(绿框写稳定占位符),顶栏一行 chip 显示每种 PII 类型命中多少条、几条低置信交人工复核。

Popular tasks · tap to copy

Backend APIs

No backend API · local CLI only

The open-source skill

microsoft/presidio★ 5,300
microsoft/presidio ↗
pip install presidio-analyzer presidio-anonymizer presidio-image-redactor presidio-structured pandas pypdf Pillow click

Prereqs: 本地需 Python ≥ 3.10 + tesseract OCR(含中英语言包);首次跑会一次性下载 spaCy `en_core_web_lg` + `zh_core_web_lg` 模型(合计约 1.2 GB)。课程在本机离线运行。可选 LLM recognizer 增强路径默认关闭,需用户显式 opt-in。