Files
qiurui cbfe4a23dc feat: info-privacy PII detection service with frame analysis support
- Pipeline: analyze(), redact(), analyze_image() methods
- API: /analyze, /redact, /analyze/frame, /analyze/frame/base64 endpoints
- Detectors: regex, NER, face (RKNN NPU)
- Privacy frame route added for KVM-Privacy Hub integration
2026-02-28 17:33:11 +08:00

8.2 KiB
Raw Permalink Blame History

Info-Privacy 开发指南

项目结构

info-privacy/
├── src/info_privacy/
│   ├── api/
│   │   ├── main.py              # FastAPI 入口,路由注册
│   │   ├── routes/
│   │   │   ├── analyze.py       # POST /api/v1/analyze
│   │   │   └── redact.py        # POST /api/v1/redact
│   │   └── models.py            # Pydantic 请求/响应模型
│   ├── classifier/
│   │   └── doc_classifier.py    # 保密文件拦截(关键词匹配)
│   ├── detectors/
│   │   ├── regex_detector.py    # Regex PII 检测
│   │   ├── ner_detector.py      # 规则词典姓名/地址检测
│   │   └── face_detector.py     # MediaPipe RKNN 人脸检测(硬件依赖)
│   ├── parsers/
│   │   ├── pdf_parser.py        # pdfminer 文字层解析
│   │   ├── office_parser.py     # python-docx / openpyxl
│   │   ├── image_parser.py      # PaddleOCR RKNN 图像 OCR(硬件依赖)
│   │   └── parser_factory.py    # 按文件扩展名路由
│   ├── redactors/
│   │   ├── text_redactor.py     # 文字节点替换(字节级安全)
│   │   └── image_redactor.py    # OpenCV 黑色矩形覆盖
│   ├── models.py                # 核心数据模型(TextBlock, Entity, DetectionReport
│   └── pipeline.py              # 串联 parser → classifier → detector → redactor
├── configs/
│   ├── pii_rules.yaml           # Regex 规则 + 保密关键词 + NER 配置
│   └── surnames.txt             # 中文姓氏词典(NER 姓名检测)
├── tests/
│   ├── test_models.py           # 数据模型单元测试
│   ├── test_classifier.py       # 文档分类测试
│   ├── test_detectors.py        # Regex/NER/人脸检测测试
│   ├── test_parsers.py          # PDF/Office/图像解析测试
│   ├── test_redactors.py        # 文字/图像遮罩测试
│   ├── test_pipeline.py         # 端到端流水线测试
│   ├── test_api.py              # FastAPI 接口测试
│   └── test_simulation.py       # RKNN 硬件仿真测试(x86 可运行)
├── scripts/
│   ├── start_server.sh          # 一键启动服务
│   └── verify.py                # 端到端验证脚本
├── docs/plans/                  # 设计文档(历史归档)
├── models/                      # 本地模型软链(指向 sibling 项目)
├── tmp/                         # 临时文件(已加 .gitignore
├── pyproject.toml
├── Makefile
└── setup_venv.sh

开发环境搭建

x86 开发机

# 1. 初始化虚拟环境
bash setup_venv.sh
source venv/bin/activate

# 2. 验证安装
python -c "from info_privacy.pipeline import PrivacyPipeline; print('OK')"

# 3. 运行全量测试
make test        # 155 passed, 4 skippedRKNN 相关跳过)
make lint        # ruff 代码检查

RK3588 板端

# 同步代码(开发机执行)
rsync -av /data/rockchip/info-privacy/ pi@192.168.0.127:/home/pi/Desktop/info-privacy/

# 板端环境(SSH 执行)
cd /home/pi/Desktop/info-privacy
bash setup_venv.sh && source venv/bin/activate
python -c "from info_privacy.pipeline import PrivacyPipeline; print('OK')"

板端需额外安装 rknn-toolkit-lite2OpenCV/NumPy 已预装。


常用开发命令

make test                          # 运行所有测试
make test-one FILE=tests/test_api.py  # 单文件测试
make lint                          # ruff 代码检查
make server                        # 启动服务(--reload 热重载)
make verify                        # 端到端验证(需先启动服务)
make clean                         # 清理 __pycache__ 和 tmp/

测试框架说明

分层测试策略

测试文件 类型 是否需要硬件
test_models.py 单元
test_classifier.py 单元
test_detectors.py 单元 否(人脸检测用 skip
test_parsers.py 单元 否(图像解析用 skip
test_redactors.py 单元
test_pipeline.py 集成
test_api.py 接口
test_simulation.py 仿真 否(mock 替换 RKNN
test_integration_real.py 集成(真实文件)
test_integration_complex.py 集成(边界/复杂场景)

RKNN 仿真测试

test_simulation.py 使用 unittest.mock.patch.dict(sys.modules, ...) 注入 mock 模块, 在 x86 环境下验证 FaceDetectorImageParser 的业务逻辑(bbox 转换、entity 构建、置信度过滤等)。

板端真机测试时,test_detectors.pytest_parsers.py 中的 skip 测试将自动运行。


扩展指南

添加新的 PII 类型(Regex

  1. configs/pii_rules.yamlregex 节下添加规则:
    passport:
      pattern: '[A-Z]{1,2}\d{7}'
      security_level: high
    
  2. src/info_privacy/models.pyEntityType 枚举中增加 PASSPORT = "passport"
  3. tests/test_detectors.py 中增加对应测试用例

添加新的 PII 类型(NER

  1. configs/pii_rules.yamlner 节下添加触发词配置
  2. src/info_privacy/detectors/ner_detector.py 中实现匹配逻辑
  3. 添加对应 EntityType 枚举值

添加新的文档格式

  1. src/info_privacy/parsers/ 下创建新的 Parser 类,实现 parse(file_path) -> (dict, list[TextBlock]) 接口
  2. src/info_privacy/parsers/parser_factory.py 中注册新格式的扩展名映射
  3. 新 Parser 的 meta 字典必须包含 formathas_text_layerredact_strategy 三个字段

数据流

[POST /analyze]
  文件 → parser_factory → TextBlock[]{text, bbox, page, layer}
    → doc_classifier →  如果 blocked: 直接返回 DetectionReport(blocked=True)
    → regex_detector + ner_detector + face_detector → Entity[]
    → doc_classifier(实体密度评估) → warning?
    → 返回 DetectionReport

[POST /redact]
  文件 + redact_types → analyze() → Entity[]
    → 按 entity.layer 分流:
        layer=="text"  → text_redactor(删除文字节点)
        layer=="image" → image_redactorOpenCV 黑框覆盖)
    → 输出文档 + X-Security-Report Header

关键配置文件

configs/pii_rules.yaml

  • regex:各类型的检测正则表达式和安全等级
  • confidential_keywords:保密文件拦截关键词列表
  • ner.name.surnames_file:中文姓氏词典路径(相对于项目根目录)
  • ner.address.triggers:地址检测触发词(省/市/区/路/号等)

安全等级说明

  • high:遮罩时默认强制处理,体现在 X-Security-Report
  • medium:遮罩时按用户 redact_types 指定处理

常见问题

Q: make test 显示 4 个 skipped 测试

正常现象。这 4 个测试依赖 RKNN 运行时(仅 RK3588 设备可用)。x86 环境下等效的仿真测试在 test_simulation.py 中覆盖(15 个)。

Q: 身份证号为何不会同时被标注为银行卡

系统内置去重逻辑:18 位身份证号满足银行卡格式,但 RegexDetector 在检测完成后会过滤掉与 id_card 值重叠的 bank_card 实体,避免双重计数影响阈值判断。

Q: 中文字符前的数字 PII 为何能被检测

正则边界使用 (?<!\d) / (?!\d) 而非 \b。Python 3 的 \b 是 Unicode-aware,中文字符属于 \w,与纯数字之间不形成词边界,故改用纯数字前后断言。

Q: 板端运行时 face_detector 报 ImportError

确认 MediaPipe-RKNN 项目路径存在:/data/rockchip/mediapipe/src/mediapipe_rknn/。FaceDetector 在 pipeline.py 中延迟加载,首次 analyze 图像文档时才触发。

Q: PDF 遮罩后用 PDF 阅读器仍能选中文字

检查 PDF 是否含文字层(meta["has_text_layer"])。文字层 PDF 必须用 text_redactor;单纯覆盖图像层无法防止文字提取。

Q: 中文姓名检测误报

NER 基于姓氏词典 + 上下文触发词("姓名:"、"申请人:"等)。调整 configs/pii_rules.yamlner.name.context_triggers 可降低误报率。