Skip to main content

A RESTful API service for PDF operations using FastAPI

Project description

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_HOSTVENDOR_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

配置环境变量

  1. 复制环境变量模板:
    cp .env.template .env
    

编辑 .env 文件,填入实际配置。

本地运行 pdf-transform

python app.py

若 terminal 无法正常读取 .env 文件,可执行如下命令强制指定

set -a && source .env && set +a && python app.py

服务启动后可访问:

运行 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(可选):是否处理封面,默认 true
    • includes_footnotes(可选):是否处理脚注,默认 true
    • ignore_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: " 前缀)

事件类型:

  1. 封面事件(如果 includes_cover=true)
{
  "kind": "cover",
  "content": "<base64编码的图片>"
}
  1. 页面处理中事件
{
  "kind": "processing",
  "page_index": 0
}
  1. 页面已处理事件
{
  "kind": "processed",
  "page_index": 0,
  "cost": 1234,
  "input_tokens": 5000,
  "output_tokens": 1000
}
  1. 页面事件(每个文件会拆成多个片段)
{
  "kind": "page",
  "page_index": 0,
  "content": "<base64编码的XML片段>"
}
  1. 资源事件(图片/资源,会被拆分成多个片段)
{
  "kind": "asset",
  "hash": "abc123",
  "content": "<base64编码的图片片段>"
}
  1. 完成事件
{"kind": "complete"}
  1. 错误事件
{
  "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 文件的下载 URL
    • target_url(必需):转换完成后的 EPUB 文件上传 URL
    • model(可选):OCR 模型,可选值:"tiny""small""base""large""gundam",默认 "gundam"
    • includes_footnotes(可选):是否处理脚注,默认 true
    • ignore_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 文件的下载 URL
    • target_url(必需):转换完成后的 ZIP 文件上传 URL
    • origin_name(可选):原始 PDF 文件名(不含扩展名),用于生成 Markdown 文件名。若不传则自动从 origin_url 提取文件名。
    • model(可选):OCR 模型,可选值:"tiny""small""base""large""gundam",默认 "gundam"
    • includes_footnotes(可选):是否处理脚注,默认 true
    • ignore_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)

  1. 构建包含 CUDA 依赖的部署包
  2. 上传到阿里云 FC
  3. 配置 GPU 实例类型(vCPU 范围:0.05~16 核,详见 FC 实例规格
  4. 设置环境变量:
    • PORT:服务端口(默认 80)
    • VERSION:服务版本(默认 "dev")
    • WORKERS_COUNT:工作进程数(建议与 vCPU 核心数相同,如 1 vCPU 设为 1,2 vCPU 设为 2)
    • SECRET_KEY:鉴权密钥(可选)
  5. 获取公网 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 文件。

贡献

  1. Fork 本仓库
  2. 创建功能分支
  3. 进行修改
  4. 运行测试:poetry run pytest
  5. 检查代码风格:poetry run pylint
  6. 提交 Pull Request

支持

如有问题,请在项目仓库提交 issue。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pdf_craft_service-0.1.0-py3-none-any.whl (110.0 kB view details)

Uploaded Python 3

File details

Details for the file pdf_craft_service-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pdf_craft_service-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 110.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.4 Darwin/25.2.0

File hashes

Hashes for pdf_craft_service-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f2bcd49d93805e63314461bc3fba4d07be48c8f4222cb239ceef88b1d23268e1
MD5 b9e2b4078e76ce8c6f5af469781bff24
BLAKE2b-256 0d11e3b16c16116b8c4f8fd71379f867bfd58d8cfedd325c780ebaf9ff3865d3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page