note/app_prd/Document Converter Backend Service.md

216 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

这是一个为后端开发团队准备的、基于 RESTful 标准的**通用文档转换服务Universal Document Converter, UDC**的产品需求文档PRD
---
# 产品需求文档:通用文档转换服务 (UDC)
**Universal Document Converter - Backend Service**
| 文档版本 | V1.0 |
| :--- | :--- |
| **最后更新** | 2025-12-09 |
| **状态** | 待开发 |
| **涉及端** | 后端 API, 异步 Worker, 对象存储 |
---
## 1. 项目背景与目标
### 1.1 背景
在构建智能题库、知识库或 RAG检索增强生成应用时需要处理大量非结构化文档PDF, Word, Excel, 图片等)。当前的痛点在于不同格式的解析方式不统一,且由 OCR 产生的图片资源难以直接被大模型引用。
### 1.2 目标
构建一个独立、无状态、高性能的**文档转换微服务**。
* **输入**:支持 PDF, DOCX, DOC, XLSX, PPTX, JPG/PNG, Markdown。
* **核心能力**
1. **格式统一**:将异构文档转换为标准 Markdown便于 LLM 处理)。
2. **逆向生成**:将 Markdown 转换为排版精美的 DOCX/PDF便于人类阅读
3. **资产云化**:自动提取文档中的图片/公式截图,上传至 MinIO并替换 Markdown 中的链接为永久 URL。
4. **样式定制**:支持通过 Word 模板定义输出文档的排版样式。
* **输出**:标准 RESTful API提供转换结果的 JSON 数据(含 MinIO 链接)或文件流。
---
## 2. 系统架构设计
系统采用 **异步任务队列** 架构,以应对 MinerU (OCR) 等高算力消耗场景。
### 2.1 核心组件
1. **API Gateway (FastAPI)**: 接收 HTTP 请求,鉴权,文件校验,上传源文件至 MinIO `raw/` 桶,发布任务至 Redis。
2. **Task Broker (Redis)**: 维护任务队列(区分 `gpu-queue``cpu-queue`)。
3. **Worker Cluster (Celery)**:
* **GPU Worker**: 部署 MinerU (Magic-PDF),处理 PDF/Image -> Markdown。
* **CPU Worker**: 部署 Pandoc, Python-Pandas, WPS-Python-RPC。处理 Docx/Excel -> Markdown 以及 Markdown -> Docx。
4. **Storage (MinIO)**:
* `udc-raw`: 存放用户上传的原始文件生命周期1天
* `udc-assets`: 存放解析出的图片资源(永久保存)。
* `udc-results`: 存放生成的 Markdown/Docx 结果文件(永久保存)。
* `udc-templates`: 存放用户上传的 Word 样式模板。
---
## 3. 功能需求详细说明
### 3.1 核心转换逻辑 (Router Strategy)
根据输入文件类型 (`input_format`) 和目标格式 (`target_format`) 自动路由。
| 输入格式 | 目标格式 | 处理引擎/逻辑 | 资源处理 | 备注 |
| :--- | :--- | :--- | :--- | :--- |
| **PDF / Image** | Markdown | **MinerU (GPU)** | 提取截图 -> 上传 MinIO -> 替换链接 | 核心场景 |
| **DOCX** | Markdown | **Pandoc** | Extract Media -> 上传 MinIO -> 替换链接 | 保留公式 Latex |
| **DOC** | Markdown | **LibreOffice/WPS** 转 PDF -> **MinerU** | 同 PDF 流程 | 解决旧版公式问题 |
| **XLSX / XLS** | Markdown | **Pandas** | 纯文本/Markdown Table 拼接 | 忽略 Excel 内嵌图 |
| **Markdown** | DOCX | **Pandoc** (+Reference Doc) | 下载网络图 -> 嵌入 Word | 支持样式模板 |
| **Markdown** | PDF | **Pandoc** -> DOCX -> **LibreOffice** | 同上 | 间接生成 |
### 3.2 资产管理 (Asset Pipeline)
任何转换过程中产生的本地图片(如 OCR 截图、Word 中的插图),必须经过以下流水线:
1. **提取**: 解析器将图片存放在临时目录 `/tmp/task_id/images/`
2. **哈希重命名**: 计算文件 MD5重命名为 `md5.jpg` (防止重复存储)。
3. **上传**: 上传至 MinIO `udc-assets/{date}/{md5}.jpg`
4. **替换**: 在生成的 Markdown 文本中,将 `![](images/a.jpg)` 替换为 `![](https://minio.host/udc-assets/.../md5.jpg)`
### 3.3 样式模板管理
* 允许用户上传 `.docx` 文件作为“参考文档” (Reference Doc)。
* 在 Markdown -> DOCX 转换时,通过 `--reference-doc` 参数应用字体、字号、页边距等样式。
---
## 4. API 接口定义 (RESTful)
**Base URL**: `/api/v1`
### 4.1 提交转换任务
* **Endpoint**: `POST /conversions`
* **Content-Type**: `multipart/form-data`
* **Description**: 提交一个文件进行转换。
**Request Parameters:**
| 参数名 | 类型 | 必填 | 说明 |
| :--- | :--- | :--- | :--- |
| `file` | File | 是 | 二进制文件流 |
| `target_format` | String | 是 | `markdown`, `docx`, `pdf` |
| `output_mode` | String | 否 | `url` (默认,存MinIO返回链接), `archive` (返回ZIP流) |
| `template_id` | String | 否 | 仅当 `target_format=docx` 时有效指定使用的样式模板ID |
| `is_ocr` | Boolean | 否 | 默认 `false`。若为 `true`,即使是电子版 PDF 也强制走 OCR |
| `callback_url` | String | 否 | 任务完成后的 Webhook 回调地址 |
**Response (202 Accepted):**
```json
{
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"eta_seconds": 30
}
```
### 4.2 查询任务状态/结果
* **Endpoint**: `GET /conversions/{task_id}`
* **Description**: 轮询任务状态。
**Response (Processing):**
```json
{
"task_id": "...",
"status": "processing",
"progress": 45 // 0-100
}
```
**Response (Success - URL Mode):**
```json
{
"task_id": "...",
"status": "success",
"completed_at": "2025-12-09T10:00:00Z",
"result": {
// 如果目标是 Markdown直接把内容返回来方便前端预览/LLM读取
"content": "# 标题\n\n正文内容...![](https://minio.../img.jpg)",
// 结果文件的下载地址
"file_url": "https://minio.host/udc-results/task_id/result.md",
// 提取出的图片列表 (方便调试)
"images": [
"https://minio.host/udc-assets/2025/abc.jpg",
"https://minio.host/udc-assets/2025/def.png"
]
}
}
```
### 4.3 上传样式模板
* **Endpoint**: `POST /templates`
* **Content-Type**: `multipart/form-data`
* **Description**: 上传一个 `.docx` 文件作为排版模板。
**Request:** `file` (binary), `name` (string)
**Response (201 Created):**
```json
{
"template_id": "tpl_01HE...",
"name": "学校试卷标准模板",
"url": "https://minio.host/udc-templates/tpl_01HE.docx"
}
```
### 4.4 预览/下载文件 (Proxy)
* **Endpoint**: `GET /files/{bucket}/{path}`
* **Description**: (可选) 如果 MinIO 不对外直接暴露,通过此接口代理下载或预览文件。
---
## 5. 数据存储方案
### 5.1 Redis Key 设计
* `task:queue:gpu`: List, 待处理的 OCR 任务。
* `task:queue:cpu`: List, 待处理的 Office/Pandoc 任务。
* `task:status:{task_id}`: Hash, 存储任务状态、进度、结果 JSON。过期时间 24 小时。
### 5.2 MinIO Bucket 策略
* **udc-raw**: Lifecycle Rule = expire after 1 day.
* **udc-assets**: Policy = ReadOnly (Public or Signed URL).
* **udc-templates**: Policy = ReadOnly.
---
## 6. 非功能需求 (NFR)
1. **幂等性**: 对同一文件的重复上传MD5相同如果参数一致应直接返回之前的 `task_id` 或缓存结果(可选优化)。
2. **并发控制**: MinerU 极其消耗显存。需要通过 Celery 的 `worker_concurrency` 严格限制 GPU Worker 的并发数(例如 1个 GPU 对应 1-2 个并发),防止 OOM。
3. **超时处理**:
* Docx 转换超时60秒。
* PDF OCR 超时300秒视页数而定
4. **异常处理**:
* 如果 OCR 失败,应在 Response 中返回 `error_code``error_msg`
* 支持“部分成功”:如果文档有 100 页,解析到 99 页挂了,应尽量返回已解析的内容。
---
## 7. 错误码定义
| Code | Message | Description |
| :--- | :--- | :--- |
| `4001` | `unsupported_format` | 不支持的文件扩展名 |
| `4002` | `template_not_found` | 指定的 Template ID 不存在 |
| `5001` | `ocr_engine_error` | MinerU 内部错误 (显存不足或模型加载失败) |
| `5002` | `conversion_timeout` | 转换超时 |
| `5003` | `storage_error` | MinIO 上传失败 |
---
## 8. 开发阶段规划
### Phase 1: 基础框架 (CPU Worker)
* 完成 FastAPI + Redis + Celery 搭建。
* 实现 Pandoc 转换逻辑 (Docx <-> Markdown)。
* 实现 MinIO 上传与链接替换逻辑。
### Phase 2: GPU 核心 (GPU Worker)
* 集成 MinerU SDK。
* 处理 PDF 转 Markdown 流程。
* 优化大文件上传和处理超时设置。
### Phase 3: 模板与优化
* 实现 `/templates` 接口。
* 实现 Pandoc `reference-doc` 逻辑。
* Docker 镜像封装 (分离 CPU/GPU 镜像)。