Docling REST API 实战指南:docling-serve HTTP 转换接口与 Python 客户端 SDK
本文基于 Docling 仓库中 REST API 文档 编写,系统讲解 docling-serve HTTP 服务的完整端点体系(同步/异步转换、状态轮询、WebSocket 订阅)、认证机制与响应格式,并结合仓库内置的 Python 客户端 SDK(docling/service_client/)与请求/响应数据模型(docling/datamodel/service/)给出源码级佐证。读完本文,你可以直接用 curl 或 Python 客户端对接一个正在运行的 docling-serve 实例,完成从 URL、文件上传到批量转换的完整工作流,并理解各转换选项的默认值与底层数据结构。
1. 定位与适用前提
docling-serve 是 Docling 的 FastAPI 服务封装,将 Docling 的文档转换能力以 REST API 形式对外暴露。典型使用场景是:从任意语言(包括 Python)通过 HTTP 调用 Docling,或让多个应用共享同一个转换服务。
使用前提与约定(以当前仓库文档为准):
- 需要一个正在运行的 docling-serve 端点——自托管部署可参考 部署文档,或使用托管服务;
- 本文示例面向本地服务
http://localhost:5001;在托管服务(如 Docling for IBM watsonx)上使用时,替换为你的服务基础 URL 与密钥; - 完整的交互式 schema 始终可在任意运行中的服务上通过
/docs(OpenAPI / Swagger)查看; - 当前文档页与 docling-serve v1.21.0 版本保持同步(文档头部明确标注 "Synced from docling-serve v1.21.0"),涉及该版本的行为细节均以仓库内容为准。
2. 端点总览
docling-serve 的转换与任务端点如下表所示:
| 端点 | 方法 | 用途 |
|---|---|---|
/v1/convert/source |
POST | 从 URL / base64 数据源转换(同步) |
/v1/convert/file |
POST | 转换上传的文件,multipart(同步) |
/v1/convert/source/async、/v1/convert/file/async |
POST | 提交异步任务 |
/v1/status/poll/{task_id} |
GET | 轮询任务状态 |
/v1/status/ws/{task_id} |
WebSocket | 订阅任务状态 |
/v1/result/{task_id} |
GET | 获取已完成任务的结果 |
从源码结构看,这些端点背后的请求体由 docling/datamodel/service/requests.py 中的 Pydantic 模型定义:ConvertSourcesRequest(即文档中 /v1/convert/source 的请求体)由 options(转换选项)、sources(数据源列表,以 kind 字段区分子类型)与 target(输出目标)三部分组成;sources 支持 file(base64 内联文件)与 http(URL)两种 kind,其中 http 源会被明确拒绝 .zip URL。
3. 认证
如果服务端设置了 DOCLING_SERVE_API_KEY,则每个请求都必须携带该密钥:
-H "X-Api-Key: <YOUR_KEY>"
在 Python 客户端中,这一机制体现得非常直接:docling/service_client/client.py 中,DoclingServiceClient 构造函数在传入 api_key 参数时会自动把 X-Api-Key 头注入到 HTTP 客户端和 WebSocket 连接的头信息中,无需手动拼装。
4. Python 客户端 SDK
Docling 自带了 API server 的 Python 客户端,不必手工拼 HTTP 调用。它接收服务 URL 和可选 API key,返回与本地 DocumentConverter 相同的 ConversionResult:
from docling.service_client import DoclingServiceClient
from docling.datamodel.service.options import ConvertDocumentsOptions
with DoclingServiceClient(url="http://localhost:5001") as client:
result = client.convert(
source="https://arxiv.org/pdf/2501.17887",
options=ConvertDocumentsOptions(to_formats=["md"]),
)
print(result.document.export_to_markdown())
source 接受 HTTP/HTTPS URL 字符串、本地 pathlib.Path,或 DocumentStream(以及 HttpSourceRequest);多输入使用 convert_all(source=[...]) 以流式方式产出多个转换结果。options 即下文第 5 节所示的转换选项。
4.1 客户端的源码级细节
结合 client.py 的实现,有几个值得了解的默认行为:
convert():单文档转换,内部走_convert_single();若返回状态不属于SUCCESS_CONVERSION_STATUSES(即success/partial_success)且raises_on_error=True(默认),会抛出ConversionError;convert_all():并发批量转换,max_concurrency默认 8(DEFAULT_MAX_CONCURRENCY),上限 512(MAX_CONCURRENCY_LIMIT);客户端会自动在提交选项中附加 JSON 输出格式,以便把服务端返回重建为DoclingDocument;- 状态监听:客户端默认使用 WebSocket 监听任务状态(
status_watcher=WEBSOCKET),并支持ws_fallback_to_poll=True自动回退为轮询——对应 watchers.py 中的WebSocketWatcher与PollingWatcher; - 任务超时:
job_timeout默认 300 秒;HTTP 层默认 3 次重试,连接超时 10 秒、读超时 60 秒; - 版本协商:客户端会附带
Accept-Docling-Document-Version头,告知服务端本机 docling-core 可读取的 DoclingDocument 版本,服务端按需做向下投影; - 异常体系:exceptions.py 定义了
TaskNotFoundError、TaskTimeoutError、ResultNotReadyError、ResultExpiredError、UsageLimitExceededError等细分异常,便于在集成中做精确的错误处理。
4.2 环境变量与示例脚本
仓库中 docs/examples/service_client/ 提供了一组可直接运行的示例脚本,它们都从环境或 .env 文件读取与服务端一致的变量(与 docling convert-remote CLI 相同):
DOCLING_SERVICE_URL=https://your-docling-service.example.com
DOCLING_SERVICE_API_KEY=your-api-key # 服务未认证时可省略
只安装客户端(不装完整模型栈)的方式:
pip install "docling-slim[service-client]"
convert.py 展示了与本地 DocumentConverter 同构的调用形态:
with DoclingServiceClient(
url=os.environ["DOCLING_SERVICE_URL"],
api_key=os.environ.get("DOCLING_SERVICE_API_KEY", ""),
) as client:
# 单文档
result = client.convert(source=SINGLE)
print(result.document.export_to_markdown()[:500])
# 多文档并发转换
for result in client.convert_all(source=MANY, max_concurrency=4):
print(result.input.file.name, result.status.value)
同目录下的 tasks.py(submit* 任务生命周期与结果目标)、batch.py(submit_batch() 内置/插件源与产物目标)、chunk.py(切分文档)分别覆盖任务 API、批量与切分场景,可作为深入阅读的材料。
5. 转换选项(通用子集)
在 JSON 请求体中,转换选项放在 options 字段下。文档列出的是通用子集,权威且完整的 schema 始终是运行中服务的 /docs OpenAPI 文档。
| 选项 | 含义 |
|---|---|
from_formats / to_formats |
输入 / 输出格式(见 支持的格式) |
image_export_mode |
图片导出方式(placeholder / embedded / referenced) |
do_ocr / force_ocr |
启用 / 强制 OCR |
ocr_preset / ocr_lang |
OCR 预设与语言(ocr_engine 已弃用——优先用 ocr_preset) |
table_mode |
表格结构模式(fast / accurate) |
pdf_backend |
PDF 解析后端 |
pipeline |
处理流水线(如 standard / VLM) |
| enrichment 开关 | code、formula、picture classification/description、chart |
这些选项对应的 Python 模型是 docling/datamodel/service/options.py 中的 ConvertDocumentsOptions,其中每个字段都带有默认值,客户端不传时即采用这些默认:
| 字段 | 默认值 | 说明 |
|---|---|---|
from_formats |
全部输入格式 | 默认可接受所有受支持的输入格式 |
to_formats |
[markdown] |
默认输出 Markdown |
image_export_mode |
placeholder |
图片导出模式 |
do_ocr |
True |
默认启用 OCR 处理位图内容 |
force_ocr |
False |
是否用 OCR 文本覆盖已有文本层 |
ocr_preset |
auto |
OCR 引擎预设 ID(如 easyocr、tesseract) |
pdf_backend |
threaded_docling_parse |
PDF 解析后端 |
table_mode |
accurate |
表格结构模式 |
pipeline |
standard |
处理流水线 |
page_range |
全部页 | 页码从 1 开始,可只转换部分页 |
do_table_structure |
True |
是否提取表格结构 |
do_code_enrichment / do_formula_enrichment / do_picture_classification / do_chart_extraction / do_picture_description |
False |
各类增强开关,默认均关闭 |
此外,options 支持预设 + 自定义配置的两段式模型选择模式:每个处理阶段(VLM 流水线、picture description、code/formula、table structure、layout、picture classification)都有对应的 *_preset(按名选择预设,如 "default"、"granite_docling"、"smolvlm")与 *_custom_config(完整自定义模型规格)字段;旧的 picture_description_local / picture_description_api、vlm_pipeline_model* 等字段在模型层已被标记为 deprecated=True,并在赋值时触发 DeprecationWarning(见 options.py 中的字段校验器)。
对于 multipart 文件上传,嵌套配置无法直接放入表单字段,ConvertDocumentsOptions 内置了一个 mode="before" 的校验器(options.py),把 JSON 字符串形式的 ocr_custom_config、table_structure_custom_config 等字段自动解码回 dict——这正是 multipart 请求中选项可以照常携带嵌套对象的原因。
6. 请求示例
6.1 转换一个 URL(异步)
curl -X POST "http://localhost:5001/v1/convert/source/async" \
-H "Content-Type: application/json" \
-d '{"http_sources": [{"url": "https://arxiv.org/pdf/2501.17887"}]}'
同步调用使用 /v1/convert/source,请求体相同。
6.2 上传文件(multipart)
/v1/convert/file 端点接受一个或多个 multipart/form-data 文件,选项以表单字段形式传入:
curl -X POST "http://localhost:5001/v1/convert/file" \
-H "Content-Type: multipart/form-data" \
-F "files=@2206.01062v1.pdf;type=application/pdf" \
-F "from_formats=pdf" \
-F "to_formats=md" \
-F "do_ocr=true" \
-F "image_export_mode=embedded" \
-F "table_mode=fast"
6.3 Base64 内联上传
不想走 multipart 时,可以 POST 到 /v1/convert/source 并带上 file_sources。大文件场景建议先把请求体写入临时文件,再用 -d @file 传入,避免 shell 报 "Argument list too long":
# 1. base64-encode the file
B64_DATA=$(base64 -w 0 /path/to/document.pdf)
# 2. build the request body
cat > /tmp/request_body.json <<EOF
{
"file_sources": [{ "base64_string": "${B64_DATA}", "filename": "document.pdf" }]
}
EOF
# 3. POST the request
curl -X POST "http://localhost:5001/v1/convert/source" \
-H "Content-Type: application/json" \
-d @/tmp/request_body.json
从源码结构看,base64 文件的载体是 docling/datamodel/service/sources.py 中的 FileSource 模型(base64_string + filename),服务端收到后通过 to_document_stream() 解码为 DocumentStream 再进入转换流程;文档名(filename)决定了格式推断与输出文件命名。
7. 响应格式
单文件转换返回 JSON:
{
"document": {
"md_content": "",
"json_content": {},
"html_content": "",
"text_content": "",
"doctags_content": ""
},
"status": "success", // success | partial_success | skipped | failure
"processing_time": 0.0,
"timings": {},
"errors": []
}
- 只有通过
to_formats请求的*_content字段会被填充; processing_time单位为秒;启用 profiling 后timings携带各组件明细;- 如果请求的是 zip 目标(target),或任务产出多个文件,则响应是 zip 归档而非 JSON。
对应的 wire 模型在 docling/datamodel/service/responses.py:ExportDocumentResponse 定义 md_content / json_content / html_content / text_content / doctags_content 等字段;外层 DocumentResultItem 携带 status(ConversionStatus)、errors、timings 与可选的 confidence 分数快照。客户端侧则按该 schema 严格反序列化,schema 不匹配时抛出 ResponseSchemaMismatchError。
8. 异步 API
两个转换端点都有 /async 变体。提交后返回任务描述符:
{
"task_id": "<task_id>",
"task_status": "pending", // pending | started | success | failure
"task_position": 1,
"task_meta": null
}
轮询直到完成——GET /v1/status/poll/{task_id}:
import time
import httpx
base_url = "http://localhost:5001/v1"
task = response.json() # from the /async submission
while task["task_status"] not in ("success", "failure"):
task = httpx.get(f"{base_url}/status/poll/{task['task_id']}").json()
time.sleep(5)
订阅:通过 WebSocket /v1/status/ws/{task_id} 获取推送式更新(消息为 JSON,message 取值 connection | update | error,附带任务对象)。
取回:任务完成后 GET /v1/result/{task_id} 获取结果。
使用 Python 客户端时无需手写上述轮询循环:客户端内置 PollingWatcher(可配置 poll_server_wait、poll_client_interval)与 WebSocketWatcher(连接失败自动回退轮询),submit() / submit_and_retrieve_each() 等方法会在任务终态时自动取回产物——convert_all 内部也是通过"提交 + 监听 + 取回"这套异步骨架实现的。
9. Picture description(图片描述增强)
开启图片描述(image captioning)增强时,用 picture_description_preset(命名预设)或 picture_description_custom_config(完全控制)选择模型。模型既可本地(进程内)运行,也可经由远程 OpenAI 兼容 API 端点运行;远程方式要求启动服务时设置 DOCLING_SERVE_ENABLE_REMOTE_SERVICES=true。
注意:旧参数
picture_description_local/picture_description_api在 docling-serve v1.21.0 已弃用——请迁移到picture_description_preset/picture_description_custom_config。这一点在仓库模型层同样有代码佐证:两个旧字段均带deprecated=True标记,且设置了互斥校验(二者只能设其一)。
picture-description 选项详见 增强功能文档,可用模型见 模型目录;整页 VLM 转换模型参见 视觉模型。
10. 延伸阅读
围绕本主题,仓库中以下路径可继续深入:
- API server 总览:选型对比(API server / 本地 Python 库 / Jobkit / MCP)与工作方式;
- 部署 与 托管服务:如何获得一个运行中的端点、配置计算引擎(进程内 / Redis 队列)与 API key;
- 客户端 SDK 示例:
convert.py(高层转换)、tasks.py(任务生命周期)、batch.py(批量与产物目标)、chunk.py(切分); - docling/service_client/:客户端实现、异常体系与状态监听器;
- docling/datamodel/service/:请求、响应、数据源、目标与选项的完整 Pydantic schema;
- 更多使用示例:转换、增强、RAG 集成等更多 recipe。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00