Mobile wallpaper
1664 字
8 分钟

PaddleOCR-VL 模型部署备忘录

2026-01-27
浏览量 加载中...
WARNING

吐槽

PaddleOCR 的文档从 2021 年写得稀巴烂,到 2026 年了,依旧他妈的稀巴烂。各种依赖冲突、版本不兼容、文档和实际代码对不上,浪费了我整整 4 个小时。写这篇文章就是为了让后来者少踩坑,因为指望百度更新文档是不可能的。

架构说明#

PaddleOCR-VL 的部署需要两个独立的服务配合运行

  1. vLLM 后端服务(端口 8118):负责 VL 模型的高性能推理
  2. PaddleX Serving 前端服务(端口 8000):负责文档预处理、版面分析,并调用 vLLM 后端
用户请求 → PaddleX Serving (8000) → vLLM Backend (8118)
返回 OCR 结果

前置条件#

  • Linux 服务器(本文以 Ubuntu 为例)
  • NVIDIA GPU(需要 CUDA 支持)
  • 足够的显存(建议 8GB+)

Step 1:安装 uv 包管理器#

为什么用 uv?因为 pip 在处理 Paddle 这种依赖地狱的时候慢得要死,uv 至少能让你在绝望中少等一会儿。

Terminal window
# 下载并安装 uv
# ⚠️ 替换:版本号 0.9.27 可根据需要更换为最新版本
wget https://speed.oo9.dpdns.org/gh/astral-sh/uv/releases/download/0.9.27/uv-x86_64-unknown-linux-gnu.tar.gz
tar -zxf uv-x86_64-unknown-linux-gnu.tar.gz
mv uv-x86_64-unknown-linux-gnu/* /usr/local/bin
# 创建工作目录
mkdir -p /paddle

Step 2:部署 vLLM 后端服务(端口 8118)#

必须先启动这个服务,因为 PaddleX Serving 依赖它。

Terminal window
cd /paddle
# 创建 vLLM 专用虚拟环境
# ⚠️ 替换:Python 版本可根据需要调整,推荐 3.10-3.12
uv venv .venv_vllm --python 3.12
source .venv_vllm/bin/activate
# 先装 pip(是的,uv 环境里还得装 pip,因为后面的脚本依赖它)
uv pip install pip
# 安装 PaddleOCR
uv pip install -U "paddleocr[doc-parser]"
# 安装 Flash Attention(加速推理的关键)
# ⚠️ 替换:根据你的 CUDA 和 PyTorch 版本选择对应的 wheel
# 这里是 CUDA 12.8 + PyTorch 2.8 + Python 3.12 的版本
# 其他版本请去 https://github.com/mjun0812/flash-attention-prebuild-wheels/releases 找
uv pip install https://speed.oo9.dpdns.org/gh/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.3.14/flash_attn-2.8.2+cu128torch2.8-cp312-cp312-linux_x86_64.whl
# 安装 vLLM 依赖
paddleocr install_genai_server_deps vllm
# 安装 transformers(版本很重要,不要乱改)
uv pip install transformers==4.57.6
# 安装 Python 开发头文件(编译某些依赖需要)
# ⚠️ 替换:python3.12-dev 根据你的 Python 版本调整
apt update && apt install -y python3.12-dev
# 启动 vLLM 服务
# ⚠️ 替换:
# - --model_name → 可选模型:PaddleOCR-VL-0.9B、PaddleOCR-VL-2B 等
# - --port 8118 → vLLM 后端端口,需要和 PaddleOCR-VL.yaml 中的配置一致
paddlex_genai_server --model_name PaddleOCR-VL-0.9B --backend vllm --port 8118
WARNING

Flash Attention 的坑

Flash Attention 的预编译 wheel 对 CUDA、PyTorch、Python 版本有严格要求。如果版本不匹配,要么安装失败,要么运行时 segfault。

百度的文档?不存在的。他们只会告诉你 pip install flash-attn,然后让你自己编译 2 小时,最后还可能失败。

建议直接去 mjun0812 的预编译仓库 找对应版本。

Step 3:部署 PaddleX Serving 前端服务(端口 8000)#

新开一个终端,部署前端服务。

Terminal window
cd /paddle
# 创建 PaddleX 专用虚拟环境(不要和 vLLM 环境混用!)
# ⚠️ 替换:Python 版本可根据需要调整
uv venv .venv_paddle --python 3.12
source .venv_paddle/bin/activate
# 安装 PaddlePaddle GPU 版本
# ⚠️ 替换:cu126 表示 CUDA 12.6,根据你的 CUDA 版本选择对应的包
# 可选:cu118(CUDA 11.8)、cu120(CUDA 12.0)、cu126(CUDA 12.6)
uv pip install paddlepaddle-gpu==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
# 安装 PaddleOCR
uv pip install -U "paddleocr[doc-parser]" pip
# 安装 PaddleX Serving 组件
paddlex --install serving
# 启动服务
# ⚠️ 替换:
# - gpu:0 → 改为你的 GPU 设备号,多卡可用 gpu:0,1
# - --port 8000 → 改为你想要的端口号
paddlex --serve --device gpu:0 --pipeline PaddleOCR-VL --port 8000
NOTE

关于 CUDA 版本

查看你的 CUDA 版本:nvcc --versionnvidia-smi

百度的文档根本不会告诉你这些,你得自己去 PaddlePaddle 官网 找对应的安装命令。而且官网的安装命令还经常和实际的包名对不上,真是谢谢您嘞。

Step 4:配置 PaddleOCR-VL.yaml(可选)#

如果你需要自定义配置(比如调整 batch_size、阈值等),可以覆盖默认的配置文件。

/root/miniconda3/lib/python3.12/site-packages/paddlex/configs/pipelines/
# ⚠️ 替换:路径中的 python3.12 根据你的 Python 版本调整
# 如果你用的是 uv venv,路径类似:/paddle/.venv_paddle/lib/python3.12/site-packages/paddlex/configs/pipelines/
cp /root/PaddleOCR-VL.yaml /paddle/.venv_paddle/lib/python3.12/site-packages/paddlex/configs/pipelines/ -r

配置文件内容如下:

PaddleOCR-VL.yaml
# ⚠️ 替换:server_url 中的端口需要和 vLLM 服务端口一致
pipeline_name: PaddleOCR-VL
batch_size: 64
use_queues: True
use_doc_preprocessor: True
use_layout_detection: True
use_chart_recognition: False
format_block_content: False
SubModules:
LayoutDetection:
module_name: layout_detection
model_name: PP-DocLayoutV2
model_dir: null
batch_size: 8
threshold:
0: 0.5 # abstract
1: 0.5 # algorithm
2: 0.5 # aside_text
3: 0.5 # chart
4: 0.5 # content
5: 0.4 # formula
6: 0.4 # doc_title
7: 0.5 # figure_title
8: 0.5 # footer
9: 0.5 # footer
10: 0.5 # footnote
11: 0.5 # formula_number
12: 0.5 # header
13: 0.5 # header
14: 0.5 # image
15: 0.4 # formula
16: 0.5 # number
17: 0.4 # paragraph_title
18: 0.5 # reference
19: 0.5 # reference_content
20: 0.45 # seal
21: 0.5 # table
22: 0.4 # text
23: 0.4 # text
24: 0.5 # vision_footnote
layout_nms: True
layout_unclip_ratio: [1.0, 1.0]
layout_merge_bboxes_mode:
0: "union" # abstract
1: "union" # algorithm
2: "union" # aside_text
3: "large" # chart
4: "union" # content
5: "large" # display_formula
6: "large" # doc_title
7: "union" # figure_title
8: "union" # footer
9: "union" # footer
10: "union" # footnote
11: "union" # formula_number
12: "union" # header
13: "union" # header
14: "union" # image
15: "large" # inline_formula
16: "union" # number
17: "large" # paragraph_title
18: "union" # reference
19: "union" # reference_content
20: "union" # seal
21: "union" # table
22: "union" # text
23: "union" # text
24: "union" # vision_footnote
VLRecognition:
module_name: vl_recognition
model_name: PaddleOCR-VL-0.9B
model_dir: null
batch_size: 2048
genai_config:
backend: vllm-server
# ⚠️ 替换:这里的端口必须和 Step 2 中 vLLM 服务的端口一致
server_url: http://127.0.0.1:8118/v1
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

Step 5:测试服务#

两个服务都启动后,可以用以下 Python 代码测试:

import requests
import base64
from concurrent.futures import ThreadPoolExecutor, as_completed
# ⚠️ 替换:改为你的 PaddleX Serving 地址和端口
API_URL = "http://localhost:8000/layout-parsing"
# ⚠️ 替换:改为你的 PDF 文件路径
with open('xxxx.pdf', 'rb') as f:
data = f.read()
content = base64.b64encode(data).decode("ascii")
def test_ocr(file_data, file_type=0):
headers = {
"Content-Type": "application/json"
}
payload = {
"file": file_data,
"fileType": file_type,
"useDocOrientationClassify": True,
"useLayoutDetection": True,
"useDocUnwarping": True,
"useChartRecognition": True,
"repetitionPenalty": 1,
"temperature": 0.1,
"topP": 1,
"minPixels": 147384,
"maxPixels": 2822400,
"layoutNms": True,
"visualize": False
}
response = requests.post(API_URL, json=payload, headers=headers)
return response.json()
# 并发测试
with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(test_ocr, content, 0) for _ in range(10)]
for future in as_completed(futures):
try:
result = future.result()
print("OCR 处理完成")
except Exception as e:
print(f"OCR 处理失败: {e}")

需要根据实际情况替换的部分汇总#

参数说明示例值
uv 版本uv 包管理器版本号0.9.27
Python 版本虚拟环境 Python 版本3.12
CUDA 版本 (PaddlePaddle)PaddlePaddle 对应的 CUDA 版本cu126(CUDA 12.6)
Flash Attention wheel预编译的 FA 包 URL根据 CUDA/PyTorch/Python 版本选择
python-dev 包名Python 开发头文件包python3.12-dev
vLLM 端口vLLM 后端服务端口8118
PaddleX Serving 端口前端服务端口(对外暴露)8000
GPU 设备号使用的 GPU 编号gpu:0gpu:0,1
模型名称PaddleOCR-VL 模型版本PaddleOCR-VL-0.9B
YAML 配置路径PaddleOCR-VL.yaml 的位置根据 Python 环境路径调整
server_urlYAML 中 vLLM 服务地址http://127.0.0.1:8118/v1

最后#

如果你按照这篇文章还是跑不起来,那大概率是版本又变了。去骂百度吧,反正他们也不会改文档的。

祝你好运。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

评论区

目录