首页
/ Docling REST API 实战指南:docling-serve HTTP 转换接口与 Python 客户端 SDK

Docling REST API 实战指南:docling-serve HTTP 转换接口与 Python 客户端 SDK

2026-09-06 13:38:09作者:冯梦姬Eddie

本文基于 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 中的 WebSocketWatcherPollingWatcher
  • 任务超时job_timeout 默认 300 秒;HTTP 层默认 3 次重试,连接超时 10 秒、读超时 60 秒;
  • 版本协商:客户端会附带 Accept-Docling-Document-Version 头,告知服务端本机 docling-core 可读取的 DoclingDocument 版本,服务端按需做向下投影;
  • 异常体系exceptions.py 定义了 TaskNotFoundErrorTaskTimeoutErrorResultNotReadyErrorResultExpiredErrorUsageLimitExceededError 等细分异常,便于在集成中做精确的错误处理。

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.pysubmit* 任务生命周期与结果目标)、batch.pysubmit_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(如 easyocrtesseract
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_apivlm_pipeline_model* 等字段在模型层已被标记为 deprecated=True,并在赋值时触发 DeprecationWarning(见 options.py 中的字段校验器)。

对于 multipart 文件上传,嵌套配置无法直接放入表单字段,ConvertDocumentsOptions 内置了一个 mode="before" 的校验器(options.py),把 JSON 字符串形式的 ocr_custom_configtable_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.pyExportDocumentResponse 定义 md_content / json_content / html_content / text_content / doctags_content 等字段;外层 DocumentResultItem 携带 statusConversionStatus)、errorstimings 与可选的 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_waitpoll_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。
登录后查看全文
热门项目推荐
相关项目推荐