Files
info-privacy/DEVELOP.md
T

215 lines
8.2 KiB
Markdown
Raw Normal View 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 开发机
```bash
# 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 板端
```bash
# 同步代码(开发机执行)
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-lite2`OpenCV/NumPy 已预装。
---
## 常用开发命令
```bash
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 环境下验证 `FaceDetector``ImageParser` 的业务逻辑(bbox 转换、entity 构建、置信度过滤等)。
板端真机测试时,`test_detectors.py``test_parsers.py` 中的 skip 测试将自动运行。
---
## 扩展指南
### 添加新的 PII 类型(Regex
1.`configs/pii_rules.yaml``regex` 节下添加规则:
```yaml
passport:
pattern: '[A-Z]{1,2}\d{7}'
security_level: high
```
2. 在 `src/info_privacy/models.py` 的 `EntityType` 枚举中增加 `PASSPORT = "passport"`
3. 在 `tests/test_detectors.py` 中增加对应测试用例
### 添加新的 PII 类型(NER
1. 在 `configs/pii_rules.yaml` 的 `ner` 节下添加触发词配置
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` 字典必须包含 `format`、`has_text_layer`、`redact_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.yaml` 中 `ner.name.context_triggers` 可降低误报率。