WIP
This commit is contained in:
239
README.md
239
README.md
@@ -7,8 +7,9 @@
|
||||
本项目实现了一个完整的发票字段自动提取流程:
|
||||
|
||||
1. **自动标注**: 利用已有 CSV 结构化数据 + OCR 自动生成 YOLO 训练标注
|
||||
2. **模型训练**: 使用 YOLOv11 训练字段检测模型
|
||||
2. **模型训练**: 使用 YOLOv11 训练字段检测模型,支持数据增强
|
||||
3. **推理提取**: 检测字段区域 -> OCR 提取文本 -> 字段规范化
|
||||
4. **Web 管理**: React 前端 + FastAPI 后端,支持文档管理、数据集构建、模型训练和版本管理
|
||||
|
||||
### 架构
|
||||
|
||||
@@ -16,15 +17,17 @@
|
||||
|
||||
```
|
||||
packages/
|
||||
├── shared/ # 共享库 (PDF, OCR, 规范化, 匹配, 工具)
|
||||
├── shared/ # 共享库 (PDF, OCR, 规范化, 匹配, 存储, 训练)
|
||||
├── training/ # 训练服务 (GPU, 按需启动)
|
||||
└── inference/ # 推理服务 (常驻运行)
|
||||
frontend/ # React 前端 (Vite + TypeScript + TailwindCSS)
|
||||
```
|
||||
|
||||
| 服务 | 部署目标 | GPU | 生命周期 |
|
||||
|------|---------|-----|---------|
|
||||
| **Inference** | Azure App Service | 可选 | 常驻 7x24 |
|
||||
| **Training** | Azure ACI | 必需 | 按需启动/销毁 |
|
||||
| **Frontend** | Vercel / Nginx | 否 | 常驻 |
|
||||
| **Inference** | Azure App Service / AWS | 可选 | 常驻 7x24 |
|
||||
| **Training** | Azure ACI / AWS ECS | 必需 | 按需启动/销毁 |
|
||||
|
||||
两个服务通过共享 PostgreSQL 数据库通信。推理服务通过 API 触发训练任务,训练服务从数据库拾取任务执行。
|
||||
|
||||
@@ -34,7 +37,8 @@ packages/
|
||||
|------|------|
|
||||
| **已标注文档** | 9,738 (9,709 成功) |
|
||||
| **总体字段匹配率** | 94.8% (82,604/87,121) |
|
||||
| **测试** | 922 passed |
|
||||
| **测试** | 1,601 passed |
|
||||
| **测试覆盖率** | 28% |
|
||||
| **模型 mAP@0.5** | 93.5% |
|
||||
|
||||
**各字段匹配率:**
|
||||
@@ -97,6 +101,9 @@ invoice-master-poc-v2/
|
||||
│ │ ├── ocr/ # PaddleOCR 封装 + 机器码解析
|
||||
│ │ ├── normalize/ # 字段规范化 (10 种 normalizer)
|
||||
│ │ ├── matcher/ # 字段匹配 (精确/子串/模糊)
|
||||
│ │ ├── storage/ # 存储抽象层 (Local/Azure/S3)
|
||||
│ │ ├── training/ # 共享训练组件 (YOLOTrainer)
|
||||
│ │ ├── augmentation/ # 数据增强 (DatasetAugmenter)
|
||||
│ │ ├── utils/ # 工具 (验证, 清理, 模糊匹配)
|
||||
│ │ ├── data/ # DocumentDB, CSVLoader
|
||||
│ │ ├── config.py # 全局配置 (数据库, 路径, DPI)
|
||||
@@ -129,12 +136,29 @@ invoice-master-poc-v2/
|
||||
│ ├── data/ # AdminDB, AsyncRequestDB, Models
|
||||
│ └── azure/ # ACI 训练触发器
|
||||
│
|
||||
├── migrations/ # 数据库迁移
|
||||
│ ├── 001_async_tables.sql
|
||||
│ ├── 002_nullable_admin_token.sql
|
||||
│ └── 003_training_tasks.sql
|
||||
├── frontend/ # React 前端 (Vite + TypeScript)
|
||||
├── tests/ # 测试 (922 tests)
|
||||
├── frontend/ # React 前端 (Vite + TypeScript + TailwindCSS)
|
||||
│ ├── src/
|
||||
│ │ ├── api/ # API 客户端 (axios + react-query)
|
||||
│ │ ├── components/ # UI 组件
|
||||
│ │ │ ├── Dashboard.tsx # 文档管理面板
|
||||
│ │ │ ├── Training.tsx # 训练管理 (数据集/任务)
|
||||
│ │ │ ├── Models.tsx # 模型版本管理
|
||||
│ │ │ ├── DatasetDetail.tsx # 数据集详情
|
||||
│ │ │ └── InferenceDemo.tsx # 推理演示
|
||||
│ │ └── hooks/ # React Query hooks
|
||||
│ └── package.json
|
||||
│
|
||||
├── migrations/ # 数据库迁移 (SQL)
|
||||
│ ├── 003_training_tasks.sql
|
||||
│ ├── 004_training_datasets.sql
|
||||
│ ├── 005_add_group_key.sql
|
||||
│ ├── 006_model_versions.sql
|
||||
│ ├── 007_training_tasks_extra_columns.sql
|
||||
│ ├── 008_fix_model_versions_fk.sql
|
||||
│ ├── 009_add_document_category.sql
|
||||
│ └── 010_add_dataset_training_status.sql
|
||||
│
|
||||
├── tests/ # 测试 (1,601 tests)
|
||||
├── docker-compose.yml # 本地开发 (postgres + inference + training)
|
||||
├── run_server.py # 快捷启动脚本
|
||||
└── runs/train/ # 训练输出 (weights, curves)
|
||||
@@ -270,9 +294,32 @@ Inference API PostgreSQL Training (ACI)
|
||||
| POST | `/api/v1/admin/documents/upload` | 上传 PDF |
|
||||
| GET | `/api/v1/admin/documents/{id}` | 文档详情 |
|
||||
| PATCH | `/api/v1/admin/documents/{id}/status` | 更新文档状态 |
|
||||
| PATCH | `/api/v1/admin/documents/{id}/category` | 更新文档分类 |
|
||||
| GET | `/api/v1/admin/documents/categories` | 获取分类列表 |
|
||||
| POST | `/api/v1/admin/documents/{id}/annotations` | 创建标注 |
|
||||
| POST | `/api/v1/admin/training/trigger` | 触发训练任务 |
|
||||
| GET | `/api/v1/admin/training/{id}/status` | 查询训练状态 |
|
||||
|
||||
**Training API:**
|
||||
|
||||
| 方法 | 端点 | 描述 |
|
||||
|------|------|------|
|
||||
| POST | `/api/v1/admin/training/datasets` | 创建数据集 |
|
||||
| GET | `/api/v1/admin/training/datasets` | 数据集列表 |
|
||||
| GET | `/api/v1/admin/training/datasets/{id}` | 数据集详情 |
|
||||
| DELETE | `/api/v1/admin/training/datasets/{id}` | 删除数据集 |
|
||||
| POST | `/api/v1/admin/training/tasks` | 创建训练任务 |
|
||||
| GET | `/api/v1/admin/training/tasks` | 任务列表 |
|
||||
| GET | `/api/v1/admin/training/tasks/{id}` | 任务详情 |
|
||||
| GET | `/api/v1/admin/training/tasks/{id}/logs` | 训练日志 |
|
||||
|
||||
**Model Versions API:**
|
||||
|
||||
| 方法 | 端点 | 描述 |
|
||||
|------|------|------|
|
||||
| GET | `/api/v1/admin/models` | 模型版本列表 |
|
||||
| GET | `/api/v1/admin/models/{id}` | 模型详情 |
|
||||
| POST | `/api/v1/admin/models/{id}/activate` | 激活模型 |
|
||||
| POST | `/api/v1/admin/models/{id}/archive` | 归档模型 |
|
||||
| DELETE | `/api/v1/admin/models/{id}` | 删除模型 |
|
||||
|
||||
## Python API
|
||||
|
||||
@@ -332,8 +379,41 @@ print(f"Customer Number: {result}") # "UMJ 436-R"
|
||||
|
||||
| 数据库 | 用途 | 存储内容 |
|
||||
|--------|------|----------|
|
||||
| **PostgreSQL** | 标注结果 | `documents`, `field_results`, `training_tasks` |
|
||||
| **SQLite** (AdminDB) | Web 应用 | 文档管理, 标注编辑, 用户认证 |
|
||||
| **PostgreSQL** | 主数据库 | 文档、标注、训练任务、数据集、模型版本 |
|
||||
|
||||
### 主要表
|
||||
|
||||
| 表名 | 说明 |
|
||||
|------|------|
|
||||
| `admin_documents` | 文档管理 (PDF 元数据, 状态, 分类) |
|
||||
| `admin_annotations` | 标注数据 (YOLO 格式边界框) |
|
||||
| `training_tasks` | 训练任务 (状态, 配置, 指标) |
|
||||
| `training_datasets` | 数据集 (train/val/test 分割) |
|
||||
| `dataset_documents` | 数据集-文档关联 |
|
||||
| `model_versions` | 模型版本管理 (激活/归档) |
|
||||
| `admin_tokens` | 管理员认证令牌 |
|
||||
| `async_requests` | 异步推理请求 |
|
||||
|
||||
### 数据集状态
|
||||
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
| `building` | 正在构建数据集 |
|
||||
| `ready` | 数据集就绪,可开始训练 |
|
||||
| `trained` | 已完成训练 |
|
||||
| `failed` | 构建失败 |
|
||||
| `archived` | 已归档 |
|
||||
|
||||
### 训练状态
|
||||
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
| `pending` | 等待执行 |
|
||||
| `scheduled` | 已计划 |
|
||||
| `running` | 正在训练 |
|
||||
| `completed` | 训练完成 |
|
||||
| `failed` | 训练失败 |
|
||||
| `cancelled` | 已取消 |
|
||||
|
||||
## 测试
|
||||
|
||||
@@ -347,8 +427,114 @@ DB_PASSWORD=xxx pytest tests/ --cov=packages --cov-report=term-missing
|
||||
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| **测试总数** | 922 |
|
||||
| **测试总数** | 1,601 |
|
||||
| **通过率** | 100% |
|
||||
| **覆盖率** | 28% |
|
||||
|
||||
## 存储抽象层
|
||||
|
||||
统一的文件存储接口,支持多后端切换:
|
||||
|
||||
| 后端 | 用途 | 安装 |
|
||||
|------|------|------|
|
||||
| **Local** | 本地开发/测试 | 默认 |
|
||||
| **Azure Blob** | Azure 云部署 | `pip install -e "packages/shared[azure]"` |
|
||||
| **AWS S3** | AWS 云部署 | `pip install -e "packages/shared[s3]"` |
|
||||
|
||||
### 配置文件 (storage.yaml)
|
||||
|
||||
```yaml
|
||||
backend: ${STORAGE_BACKEND:-local}
|
||||
presigned_url_expiry: 3600
|
||||
|
||||
local:
|
||||
base_path: ${STORAGE_BASE_PATH:-./data/storage}
|
||||
|
||||
azure:
|
||||
connection_string: ${AZURE_STORAGE_CONNECTION_STRING}
|
||||
container_name: ${AZURE_STORAGE_CONTAINER:-documents}
|
||||
|
||||
s3:
|
||||
bucket_name: ${AWS_S3_BUCKET}
|
||||
region_name: ${AWS_REGION:-us-east-1}
|
||||
```
|
||||
|
||||
### 使用示例
|
||||
|
||||
```python
|
||||
from shared.storage import get_storage_backend
|
||||
|
||||
# 从配置文件加载
|
||||
storage = get_storage_backend("storage.yaml")
|
||||
|
||||
# 上传文件
|
||||
storage.upload(Path("local.pdf"), "documents/invoice.pdf")
|
||||
|
||||
# 获取预签名 URL (前端访问)
|
||||
url = storage.get_presigned_url("documents/invoice.pdf", expires_in_seconds=3600)
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
|
||||
| 变量 | 后端 | 说明 |
|
||||
|------|------|------|
|
||||
| `STORAGE_BACKEND` | 全部 | `local`, `azure_blob`, `s3` |
|
||||
| `STORAGE_BASE_PATH` | Local | 本地存储路径 |
|
||||
| `AZURE_STORAGE_CONNECTION_STRING` | Azure | 连接字符串 |
|
||||
| `AZURE_STORAGE_CONTAINER` | Azure | 容器名称 |
|
||||
| `AWS_S3_BUCKET` | S3 | 存储桶名称 |
|
||||
| `AWS_REGION` | S3 | 区域 (默认: us-east-1) |
|
||||
|
||||
## 数据增强
|
||||
|
||||
训练时支持多种数据增强策略:
|
||||
|
||||
| 增强类型 | 说明 |
|
||||
|----------|------|
|
||||
| `perspective_warp` | 透视变换 (模拟扫描角度) |
|
||||
| `wrinkle` | 皱纹效果 |
|
||||
| `edge_damage` | 边缘损坏 |
|
||||
| `stain` | 污渍效果 |
|
||||
| `lighting_variation` | 光照变化 |
|
||||
| `shadow` | 阴影效果 |
|
||||
| `gaussian_blur` | 高斯模糊 |
|
||||
| `motion_blur` | 运动模糊 |
|
||||
| `gaussian_noise` | 高斯噪声 |
|
||||
| `salt_pepper` | 椒盐噪声 |
|
||||
| `paper_texture` | 纸张纹理 |
|
||||
| `scanner_artifacts` | 扫描伪影 |
|
||||
|
||||
增强配置示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"augmentation": {
|
||||
"gaussian_blur": { "enabled": true, "kernel_size": 5 },
|
||||
"perspective_warp": { "enabled": true, "intensity": 0.1 }
|
||||
},
|
||||
"augmentation_multiplier": 2
|
||||
}
|
||||
```
|
||||
|
||||
## 前端功能
|
||||
|
||||
React 前端提供以下功能模块:
|
||||
|
||||
| 模块 | 功能 |
|
||||
|------|------|
|
||||
| **Dashboard** | 文档列表、上传、标注状态管理、分类筛选 |
|
||||
| **Training** | 数据集创建/管理、训练任务配置、增强设置 |
|
||||
| **Models** | 模型版本管理、激活/归档、指标查看 |
|
||||
| **Inference Demo** | 实时推理演示、结果可视化 |
|
||||
|
||||
### 启动前端
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
# 访问 http://localhost:5173
|
||||
```
|
||||
|
||||
## 技术栈
|
||||
|
||||
@@ -357,10 +543,27 @@ DB_PASSWORD=xxx pytest tests/ --cov=packages --cov-report=term-missing
|
||||
| **目标检测** | YOLOv11 (Ultralytics) |
|
||||
| **OCR 引擎** | PaddleOCR v5 (PP-OCRv5) |
|
||||
| **PDF 处理** | PyMuPDF (fitz) |
|
||||
| **数据库** | PostgreSQL + psycopg2 |
|
||||
| **数据库** | PostgreSQL + SQLModel |
|
||||
| **Web 框架** | FastAPI + Uvicorn |
|
||||
| **前端** | React + TypeScript + Vite + TailwindCSS |
|
||||
| **状态管理** | React Query (TanStack Query) |
|
||||
| **深度学习** | PyTorch + CUDA 12.x |
|
||||
| **部署** | Docker + Azure ACI (训练) / App Service (推理) |
|
||||
| **部署** | Docker + Azure/AWS (训练) / App Service (推理) |
|
||||
|
||||
## 环境变量
|
||||
|
||||
| 变量 | 必需 | 说明 |
|
||||
|------|------|------|
|
||||
| `DB_PASSWORD` | 是 | PostgreSQL 密码 |
|
||||
| `DB_HOST` | 否 | 数据库主机 (默认: localhost) |
|
||||
| `DB_PORT` | 否 | 数据库端口 (默认: 5432) |
|
||||
| `DB_NAME` | 否 | 数据库名 (默认: docmaster) |
|
||||
| `DB_USER` | 否 | 数据库用户 (默认: docmaster) |
|
||||
| `STORAGE_BASE_PATH` | 否 | 存储路径 (默认: ~/invoice-data/data) |
|
||||
| `MODEL_PATH` | 否 | 模型路径 |
|
||||
| `CONFIDENCE_THRESHOLD` | 否 | 置信度阈值 (默认: 0.5) |
|
||||
| `SERVER_HOST` | 否 | 服务器主机 (默认: 0.0.0.0) |
|
||||
| `SERVER_PORT` | 否 | 服务器端口 (默认: 8000) |
|
||||
|
||||
## 许可证
|
||||
|
||||
|
||||
Reference in New Issue
Block a user