PDF Craft Service
基于 FastAPI 的 PDF 处理服务,提供 OCR(光学字符识别)和格式转换(EPUB、Markdown)功能。
项目概述
本项目包含两个微服务:
1. pdf-ocr
需要 CUDA 支持的 OCR 服务
- 使用 AI 模型对 PDF 文件进行 OCR 识别
- 必须运行在 CUDA GPU 环境(专为阿里云函数计算 FC 设计)
- 无法在 macOS 上运行 - 需要 Linux + NVIDIA GPU
- 开发建议:直接部署到阿里云 FC 测试效果
- 如果一定要本地测试,需要准备一台有 CUDA 的设备
2. pdf-transform
纯 CPU 的 PDF 转换服务
- 将 PDF 转换为 EPUB 或 Markdown 格式
- 可以在 macOS 上运行 - 不需要 GPU
- 内部调用 OCR 服务进行 PDF 处理
- 适合本地开发和测试
3. 根目录开发环境
VSCode Python 支持
- 根目录的
pyproject.toml仅用于 IDE 集成 - 运行
poetry install让 VSCode 的 Python 能读到依赖,不报错 - 自动使用纯 CPU 版本依赖(不包含 CUDA)
- 同时也支持本地运行 pdf-transform
快速开始
环境要求
- Python 3.11+
- Poetry(依赖管理工具)
- pdf-ocr 需要:Linux + NVIDIA GPU + CUDA 支持
- pdf-transform 需要:任意系统(macOS、Linux、Windows)
安装
开发环境(macOS/Linux/Windows)
在根目录安装,用于 VSCode 支持:
poetry install
这会安装:
- CPU 版本的 PyTorch(来自 PyPI)
- FastAPI 及相关依赖
- 开发工具(pytest、httpx、pylint)
- 让 VSCode 的 IntelliSense 正常工作
使用 Conda(可选)
如果你更喜欢用 Conda 管理环境:
# 创建 Conda 环境
conda create -p ./.conda python=3.11.14
conda activate ./.conda
# 安装依赖
poetry install
验证安装:
python -c "import torch; import pdf_craft; print(f'torch: {torch.__version__}'); print('pdf_craft: OK')"
生产环境(CUDA 环境)
在 GPU 机器上安装 pdf-ocr 服务:
cd pdf-ocr
poetry install
这会从 pytorch-cu121 源安装支持 CUDA 的 PyTorch。
环境变量
通用环境变量(pdf-ocr 和 pdf-transform 共享)
| 环境变量 | 是否必需 | 默认值 | 说明 |
|---|---|---|---|
PORT |
否 | 80 |
服务监听端口,必须是有效的整数 |
VERSION |
否 | "dev" |
服务版本号,显示在 API 文档中 |
SECRET_KEY |
否 | 无 | 鉴权密钥,设置后会启用 Authorization header 验证 |
LOG_LEVEL |
否 | "INFO" |
日志级别,可选值:"DEBUG"、"INFO"、"WARNING"、"ERROR"、"CRITICAL"。设置为 "DEBUG" 可查看详细的调试日志 |
LOG_STORAGE_PATH |
否 | 无 | 日志文件存储目录,若不设置则只输出到控制台 |
WORKERS_COUNT |
否 | 1 |
Gunicorn 工作进程数量。对于 FastAPI 异步应用,建议值为 CPU 核心数(如 1 vCPU → 1 worker,2 vCPU → 2 worker,4 vCPU → 4 worker)。每个 worker 运行独立的事件循环处理并发请求。pdf-ocr 建议保持较小值避免 GPU 资源竞争。 |
WORKER_TIMEOUT |
否 | 86400 |
Gunicorn worker 超时时间(秒),默认 86400 秒(24 小时)。如果 worker 处理请求超过此时间会被强制重启。处理大文件时可能需要增加此值。 |
pdf-transform 服务独有环境变量
OCR 处理方式配置(二选一)
方式 1: 使用自建 OCR 服务(推荐用于生产环境)
| 环境变量 | 是否必需 | 默认值 | 说明 |
|---|---|---|---|
OCR_HOST |
条件必需 | 无 | pdf-ocr 服务的 URL,必须是有效的 HTTP/HTTPS URL(如:https://example.com)。与 VENDOR_API_KEY 二选一 |
方式 2: 使用第三方 Vendor API(例如 SiliconFlow)
| 环境变量 | 是否必需 | 默认值 | 说明 |
|---|---|---|---|
VENDOR_API_KEY |
条件必需 | 无 | 第三方 Vendor API 密钥。与 OCR_HOST 二选一,二者至少设置一个 |
VENDOR_URL |
否 | 无 | Vendor API 的服务 URL(可选字符串,如 https://api.siliconflow.cn/v1)。若不设置则使用默认 Vendor 服务地址 |
VENDOR_MODEL_LV0 |
否 | "deepseek-ocr" |
Vendor API 的基础模型名称(Level 0),用于默认请求 |
VENDOR_MODEL_LV1 |
否 | "deepseek-ocr" |
Vendor API 的标准模型名称(Level 1),当使用 OOMOL API 时生效 |
VENDOR_MODEL_LV2 |
否 | "deepseek-ocr" |
Vendor API 的高并发模型名称(Level 2),当并发量达到 VENDOR_L2_CONCURRENCY 阈值时自动切换 |
VENDOR_L2_CONCURRENCY |
否 | 无 | Level 2 模型切换的并发阈值(可选整数)。当全局并发请求数超过此值时,自动从 LV1 切换到 LV2 模型 |
VENDOR_TEMPERATURE |
否 | None |
Vendor API 的 temperature 参数,控制生成的随机性(可选浮点数,如 0.95) |
VENDOR_TOP_P |
否 | None |
Vendor API 的 top_p 参数,控制采样概率(可选浮点数,如 0.95) |
注意: OCR_HOST 和 VENDOR_API_KEY 必须至少设置一个:
- 如果设置了
OCR_HOST,将使用自建 OCR 服务 - 如果只设置了
VENDOR_API_KEY,将使用第三方 Vendor API(当前支持 SiliconFlow) - 如果两者都未设置,服务将无法启动
Redis 配置
| 环境变量 | 是否必需 | 默认值 | 说明 |
|---|---|---|---|
REDIS_DOMAIN |
是 | 无 | Redis 服务器域名或 IP 地址 |
REDIS_USERNAME |
是 | 无 | Redis 用户名 |
REDIS_PASSWORD |
是 | 无 | Redis 密码 |
REDIS_PORT |
是 | 无 | Redis 端口,必须是有效的整数 |
REDIS_DB |
是 | 无 | Redis 数据库编号,必须是有效的整数 |
REDIS_EXPIRE_SECONDS |
是 | 无 | Redis 键过期时间(秒),必须是有效的整数 |
开发指南
详细的开发指南请参阅 DEVELOPMENT.md。
配置环境变量
- 复制环境变量模板:
cp .env.template .env
编辑 .env 文件,填入实际配置。
本地运行 pdf-transform
python app.py
若 terminal 无法正常读取 .env 文件,可执行如下命令强制指定
set -a && source .env && set +a && python app.py
服务启动后可访问:
- API:http://localhost:3000
- API 文档:http://localhost:3000/docs
运行 pdf-ocr(需要 CUDA)
注意: 此服务需要 CUDA GPU,通常在阿里云 FC 中运行。
# 从根目录启动(会自动加载 .env 文件)
set -a && source .env && set +a && python app.py
本地测试需要:
- Linux 操作系统
- NVIDIA GPU + CUDA 12.1+
- 正确安装的 GPU 驱动
运行测试
从根目录执行:
poetry run pytest
API 接口文档
pdf-ocr 服务
GET /
健康检查和服务信息。
响应:
{
"service": "PDF Craft OCR Service",
"version": "0.1.0",
"status": "running"
}
示例:
curl https://your-ocr-service.com/
GET /health
简单的健康检查端点。
响应:
{
"status": "healthy"
}
示例:
curl https://your-ocr-service.com/health
POST /initialize
初始化 OCR 模型。该端点用于预加载 OCR 模型到内存中,加快后续 OCR 请求的处理速度。通常在服务启动后调用一次。
响应:
{
"status": "initialized",
"cost_ms": 1234.56
}
示例:
curl -X POST https://your-ocr-service.com/initialize
GET /pre-stop
预停止端点。用于优雅关闭服务,释放 GPU 设备资源。通常在容器或服务即将停止前调用。
响应:
{
"status": "disposed"
}
示例:
curl https://your-ocr-service.com/pre-stop
POST /ocr
对 PDF 文件执行 OCR,返回流式响应。
请求:
- Content-Type:
multipart/form-data - Headers:
TaskID(必需):任务唯一标识符,用于追踪任务进度和日志
- 参数:
file(必需):要处理的 PDF 文件model(可选):OCR 模型,可选值:"tiny"、"small"、"base"、"large"、"gundam",默认"gundam"max_tokens(可选):最大输入 tokens,默认0(无限制)max_output_tokens(可选):最大输出 tokens,默认0(无限制)includes_cover(可选):是否处理封面,默认trueincludes_footnotes(可选):是否处理脚注,默认trueignore_pdf_errors(可选):是否忽略 PDF 解析错误,默认false。设为true时即使 PDF 文件存在错误也会尝试继续处理ignore_ocr_errors(可选):是否忽略 OCR 识别错误,默认false。设为true时即使某些页面 OCR 失败也会继续处理其他页面max_waiting_queue_size(可选):最大等待队列大小,默认-1(无限制)。当队列已满时会返回 429 错误max_waiting_time_seconds(可选):最大等待时间(秒),默认-1(无限制)。超过等待时间会返回 408 错误
响应:
- Content-Type:
text/event-stream(服务器发送事件) - 流式 JSON 事件(每行一个,带 "data: " 前缀)
事件类型:
- 封面事件(如果 includes_cover=true)
{
"kind": "cover",
"content": "<base64编码的图片>"
}
- 页面处理中事件
{
"kind": "processing",
"page_index": 0
}
- 页面已处理事件
{
"kind": "processed",
"page_index": 0,
"cost": 1234,
"input_tokens": 5000,
"output_tokens": 1000
}
- 页面事件(每个文件会拆成多个片段)
{
"kind": "page",
"page_index": 0,
"content": "<base64编码的XML片段>"
}
- 资源事件(图片/资源,会被拆分成多个片段)
{
"kind": "asset",
"hash": "abc123",
"content": "<base64编码的图片片段>"
}
- 完成事件
{"kind": "complete"}
- 错误事件
{
"kind": "error",
"message": "错误描述"
}
错误码:
400:无效文件(不是 PDF)408:等待超时(超过max_waiting_time_seconds限制)429:队列已满(超过max_waiting_queue_size限制)500:服务器错误
示例:
# 基本调用
curl -X POST https://your-ocr-service.com/ocr \
-H "TaskID: unique-task-id-12345" \
-F "file=@document.pdf"
# 使用所有参数
curl -X POST https://your-ocr-service.com/ocr \
-H "TaskID: unique-task-id-12345" \
-F "file=@document.pdf" \
-F "model=gundam" \
-F "max_tokens=10000" \
-F "max_output_tokens=5000" \
-F "includes_cover=true" \
-F "includes_footnotes=false" \
-F "ignore_pdf_errors=false" \
-F "ignore_ocr_errors=false" \
-F "max_waiting_queue_size=100" \
-F "max_waiting_time_seconds=300"
pdf-transform 服务
GET /
健康检查和服务信息。
响应:
{
"service": "PDF Craft Transform Service",
"version": "0.1.0",
"status": "running"
}
示例:
curl https://your-transform-service.com/
GET /health
简单的健康检查端点。
响应:
{
"status": "healthy"
}
示例:
curl https://your-transform-service.com/health
GET /pre-stop
预停止端点。用于优雅关闭服务,释放并发控制资源。通常在容器或服务即将停止前调用。
响应:
{
"status": "disposed"
}
示例:
curl https://your-transform-service.com/pre-stop
POST /transform/epub
将 PDF 转换为 EPUB(电子书)格式。
请求:
- Content-Type:
multipart/form-data - Headers:
TaskID(必需):任务唯一标识符,用于追踪任务进度和日志Authorization(条件必需):Bearer token 格式的鉴权令牌。仅当服务端设置了SECRET_KEY环境变量时需要提供,格式为Bearer <your-secret-key>
- 参数:
origin_url(必需):要转换的 PDF 文件的下载 URLtarget_url(必需):转换完成后的 EPUB 文件上传 URLmodel(可选):OCR 模型,可选值:"tiny"、"small"、"base"、"large"、"gundam",默认"gundam"includes_footnotes(可选):是否处理脚注,默认trueignore_pdf_errors(可选):是否忽略 PDF 解析错误,默认false。设为true时即使 PDF 文件存在错误也会尝试继续处理ignore_ocr_errors(可选):是否忽略 OCR 识别错误,默认false。设为true时即使某些页面 OCR 失败也会继续处理其他页面inline_latex(可选):是否使用内联 LaTeX 格式输出数学公式,默认false。设为true时数学公式将以 LaTeX 格式内联在文本中ocr_workers(可选):OCR 并发处理的 worker 数量,默认1。增加此值可以提高处理速度,但会增加对 OCR 服务的并发请求压力oomol_api_key(可选):OOMOL API 密钥。配置此字段后,服务将直接连接 OOMOL 平台(https://llm.oomol.com)进行 OCR 处理并走计费系统。如果不配置此字段,服务将优先使用环境变量OCR_HOST(自建 OCR 服务)或VENDOR_API_KEY(硅基流动等第三方服务),且不会产生 OOMOL 平台费用
响应:
- Content-Type:
application/json - Body:
{
"Content-Type": "application/epub+zip",
"URL": "<上传的目标URL>"
}
错误码:
400:无效 URL 或参数401:鉴权失败(需要设置正确的 Authorization header)500:服务器错误
示例:
# 基本调用(需要 TaskID 和 Authorization)
curl -X POST https://your-transform-service.com/transform/epub \
-H "TaskID: unique-task-id-12345" \
-H "Authorization: Bearer your-secret-key" \
-F "origin_url=https://example.com/document.pdf" \
-F "target_url=https://example.com/upload/output.epub"
# 带所有参数
curl -X POST https://your-transform-service.com/transform/epub \
-H "TaskID: unique-task-id-12345" \
-H "Authorization: Bearer your-secret-key" \
-F "origin_url=https://example.com/document.pdf" \
-F "target_url=https://example.com/upload/output.epub" \
-F "model=gundam" \
-F "includes_footnotes=false" \
-F "ignore_pdf_errors=false" \
-F "ignore_ocr_errors=false" \
-F "inline_latex=true" \
-F "ocr_workers=2"
# 使用 OOMOL API 进行处理(走计费系统)
curl -X POST https://your-transform-service.com/transform/epub \
-H "TaskID: unique-task-id-12345" \
-H "Authorization: Bearer your-secret-key" \
-F "origin_url=https://example.com/document.pdf" \
-F "target_url=https://example.com/upload/output.epub" \
-F "oomol_api_key=your-oomol-api-key"
POST /transform/markdown
将 PDF 转换为 Markdown 格式(带图片),输出为 ZIP 压缩包。
请求:
- Content-Type:
multipart/form-data - Headers:
TaskID(必需):任务唯一标识符,用于追踪任务进度和日志Authorization(条件必需):Bearer token 格式的鉴权令牌。仅当服务端设置了SECRET_KEY环境变量时需要提供,格式为Bearer <your-secret-key>
- 参数:
origin_url(必需):要转换的 PDF 文件的下载 URLtarget_url(必需):转换完成后的 ZIP 文件上传 URLorigin_name(可选):原始 PDF 文件名(不含扩展名),用于生成 Markdown 文件名。若不传则自动从origin_url提取文件名。model(可选):OCR 模型,可选值:"tiny"、"small"、"base"、"large"、"gundam",默认"gundam"includes_footnotes(可选):是否处理脚注,默认trueignore_pdf_errors(可选):是否忽略 PDF 解析错误,默认false。设为true时即使 PDF 文件存在错误也会尝试继续处理ignore_ocr_errors(可选):是否忽略 OCR 识别错误,默认false。设为true时即使某些页面 OCR 失败也会继续处理其他页面inline_latex(可选):是否使用内联 LaTeX 格式输出数学公式,默认true。设为true时数学公式将以 LaTeX 格式内联在文本中。ocr_workers(可选):OCR 并发处理的 worker 数量,默认1。增加此值可以提高处理速度,但会增加对 OCR 服务的并发请求压力oomol_api_key(可选):OOMOL API 密钥。配置此字段后,服务将直接连接 OOMOL 平台(https://llm.oomol.com)进行 OCR 处理并走计费系统。如果不配置此字段,服务将优先使用环境变量OCR_HOST(自建 OCR 服务)或VENDOR_API_KEY(硅基流动等第三方服务),且不会产生 OOMOL 平台费用
响应:
- Content-Type:
application/json - Body:
{
"Content-Type": "application/zip",
"URL": "<上传的目标URL>"
}
ZIP 压缩包内容:
{原文件名}.md(根目录)images/文件夹,包含提取的图片(如果有)
错误码:
400:无效 URL 或参数401:鉴权失败(需要设置正确的 Authorization header)500:服务器错误
示例:
# 基本调用(需要 TaskID 和 Authorization)
curl -X POST https://your-transform-service.com/transform/markdown \
-H "TaskID: unique-task-id-12345" \
-H "Authorization: Bearer your-secret-key" \
-F "origin_url=https://example.com/document.pdf" \
-F "target_url=https://example.com/upload/output.zip"
# 带所有参数
curl -X POST https://your-transform-service.com/transform/markdown \
-H "TaskID: unique-task-id-12345" \
-H "Authorization: Bearer your-secret-key" \
-F "origin_url=https://example.com/document.pdf" \
-F "target_url=https://example.com/upload/output.zip" \
-F "model=gundam" \
-F "includes_footnotes=false" \
-F "ignore_pdf_errors=false" \
-F "ignore_ocr_errors=false" \
-F "inline_latex=true" \
-F "ocr_workers=2"
# 使用 OOMOL API 进行处理(走计费系统)
curl -X POST https://your-transform-service.com/transform/markdown \
-H "TaskID: unique-task-id-12345" \
-H "Authorization: Bearer your-secret-key" \
-F "origin_url=https://example.com/document.pdf" \
-F "target_url=https://example.com/upload/output.zip" \
-F "oomol_api_key=your-oomol-api-key"
Task 进度汇报和用量统计
pdf-transform 服务会将任务的实时进度和用量统计信息上报到 Redis,客户端可以通过查询 Redis 获取任务的实时状态。详细实现参见 task_status.py。
Redis 数据结构
1. 任务总体状态(Hash)
Key: pdf-craft:{task_id}
类型: Hash
| 字段名 | 数据类型 | 说明 | 更新时机 |
|---|---|---|---|
status |
String | 任务状态,可选值:pending(阻塞)、reading(读取中)、ocr(OCR处理中)、generating(生成中)、completed(已完成)、failed(失败)、aborted(已中止) |
调用 report_status() 时更新;任务完成或异常时自动更新 |
total_pages |
Integer | PDF 总页数 | 调用 report_pages() 时初始化 |
completed_pages |
Integer | 已完成页数 | 调用 report_page_completed() 时原子性累加(使用 Redis HINCRBY) |
input_tokens |
Integer | 累计输入 token 数 | 调用 report_page_completed() 时原子性累加(使用 Redis HINCRBY) |
output_tokens |
Integer | 累计输出 token 数 | 调用 report_page_completed() 时原子性累加(使用 Redis HINCRBY) |
过期时间: REDIS_EXPIRE_SECONDS(每次更新时重置)
示例查询:
# 获取任务状态
redis-cli HGET "pdf-craft:{task_id}" status
# 获取所有字段
redis-cli HGETALL "pdf-craft:{task_id}"
2. 页面详细状态(List)
Key: pdf-craft:{task_id}:pages
类型: List(每个元素是 JSON 字符串)
元素结构(JSON):
{
"status": "pending | processing | completed",
"cost_time_ms": 1234,
"input_tokens": 5000,
"output_tokens": 1000
}
| 字段名 | 数据类型 | 说明 | 更新时机 |
|---|---|---|---|
status |
String | 页面状态:pending(待处理)、processing(处理中)、completed(已完成) |
调用 report_page_status() 时更新 |
cost_time_ms |
Integer | 该页处理耗时(毫秒) | 页面处理完成时记录 |
input_tokens |
Integer | 该页输入 token 数 | 页面处理完成时记录 |
output_tokens |
Integer | 该页输出 token 数 | 页面处理完成时记录 |
过期时间: REDIS_EXPIRE_SECONDS(每次更新时重置)
初始化时机: 调用 report_pages(total_pages) 时创建,所有页面初始状态为 pending
示例查询:
# 获取所有页面状态
redis-cli LRANGE "pdf-craft:{task_id}:pages" 0 -1
# 获取第一页状态(index 0)
redis-cli LINDEX "pdf-craft:{task_id}:pages" 0
# 获取总页数
redis-cli LLEN "pdf-craft:{task_id}:pages"
使用示例
Python 查询示例:
import redis
import json
r = redis.Redis(host='your-redis-host', decode_responses=True)
task_id = 'your-task-id'
# 获取任务总体状态
task_info = r.hgetall(f"pdf-craft:{task_id}")
print(f"Status: {task_info.get('status')}")
print(f"Total Pages: {task_info.get('total_pages', 0)}")
print(f"Completed Pages: {task_info.get('completed_pages', 0)}")
print(f"Total Input Tokens: {task_info.get('input_tokens', 0)}")
print(f"Total Output Tokens: {task_info.get('output_tokens', 0)}")
# 获取页面详细状态
pages = r.lrange(f"pdf-craft:{task_id}:pages", 0, -1)
for i, page_json in enumerate(pages):
page = json.loads(page_json)
print(f"Page {i+1}: {page['status']}, Cost: {page['cost_time_ms']}ms")
监控进度示例:
import time
def monitor_task(task_id):
while True:
task_info = r.hgetall(f"pdf-craft:{task_id}")
status = task_info.get('status')
if status in ['completed', 'failed', 'aborted']:
print(f"Task {status}")
break
# 从 Hash 字段直接获取进度(更高效)
completed = int(task_info.get('completed_pages', 0))
total = int(task_info.get('total_pages', 0))
print(f"Progress: {completed}/{total} pages, Status: {status}")
time.sleep(1)
部署
容器化部署文档请参阅 DEPLOYMENT.md。
阿里云函数计算(pdf-ocr)
- 构建包含 CUDA 依赖的部署包
- 上传到阿里云 FC
- 配置 GPU 实例类型(vCPU 范围:0.05~16 核,详见 FC 实例规格)
- 设置环境变量:
PORT:服务端口(默认 80)VERSION:服务版本(默认 "dev")WORKERS_COUNT:工作进程数(建议与 vCPU 核心数相同,如 1 vCPU 设为 1,2 vCPU 设为 2)SECRET_KEY:鉴权密钥(可选)
- 获取公网 URL 用于 OCR_HOST
Docker 部署(pdf-transform)
# 构建镜像
docker build -f pdf-transform/Dockerfile -t pdf-transform .
# 运行容器(单核 CPU)
docker run -p 3000:3000 \
-e PORT=3000 \
-e WORKERS_COUNT=1 \
-e OCR_HOST=http://你的fc地址.com \
pdf-transform
# 运行容器(4 核 CPU)
docker run -p 3000:3000 \
-e PORT=3000 \
-e WORKERS_COUNT=4 \
-e OCR_HOST=http://你的fc地址.com \
pdf-transform
日志分析
分析 OCR 处理日志
项目提供了日志分析脚本,可以对 pdf-transform 服务的日志文件进行详细分析,生成包含性能统计和处理详情的报告。
使用方法
# 自动分析 ./logs 目录下最新的日志文件
python3 scripts/analyze_log.py
# 或指定日志文件路径
python3 scripts/analyze_log.py <日志文件路径>
示例
# 自动检测并分析最新日志
python3 scripts/analyze_log.py
# 输出
# No log file specified. Using latest log file: logs/2025-11-21-12-35-16.log
# Analyzing log file: logs/2025-11-21-12-35-16.log
# Generating report: report.md
# Analysis complete!
# Report saved to: report.md
# 分析指定日志文件
python3 scripts/analyze_log.py logs/2025-11-21-12-35-16.log
生成的报告内容
脚本会在项目根目录生成 report.md 文件,包含以下统计信息(按 TaskID 分组):
1. 基本信息
- PDF 总页数
- OCR Workers 并发数
2. 实际处理时长
- 并发处理总时长:从第一条日志到最后一条日志的实际时间
- 累计处理时长(假设不并发):所有页面处理时间的累加值
- 平均每页实际耗时:并发处理总时长除以已处理页数
3. 页面处理统计
- 平均时长:每页 OCR 处理的平均时间
- 中位时长:中位数时长
- 方差:时长方差
4. OCR 连接建立统计
- 最大建连时长
- 中位建连时长
- 建连次数
5. 每页转换详情
- 详细的页码、耗时、开始时间偏移表格
报告示例
## TaskID: aasdafjksdgjsdfkjsdhkhfjsjdtaskId22
### 基本信息
- **总页数**: 373
- **OCR Workers 并发数**: 2
### 实际处理时长
- **并发处理总时长**: 1315.68 秒
- **累计处理时长(假设不并发)**: 1309.46 秒
- **平均每页实际耗时**: 10.53 秒
### 页面处理统计
- **平均时长**: 10.48 秒
- **中位时长**: 10.74 秒
- **方差**: 2.80
### OCR 连接建立统计
- **最大建连时长**: 68.96 秒
- **中位建连时长**: 0.41 秒
- **建连次数**: 21
### 每页转换详情
| 页码 | 耗时(秒) | 开始时间偏移(秒) |
|------|----------|------------------|
| 1 | 8.12 | 78.69 |
| 2 | 4.12 | 82.43 |
| 3 | 17.89 | 100.34 |
...
依赖管理
版本同步
三个 pyproject.toml 文件都依赖 pdf-craft,需要保持版本一致:
检查版本一致性:
python scripts/check_pdf_craft_version.py
从根目录同步版本:
# 1. 更新根目录 pyproject.toml 中的版本
# 2. 运行同步脚本
python scripts/sync_pdf_craft_version.py
# 3. 提交所有变更的文件
许可证
详见 LICENSE 文件。
贡献
- Fork 本仓库
- 创建功能分支
- 进行修改
- 运行测试:
poetry run pytest - 检查代码风格:
poetry run pylint - 提交 Pull Request
支持
如有问题,请在项目仓库提交 issue。
Metadata
Release files for pdf-craft-service 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdf_craft_service-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / pdf_craft_service-0.1.0-py3-none-any.whl
| Download URL | pdf_craft_service-0.1.0-py3-none-any.whl |
|---|---|
| Size | 110.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f2bcd49d93805e63314461bc3fba4d07be48c8f4222cb239ceef88b1d23268e1
|
|
BLAKE2b-256 checksum How to use checksums |
0d11e3b16c16116b8c4f8fd71379f867bfd58d8cfedd325c780ebaf9ff3865d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.13.4 Darwin/25.2.0
|