1. 部署目标
客户内网只提供 PaddleOCR-VL-1.6-0.9B 基础 VLM 推理服务,未提供完整的 PaddleOCR-VL 文档解析流水线和 PP-OCRv6 服务。现场需补齐:
PaddleOCR-VL:本地完成版面检测、区域裁剪和结果组装,调用客户 VLM 识别区域内容。
PP-OCRv6:本地完成文字检测、文本行方向判断和文字识别,对外提供
/ocr。
本方案已在 Windows 11、Docker Desktop/WSL2 和 RTX 4060 8 GB 环境完成容器启动与接口连通验证。
2. 组件关系
flowchart LR
backend["DTEmpower SPC 后端"]
subgraph local["本机 Docker / GPU 0"]
ppapi["PaddleX 服务<br/>POST /ocr"]
pp["PP-OCRv6<br/>检测 → 方向判断 → 识别"]
vlapi["PaddleX 服务<br/>POST /layout-parsing"]
layout["PP-DocLayoutV3<br/>版面检测"]
paddle["PaddlePaddle GPU"]
cuda["CUDA / cuDNN"]
gpu["RTX 4060"]
ppapi --> pp --> paddle
vlapi --> layout --> paddle
paddle --> cuda --> gpu
end
subgraph customer["客户内网"]
vlm["PaddleOCR-VL-1.6-0.9B<br/>VLM 推理服务"]
end
backend -->|"30606"| ppapi
backend -->|"31606"| vlapi
layout -->|"区域图片 + 提示词"| vlm
vlm -->|"识别内容"| vlapi
PP-OCRv6 与 PaddleOCR-VL 相互独立。两者都由 PaddleX 发布服务,并通过 PaddlePaddle 使用本机 GPU;客户 VLM 运行在远程服务,不占用本机显存。
3. 环境与目录
3.1 环境要求
Windows 11 + Docker Desktop/WSL2,或 Linux Docker Engine + Compose。
NVIDIA GPU 和兼容驱动;Linux 还需 NVIDIA Container Toolkit。
客户 VLM 能从 PaddleOCR-VL 容器访问。
端口 30606、31606 可用。
Docker 数据盘至少预留 30 GB。
Windows 无需单独安装 CUDA Toolkit,CUDA/cuDNN 已包含在 GPU 镜像中。
3.2 部署目录
D:\study\work\dainqi\
├─ paddleocr-vl\
│ ├─ compose.yaml
│ └─ pipeline_config.yaml
└─ ppocr-paddlex\
├─ .dockerignore
├─ Dockerfile
├─ compose.yaml
└─ ocr_config.yaml
Compose 未指定宿主机 IP,Docker 会监听所有网卡。其他机器可通过宿主机内网 IP 访问,现场需按网络策略放行 30606 和 31606 端口。
4. 部署 PaddleOCR-VL
4.1 镜像
ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleocr-vl@sha256:6c735bdf9e758ffdd58ccc067db0c2d84e37e5e6a2cbd47156069d4d7ea5d709
镜像摘要对应 2026-09-16 查询到的官方 latest-nvidia-gpu-offline 内容,用摘要可避免标签更新导致环境变化。
4.2 配置客户 VLM
修改 pipeline_config.yaml:
genai_config:
backend: vllm-server
server_url: "https://customer-vlm.example.internal/v1"
max_concurrency: 1
client_kwargs:
model_name: "paddleocr-vl-1.6"
api_key: "REPLACE_WITH_CUSTOMER_API_KEY"
server_url 填兼容 OpenAI 接口的 Base URL,即以 /v1 结尾,不填写 /chat/completions。API Key 仅保存在现场受控配置中。使用内部 CA 时,还需把 CA 证书加入容器信任库。
4.3 启动
cd D:\study\work\dainqi\paddleocr-vl
docker compose config --quiet
docker compose pull
docker compose up -d
docker compose logs -f --tail 100
完整 Compose 和流水线配置见附录 A。
5. 部署 PP-OCRv6
5.1 镜像与模型
自定义镜像 local/paddlex-ppocrv6:3.7.0-gpu 基于已固定摘要的官方 VL GPU 镜像构建,安装 PaddleOCR 3.7.0、PaddleX 3.7.2 和 Serving 依赖。复用 VL 镜像只为减少基础镜像下载,PP-OCRv6 运行时不依赖 VL 服务。
流水线加载以下模型:
PP-OCRv6_medium_detPP-LCNet_x1_0_textline_oriPP-OCRv6_medium_rec
ocr_config.yaml 中 use_textline_orientation 必须为 true,并与调用参数一致。Serving.extra.max_num_input_imgs: null 取消服务端输入图片数量上限,避免长 PDF 的 VL 与 PP-OCR 处理页数不一致;实际页数仍应按显存和处理时长限制。
5.2 构建与启动
cd D:\study\work\dainqi\ppocr-paddlex
docker compose config --quiet
docker compose build --progress=plain
docker compose up -d
docker compose logs -f --tail 100
模型缓存卷挂载到 /home/paddleocr/.paddlex,容器重建后可复用已下载模型。完整配置见附录 B。
6. 验证
docker ps --filter name=ppocr-api-v6 --filter name=paddleocr-vl-api
Invoke-RestMethod http://127.0.0.1:30606/health
Invoke-RestMethod http://127.0.0.1:31606/health
docker exec ppocr-api-v6 python -c "import paddle,paddleocr,paddlex; print(paddle.__version__); print(paddleocr.__version__); print(paddlex.__version__); print(paddle.device.cuda.device_count())"
nvidia-smi
docker stats --no-stream ppocr-api-v6 paddleocr-vl-api
/health 只验证服务进程存活。验收时还需使用真实图片或 PDF 分别调用 /ocr 和 /layout-parsing,确认模型输出、客户 VLM 鉴权及网络均正常,并检查两个服务同时运行时是否发生显存溢出。
7. 完全内网交付
联网制品机需完成以下工作:
构建并验证 PP-OCRv6 镜像。
固定 PaddleOCR-VL 镜像摘要。
将 PP-OCRv6 模型放入最终镜像,或备份
/home/paddleocr/.paddlex对应命名卷。验证两个容器在无公网环境冷启动。
通过内网镜像仓库分发,或导出镜像和 SHA-256 校验文件。
docker save -o paddlex-ppocrv6-3.7.0-gpu.tar local/paddlex-ppocrv6:3.7.0-gpu
docker save -o paddleocr-vl-1.6-gpu-offline.tar ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleocr-vl@sha256:6c735bdf9e758ffdd58ccc067db0c2d84e37e5e6a2cbd47156069d4d7ea5d709
Get-FileHash *.tar -Algorithm SHA256
docker load -i paddlex-ppocrv6-3.7.0-gpu.tar
docker load -i paddleocr-vl-1.6-gpu-offline.tar
docker save 不包含命名卷数据。若模型仍在卷中,必须单独备份卷。
8. 常见故障
9. 验收与参考
验收至少覆盖:
图片和多页 PDF 的
/ocr、/layout-parsing请求。客户 VLM 的网络、证书、鉴权和模型名。
两个服务同时运行时的显存峰值。
容器重建和无公网冷启动。
官方文档:
附录 A. PaddleOCR-VL 完整配置
目录:D:\study\work\dainqi\paddleocr-vl
A.1 compose.yaml
services:
paddleocr-vl-api:
image: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleocr-vl@sha256:6c735bdf9e758ffdd58ccc067db0c2d84e37e5e6a2cbd47156069d4d7ea5d709
container_name: paddleocr-vl-api
ports:
- "31606:8080"
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["0"]
capabilities: [gpu]
shm_size: "2g"
user: root
restart: unless-stopped
volumes:
- ./pipeline_config.yaml:/home/paddleocr/pipeline_config.yaml:ro
command:
- paddlex
- --serve
- --pipeline
- /home/paddleocr/pipeline_config.yaml
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 300s
A.2 pipeline_config.yaml
pipeline_name: PaddleOCR-VL-1.6
batch_size: 64
use_queues: True
use_doc_preprocessor: False
use_layout_detection: True
use_chart_recognition: False
use_seal_recognition: False
format_block_content: False
merge_layout_blocks: True
markdown_ignore_labels:
- number
- footnote
- header
- header_image
- footer
- footer_image
- aside_text
SubModules:
LayoutDetection:
module_name: layout_detection
model_name: PP-DocLayoutV3
model_dir: null
batch_size: 8
threshold: 0.3
layout_nms: True
layout_unclip_ratio: [1.0, 1.0]
layout_merge_bboxes_mode:
0: "union"
1: "union"
2: "union"
3: "large"
4: "union"
5: "large"
6: "large"
7: "union"
8: "union"
9: "union"
10: "union"
11: "union"
12: "union"
13: "union"
14: "union"
15: "large"
16: "union"
17: "large"
18: "union"
19: "union"
20: "union"
21: "union"
22: "union"
23: "union"
24: "union"
VLRecognition:
module_name: vl_recognition
model_name: PaddleOCR-VL-1.6-0.9B
model_dir: null
batch_size: 4096
genai_config:
backend: vllm-server
server_url: "REPLACE_WITH_CUSTOMER_VLM_URL"
max_concurrency: 1
client_kwargs:
model_name: "paddleocr-vl-1.6"
api_key: "REPLACE_WITH_CUSTOMER_API_KEY"
SubPipelines:
DocPreprocessor:
pipeline_name: doc_preprocessor
batch_size: 8
use_doc_orientation_classify: True
use_doc_unwarping: True
SubModules:
DocOrientationClassify:
module_name: doc_text_orientation
model_name: PP-LCNet_x1_0_doc_ori
model_dir: null
batch_size: 8
DocUnwarping:
module_name: image_unwarping
model_name: UVDoc
model_dir: null
Serving:
extra:
max_num_input_imgs: null
附录 B. PP-OCRv6 完整配置
目录:D:\study\work\dainqi\ppocr-paddlex
B.1 Dockerfile
# 复用已有官方 PaddleOCR-VL GPU 镜像,避免重复下载超大基础镜像。
FROM ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleocr-vl@sha256:6c735bdf9e758ffdd58ccc067db0c2d84e37e5e6a2cbd47156069d4d7ea5d709
USER root
ARG PADDLEOCR_VERSION=3.7.0
ARG PADDLEX_VERSION=3.7.2
RUN python -m pip install --no-cache-dir --upgrade \
"paddleocr==${PADDLEOCR_VERSION}" \
"paddlex[ocr-core]==${PADDLEX_VERSION}" \
&& paddlex --install serving
WORKDIR /app
CMD ["paddlex", \
"--serve", \
"--pipeline", "/app/ocr_config.yaml", \
"--device", "gpu:0", \
"--host", "0.0.0.0", \
"--port", "8080"]
B.2 compose.yaml
services:
ppocr-api:
build:
context: .
dockerfile: Dockerfile
args:
PADDLEOCR_VERSION: "3.7.0"
PADDLEX_VERSION: "3.7.2"
image: local/paddlex-ppocrv6:3.7.0-gpu
container_name: ppocr-api-v6
ports:
- "30606:8080"
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["0"]
capabilities: [gpu]
shm_size: "2gb"
user: root
restart: unless-stopped
environment:
PADDLE_PDX_MODEL_SOURCE: BOS
volumes:
- ./ocr_config.yaml:/app/ocr_config.yaml:ro
- ppocr-v6-model-cache:/home/paddleocr/.paddlex
command:
- paddlex
- --serve
- --pipeline
- /app/ocr_config.yaml
- --device
- gpu:0
- --host
- 0.0.0.0
- --port
- "8080"
healthcheck:
test:
- CMD-SHELL
- >-
python -c "import urllib.request;
urllib.request.urlopen('http://127.0.0.1:8080/health', timeout=5)"
interval: 20s
timeout: 10s
retries: 10
start_period: 600s
volumes:
ppocr-v6-model-cache:
B.3 ocr_config.yaml
pipeline_name: OCR
text_type: general
use_doc_preprocessor: false
use_textline_orientation: true
SubPipelines:
DocPreprocessor:
pipeline_name: doc_preprocessor
use_doc_orientation_classify: false
use_doc_unwarping: false
SubModules:
DocOrientationClassify:
module_name: doc_text_orientation
model_name: PP-LCNet_x1_0_doc_ori
model_dir: null
DocUnwarping:
module_name: image_unwarping
model_name: UVDoc
model_dir: null
SubModules:
TextDetection:
module_name: text_detection
model_name: PP-OCRv6_medium_det
model_dir: null
limit_side_len: 64
limit_type: min
max_side_limit: 4000
thresh: 0.3
box_thresh: 0.6
unclip_ratio: 1.5
TextLineOrientation:
module_name: textline_orientation
model_name: PP-LCNet_x1_0_textline_ori
model_dir: null
batch_size: 6
TextRecognition:
module_name: text_recognition
model_name: PP-OCRv6_medium_rec
model_dir: null
batch_size: 6
score_thresh: 0.0
Serving:
visualize: false
extra:
max_num_input_imgs: null
B.4 .dockerignore
.git
.idea
.vscode
*.log
models