12 KiB
这是一个为后端开发团队准备的、基于 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。
- 核心能力:
- 格式统一:将异构文档转换为标准 Markdown(便于 LLM 处理)。
- 逆向生成:将 Markdown 转换为排版精美的 DOCX/PDF(便于人类阅读)。
- 资产云化:自动提取文档中的图片/公式截图,上传至 MinIO,并替换 Markdown 中的链接为永久 URL。
- 样式定制:支持通过 Word 模板定义输出文档的排版样式。
- 输出:标准 RESTful API,提供转换结果的 JSON 数据(含 MinIO 链接)或文件流。
2. 系统架构设计
系统采用 异步任务队列 架构,以应对 MinerU (OCR) 等高算力消耗场景。
2.1 核心组件
- API Gateway (FastAPI): 接收 HTTP 请求,鉴权,文件校验,上传源文件至 MinIO
raw/桶,发布任务至 Redis。 - Task Broker (Redis): 维护任务队列(区分
gpu-queue和cpu-queue)。 - Worker Cluster (Celery):
- GPU Worker: 部署 MinerU (Magic-PDF),处理 PDF/Image -> Markdown。
- CPU Worker: 部署 Pandoc, Python-Pandas, WPS-Python-RPC。处理 Docx/Excel -> Markdown 以及 Markdown -> Docx。
- Storage (MinIO):
udc-raw: 存放用户上传的原始文件。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 | Pandoc -> DOCX -> LibreOffice | 同上 | 间接生成 |
3.2 资产管理 (Asset Pipeline)
任何转换过程中产生的本地图片(如 OCR 截图、Word 中的插图),必须经过以下流水线:
- 提取: 解析器将图片存放在临时目录
/tmp/task_id/images/。 - 哈希重命名: 计算文件 MD5,重命名为
md5.jpg(防止重复存储)。 - 上传: 上传至 MinIO
udc-assets/{date}/{md5}.jpg。 - 替换: 在生成的 Markdown 文本中,将
替换为。
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):
{
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"eta_seconds": 30
}
4.2 查询任务状态/结果
- Endpoint:
GET /conversions/{task_id} - Description: 轮询任务状态。
Response (Processing):
{
"task_id": "...",
"status": "processing",
"progress": 45 // 0-100
}
Response (Success - URL Mode):
{
"task_id": "...",
"status": "success",
"completed_at": "2025-12-09T10:00:00Z",
"result": {
// 如果目标是 Markdown,直接把内容返回来方便前端预览/LLM读取
"content": "# 标题\n\n正文内容...",
// 结果文件的下载地址
"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):
{
"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)
- 幂等性: 对同一文件的重复上传(MD5相同),如果参数一致,应直接返回之前的
task_id或缓存结果(可选优化)。 - 并发控制: MinerU 极其消耗显存。需要通过 Celery 的
worker_concurrency严格限制 GPU Worker 的并发数(例如 1个 GPU 对应 1-2 个并发),防止 OOM。 - 超时处理:
- Docx 转换超时:60秒。
- PDF OCR 超时:300秒(视页数而定)。
- 异常处理:
- 如果 OCR 失败,应在 Response 中返回
error_code和error_msg。 - 支持“部分成功”:如果文档有 100 页,解析到 99 页挂了,应尽量返回已解析的内容。
- 如果 OCR 失败,应在 Response 中返回
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. 技术选型
本系统采用 "AI-Native" 的开发策略,技术选型优先考虑与大模型(LLM)的兼容性、社区文档丰富度以及类型系统的完备性,以实现极致的 Vibe Coding 开发体验。
8.1 核心技术栈 (Core Stack)
| 组件 | 选型 | 版本要求 | 选型理由 |
|---|---|---|---|
| 开发语言 | Python | 3.10+ | 必须启用强类型提示 (Type Hints);MinerU/Pandas 等核心库的原生语言;LLM 生成代码质量最高。 |
| Web 框架 | FastAPI | Latest | 自动生成 OpenAPI 文档;基于 Pydantic 的类型验证是 AI 理解业务逻辑的最佳桥梁。 |
| 数据验证 | Pydantic | V2 | 通过定义 Class Schema 驱动开发,AI 可根据 Schema 自动补全业务代码。 |
| 异步队列 | Celery | Latest | 处理 PDF OCR 等长耗时任务的工业级标准;配合 Redis 使用。 |
| 包管理 | uv | Latest | 极速 Python 包管理器(比 pip 快 10-100 倍),保障开发心流不被打断。 |
| 数据库 | PostgreSQL | 14+ | 优异的 JSONB 支持(存储试题结构);pgvector 扩展方便未来做向量检索。 |
| 对象存储 | MinIO | Latest | S3 兼容协议;用于存储文档、图片及中间产物。 |
| ORM 框架 | SQLModel | Latest | 结合了 SQLAlchemy 和 Pydantic,让数据库操作与数据验证统一,降低 AI 上下文切换成本。 |
8.2 Vibe Coding 开发工作流
为确保 AI 辅助编码的准确性和可维护性,开发过程需严格遵循以下工作流:
-
Schema First (模型驱动):
- 在编写业务逻辑前,必须先定义 Pydantic Model(输入/输出数据结构)。
- 理由:一旦 Schema 定义清晰,AI 能以接近 100% 的准确率自动生成 API 接口代码和数据库迁移脚本。
-
微提交策略 (Micro-Commits):
- 原则:将 Git Commit 视为“游戏存档点”。
- 操作:每当 AI 完成一个独立功能函数(Function)或修复一个 Bug 并验证通过后,立即 Commit。
- 理由:AI 有时会产生“幻觉”改坏现有逻辑。高频提交允许开发者随时回滚到上一个“稳态”,避免代码崩坏。
-
模块化上下文 (Modular Context):
- 禁止将所有代码写在
main.py或单文件中。 - 强制按功能分包:
routers/,services/,models/,tasks/,core/。 - 理由:AI 的上下文窗口有限。模块化让开发者可以只将相关文件(如
minio_service.py)喂给 AI,从而获得更精准的代码生成。
- 禁止将所有代码写在
-
环境隔离与极速构建:
- 使用
uv venv创建虚拟环境。 - 依赖变更后立即运行
uv sync。 - 理由:保持环境纯净,避免依赖冲突导致的 AI 调试死循环。
- 使用
8.3 关键依赖库
- PDF/OCR:
magic-pdf(MinerU SDK) - 需 GPU 环境。 - Word:
pypandoc(Pandoc 包装),python-docx(后处理)。 - Excel:
pandas,openpyxl。 - LLM 交互:
openai(官方 SDK, 兼容 DeepSeek)。 - 文档生成:
jinja2(配合 Pandoc 做模板渲染)。
8.4 Git 提交规范
推荐使用 Conventional Commits 规范,以便 AI 自动生成 Changelog:
feat: add pdf parser servicefix: resolve minio upload timeoutchore: update dependencies via uvrefactor: optimize celery task structure
9. 开发阶段规划
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 镜像)。