# PaddleOCR-VL 高性能服务化部署 [English](README_en.md) 本目录提供一套支持并发请求处理的 **PaddleOCR-VL 系列**高性能服务化部署方案,适用于 `PaddleOCR-VL`、`PaddleOCR-VL-1.5`、`PaddleOCR-VL-1.6` 等产线版本。 > 本方案目前暂时只支持 NVIDIA GPU,对其他推理设备的支持仍在完善中。 ## 架构 ``` 客户端 → FastAPI 网关 → Triton 服务器 → vLLM 服务器 ``` | 组件     | 说明                                       | | ---------------| ----------------------------------------------------------------------------------| | FastAPI 网关 | 统一访问入口、简化客户端调用、并发控制                      | | Triton 服务器 | 版面分析模型(如 PP-DocLayoutV3)及产线串联逻辑,负责模型管理、动态批处理、推理调度 | | vLLM 服务器  | VLM,连续批处理推理                    | **Triton 模型:** | 模型 | 设备 | 说明 | |------|------|------| | `layout-parsing` | 推理设备(如 GPU) | 版面解析推理 | | `restructure-pages` | CPU | 多页结果后处理(跨页表格合并、标题层级重分配) | ## 环境要求 - x64 CPU - NVIDIA GPU,Compute Capability >= 8.0 且 < 10.0 - NVIDIA 驱动支持 CUDA 12.6 - Docker >= 19.03 - Docker Compose >= 2.0 ## 快速开始 1. 拉取 PaddleOCR 源码并切换到当前目录: ```bash git clone https://github.com/PaddlePaddle/PaddleOCR.git cd PaddleOCR/deploy/paddleocr_vl_docker/hps ``` 2. 准备必要文件: ```bash cp .env.example .env # 按需修改 .env 中的 HPS_PIPELINE_NAME bash prepare.sh ``` `prepare.sh` 会根据 `.env` 下载对应 PaddleOCR-VL 版本的高稳定性服务化部署 SDK,并写入 Triton 产线配置。 3. 启动服务: ```bash docker compose up ``` 上述命令将依次启动 3 个容器: | 服务 | 说明 | 端口 | |------|------|------| | `paddleocr-vl-api` | FastAPI 网关(对外入口) | 8080 | | `paddleocr-vl-pipeline` | 运行产线的 Triton 推理服务器 | 8000(内部) | | `paddleocr-vlm-server` | 基于 vLLM 的 VLM 推理服务 | 8080(内部) | > 首次启动会自动下载并构建镜像,耗时较长;从第二次启动起将直接使用本地镜像,启动速度更快。 ## 配置说明 ### 环境变量 复制 `.env.example` 到 `.env` 并根据需要修改。 ```bash cp .env.example .env ``` 除了通过 `.env` 文件设置,也可以直接设置环境变量,如: ```bash export HPS_MAX_CONCURRENT_INFERENCE_REQUESTS=8 ``` #### 产线与 SDK 配置 通过以下变量选择 PaddleOCR-VL 系列中的具体版本(修改后需重新执行 `prepare.sh` 并重建镜像): 本方案复用 PaddleX 的[高稳定性服务化部署](https://paddlepaddle.github.io/PaddleX/latest/pipeline_deploy/serving.html#2) SDK 作为 Triton 服务的基础模型仓库与客户端依赖,并在其基础上增加 PaddleOCR-VL 专用的 FastAPI 网关和 vLLM 服务编排。 | 变量 | 默认值 | 说明 | |------|--------|------| | `HPS_PIPELINE_NAME` | `PaddleOCR-VL-1.6` | 产线名称 | | `HPS_PADDLEX_VERSION` | `3.6` | PaddleX 版本(仅填 major.minor,如 `3.6`),同时决定 Triton 基础镜像标签(`paddlex${HPS_PADDLEX_VERSION}-gpu`)和 SDK 发布目录(`v${HPS_PADDLEX_VERSION}`),二者保持一致 | | `HPS_SDK_DIR` | `paddlex_hps_PaddleOCR-VL-1.6_sdk` | 解压后的 SDK 目录,遵循 `paddlex_hps_${HPS_PIPELINE_NAME}_sdk` | 常见配置示例: | 目标版本 | `HPS_PIPELINE_NAME` | `HPS_SDK_DIR` | |----------|-----------------|---------------| | PaddleOCR-VL-1.6 | `PaddleOCR-VL-1.6` | `paddlex_hps_PaddleOCR-VL-1.6_sdk` | | PaddleOCR-VL-1.5 | `PaddleOCR-VL-1.5` | `paddlex_hps_PaddleOCR-VL-1.5_sdk` | | PaddleOCR-VL (v1) | `PaddleOCR-VL` | `paddlex_hps_PaddleOCR-VL_sdk` | #### 网关与设备 | 变量                    | 默认值              | 说明                  | | ---------------------------------------------| ----------------------------------| -----------------------------------------| | `HPS_MAX_CONCURRENT_INFERENCE_REQUESTS`   | 16                | 推理操作(版面解析)最大并发请求数   | | `HPS_MAX_CONCURRENT_NON_INFERENCE_REQUESTS` | 64                | 非推理操作(多页重组)最大并发请求数  | | `HPS_INFERENCE_TIMEOUT`           | 600               | 请求超时时间(秒)           | | `HPS_HEALTH_CHECK_TIMEOUT`         | 5                | 健康检查超时时间(秒)         | | `HPS_VLM_URL`                | http://paddleocr-vlm-server:8080 | VLM 服务器地址 | | `HPS_LOG_LEVEL`               | INFO               | 日志级别(DEBUG, INFO, WARNING, ERROR) | | `HPS_FILTER_HEALTH_ACCESS_LOG`       | true               | 是否过滤健康检查的访问日志       | | `HPS_UVICORN_WORKERS`            | 4                | 网关 Worker 进程数           | | `HPS_DEVICE_ID`               | 0                | 使用的推理设备 ID            | ### 产线配置调整 如需调整产线相关配置(如模型路径、批处理大小、部署设备等),请参考 [PaddleOCR-VL 使用教程](https://github.com/PaddlePaddle/PaddleOCR/blob/main/docs/version3.x/pipeline_usage/PaddleOCR-VL.md) 中的产线配置调整说明章节。 ## API 使用 ### 文档解析 请参考 [PaddleOCR-VL 使用教程](https://github.com/PaddlePaddle/PaddleOCR/blob/main/docs/version3.x/pipeline_usage/PaddleOCR-VL.md) 中的客户端调用相关章节。 服务支持 PDF 或图像文件(含 TIFF,多页时按页处理);多页 TIFF 请使用 `fileType=1`。 ### 健康检查 ```bash # 存活检查 curl http://localhost:8080/health # 就绪检查(验证 Triton 和 VLM 服务是否已准备好处理请求) curl http://localhost:8080/health/ready ``` ## 性能调优 ### 并发设置 网关对推理操作和非推理操作各自独立地进行并发控制: - **`HPS_MAX_CONCURRENT_INFERENCE_REQUESTS`**(默认 16):控制 `layout-parsing`(版面解析)等推理操作的并发数 - 过低(4):推理设备利用率不足,请求不必要地排队 - 过高(64):可能导致 Triton 过载,出现 OOM 或超时 - 默认值 16 允许在当前批次处理时有足够请求排队形成下一批次 - 如推理设备资源有限,建议适当降低此值 - **`HPS_MAX_CONCURRENT_NON_INFERENCE_REQUESTS`**(默认 64):控制 `restructure-pages`(多页重组)等非推理操作的并发数 - 非推理操作不占用推理设备资源,可以设置更高的并发数 - 可根据 CPU 核数和内存情况调整 **高吞吐配置示例:** ```bash # .env HPS_MAX_CONCURRENT_INFERENCE_REQUESTS=32 HPS_MAX_CONCURRENT_NON_INFERENCE_REQUESTS=128 HPS_UVICORN_WORKERS=8 ``` **低延迟配置示例:** ```bash # .env HPS_MAX_CONCURRENT_INFERENCE_REQUESTS=8 HPS_MAX_CONCURRENT_NON_INFERENCE_REQUESTS=32 HPS_INFERENCE_TIMEOUT=300 HPS_UVICORN_WORKERS=2 ``` ### Worker 进程数 每个 Uvicorn Worker 是独立的进程,有自己的事件循环: - **1 个 Worker**:简单,但受限于单进程 - **4 个 Worker**:适合大多数场景 - **8+ 个 Worker**:适用于高并发、大量小请求的场景 ### Triton 动态批处理 Triton 自动将请求批处理以提高推理设备利用率。最大批处理大小通过模型配置文件中的 `max_batch_size` 参数控制(默认:8),配置文件位于模型仓库目录下的 `config.pbtxt`(如 `model_repo/layout-parsing/config.pbtxt`)。 ### Triton 实例数 每个 Triton 模型的并行推理实例数通过 `config.pbtxt` 中的 `instance_group` 配置(默认:1)。增加实例数可以提高并行处理能力,但会占用更多设备资源。 ``` # model_repo/layout-parsing/config.pbtxt instance_group [ { count: 1 # 实例数,增大可提高并行度 kind: KIND_GPU gpus: [ 0 ] } ] ``` 实例数与动态批处理之间存在权衡: - **单实例(`count: 1`)**:动态批处理会将多个请求合并为一个批次并行执行,但同批次的请求需等待最慢的那个完成后才能一起返回,可能导致部分请求的时延升高。同时,单实例同一时刻只能处理一个批次,当前批次未完成时后续请求只能排队等待。适合显存有限或请求耗时较均匀的场景 - **多实例(`count: 2+`)**:多个实例可以同时各自处理不同的批次,能够同时处理更多请求,减少排队等待时间,单个请求的时延也会有所改善。但需注意,同一实例内的批次仍然遵循动态批处理的行为(批内请求一起开始、一起结束)。每增加一个实例会额外占用一份版面分析模型的显存,同时也会增加对 VLM 推理服务的负载以及内存和 CPU 的使用,需根据推理设备的资源情况酌情设置 非推理模型(如 `restructure-pages`)运行在 CPU 上,可根据 CPU 核数适当增加实例数。 ## 故障排查与解决 ### 服务无法启动 查看各服务的日志以定位问题: ```bash docker compose logs paddleocr-vl-api docker compose logs paddleocr-vl-pipeline docker compose logs paddleocr-vlm-server ``` 常见原因包括端口被占用、推理设备不可用或镜像拉取失败。 ### 超时错误 - 增加 `HPS_INFERENCE_TIMEOUT`(针对复杂文档) - 如果推理设备过载,减少 `HPS_MAX_CONCURRENT_INFERENCE_REQUESTS` ### 内存/显存不足 - 减少 `HPS_MAX_CONCURRENT_INFERENCE_REQUESTS` - 确保每个推理设备只运行一个服务 - 检查 compose.yaml 中的 `shm_size`(默认:4GB)