深入解析 Docling Java SDK 集成:Source 与 Target 的实战应用

9 阅读17分钟

深入解析 Docling Java SDK 集成:Source 与 Target 的实战应用

前言:Docling 的两种调用方式

Docling 文档解析引擎提供了两种调用方式:

方式一:HTTP 原生请求

部署 Docling 服务后,可以直接使用 HTTP REST API 进行调用:

# 示例:使用 curl 上传文件进行解析
curl -X POST http://localhost:5001/convert \
  -H "Content-Type: multipart/form-data" \
  -F "file=@document.pdf" \
  -F "output_format=json"

这种方式适合:

  • 非 Java 项目集成
  • 跨语言调用
  • 简单验证和测试

方式二:Java SDK(推荐方案)

对于 Java 项目,Docling 官方提供了专门的 Java SDK,封装了 HTTP 请求细节:

// 使用 SDK 进行文档解析
ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(FileSource.builder()
        .filename("document.pdf")
        .base64String(base64)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

ConvertDocumentResponse response = doclingClient.convert(request);

Java SDK 的核心优势

  • 生态集成:无缝对接 Spring Boot、Micronaut 等主流框架
  • 类型安全:Builder 模式提供编译期检查,降低配置错误
  • 异常封装:统一的异常体系,便于业务层处理
  • 依赖注入:支持 Spring Bean 管理,符合现代 Java 开发范式

为什么需要深入理解 SDK 设计?

官方文档的现状是:只展示了最基础的用法示例,比如如何创建一个 ConvertDocumentRequest 并调用 convert() 方法。但对于实际项目开发需要的关键信息,文档存在明显的缺失:

缺失的 API 说明

  • FileSource 有几种构建方式?每种方式的内部实现机制是什么?
  • UrlSource 如何使用?URL 需要满足什么条件(公网可访问?需要鉴权?)
  • InBodyTarget 是唯一的 Target 类型吗?未来会有扩展吗?
  • ConvertDocumentResponse 的结构是什么?如何提取解析结果?

缺失的方法细节

  • FileSource.fromInputStream() 内部如何处理流?会自动转 Base64 吗?
  • Builder 模式的必填字段和可选字段有哪些?
  • 异常体系是什么样的?哪些异常需要业务层处理?

这些信息在官方文档中要么没提及,要么一笔带过,开发者只能通过阅读源码或反复调试来摸索。

第一个坑:Source 类型的选择

文档只列出了 FileSource.fromFile()FileSource.fromInputStream() 等方法,但没有说明什么场景用什么。新手往往会直接用 fromFile(),直到遇到 100MB 的 PDF 导致内存溢出才发现问题。实际上:

  • 小文件(< 10MB):Base64 方案简单直接
  • 上传流:fromInputStream() 更自然
  • 大文件(> 100MB):应该用 UrlSource,让 Docling 服务端直接拉取

这些边界文档没写,只能靠踩坑学习。

第二个坑:Target 的概念混淆

很多开发者看到 InBodyTarget 就理解为"上传方式",实际上它控制的是"响应返回方式"。这个误解会导致后续设计出错误的架构——比如试图通过 Target 来控制文件传输,或者不理解为什么大文件解析会阻塞 HTTP 连接。

第三个坑:文档没有提到的性能边界

Base64 编码会导致 ~33% 的数据膨胀,对于大文件来说这是显著的内存压力。但文档没有给出明确的大小阈值,开发者只能自己摸索什么时候切换到 UrlSource

本文的价值在于:帮你避开这些坑,建立正确的设计思维,而不是等你踩坑后再复盘。


认知误区:一个常见的概念陷阱

一句话模型Source = 文件从哪里来(输入)Target = 结果怎么返回(输出)

在集成 Docling Java SDK 时,很多开发者(包括笔者)都会陷入一个概念陷阱:

ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(FileSource.builder()
        .filename(filename)
        .base64String(base64)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

看到这段代码,第一反应往往是:

"FileSource 是描述文件,InBodyTarget 是实际传输方式"

或者更模糊的理解:

"InBodyTarget 决定了文件怎么传过去"

这些理解都是错误的,而且这种错误理解会导致后续架构设计出现严重偏差。


Source 和 Target 的基本理解

Docling SDK 的设计遵循了职责分离原则,将文档处理请求拆解为三个独立维度:

ConvertDocumentRequest
    ├── source   ← 输入数据(文件从哪里来)
    ├── options  ← 解析配置(如何处理)
    └── target   ← 输出结果(结果怎么回)

这个设计揭示了 Docling 的核心理念:

Source 负责:数据供给(怎么进来)
Target 负责:结果交付(怎么出去)
Options 负责:处理策略(中间过程)

Source 的四种供给方式

Source 决定了文件如何进入 Docling 处理流程。SDK 提供了四种供给方式,从手动编码到自动化处理,呈现出明显的递进关系。


1. Base64 手动编码:最基础的方式

完整调用示例

import java.net.URI;
import java.util.Base64;
import ai.docling.serve.api.DoclingServeApi;
import ai.docling.serve.api.convert.request.ConvertDocumentRequest;
import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions;
import ai.docling.serve.api.convert.request.options.OutputFormat;
import ai.docling.serve.api.convert.request.source.FileSource;
import ai.docling.serve.api.convert.request.target.InBodyTarget;
import ai.docling.serve.api.convert.response.ConvertDocumentResponse;

// 创建 Docling API 客户端
DoclingServeApi api = DoclingServeApi.builder()
    .baseUrl("http://localhost:8000")
    .logRequests()
    .logResponses()
    .prettyPrint()
    .build();

// 手动将文件读取并编码为 Base64(在内存中处理)
byte[] fileBytes = Files.readAllBytes(Paths.get("document.pdf"));
String base64 = Base64.getEncoder().encodeToString(fileBytes);

// 构建 Request,手动传入 Base64 字符串
ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(FileSource.builder()
        .filename("document.pdf")
        .base64String(base64)
        .build())
    .options(ConvertDocumentOptions.builder()
        .toFormat(OutputFormat.MARKDOWN)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

// 调用并获取结果
ConvertDocumentResponse response = api.convertSource(request);
System.out.println(response.getDocument().getMarkdownContent());

这种方式是在客户端内存中手动读取文件、编码为 Base64,然后发送给 Docling 服务。文件数据完全在客户端处理。

优点

  • 代码简单直观,易于理解
  • SDK 直接支持,无需额外处理
  • 适合已有 Base64 数据的场景(如前端上传的 Base64 字符串)

缺点

  • Base64 编码导致 ~33% 数据膨胀,增加内存压力
  • 大文件编码耗时长,阻塞上传流程
  • 编码/解码有额外 CPU 开销

适用边界:小文件(< 10MB),或已有 Base64 数据的场景。


Base64 编码对大文件的具体问题

数据膨胀问题

Base64 编码将每 3 个字节编码为 4 个字符,导致数据量增加约 33%。对于大文件,这意味着:

原始文件大小:100 MB
Base64 编码后:133 MB
内存峰值:100 MB(原始) + 133 MB(编码) + 额外开销

内存占用问题

在 Java 环境中,Base64 编码过程会导致显著的内存压力:

  1. 原始文件加载Files.readAllBytes() 将整个文件加载到内存
  2. Base64 字符串创建:编码后的字符串再次占用内存
  3. HTTP 请求构建:请求对象包含完整的 Base64 字符串

对于一个 100 MB 的文件,实际内存占用可能超过 300 MB

GC 压力问题

大字符串对象会进入 JVM 的老年代(Old Generation),导致:

  • Full GC 频繁触发
  • 应用响应时间变长
  • 可能导致 OutOfMemoryError

网络传输问题

即使服务器带宽充足,Base64 编码仍然会导致:

  • 上传时间增加 33%
  • Docling 服务端需要解码 Base64,额外消耗 CPU
  • 整体处理时间延长

实战建议

文件大小推荐方式原因
< 10MBBase64内存压力可控,实现简单
10-50MBInputStream流式处理,减少内存峰值
> 50MBHTTP URL零内存压力,生产级方案

2. InputStream:更优雅的流式供给

完整调用示例

import java.io.InputStream;
import java.net.URI;
import ai.docling.serve.api.DoclingServeApi;
import ai.docling.serve.api.convert.request.ConvertDocumentRequest;
import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions;
import ai.docling.serve.api.convert.request.options.OutputFormat;
import ai.docling.serve.api.convert.request.source.FileSource;
import ai.docling.serve.api.convert.request.target.InBodyTarget;
import ai.docling.serve.api.convert.response.ConvertDocumentResponse;

// 创建 Docling API 客户端
DoclingServeApi api = DoclingServeApi.builder()
    .baseUrl("http://localhost:8000")
    .build();

// 从上传流或文件流获取 InputStream
InputStream inputStream = new FileInputStream("document.pdf");

// 构建 Request,SDK 自动处理流数据
ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(FileSource.fromInputStream(inputStream, "document.pdf"))
    .options(ConvertDocumentOptions.builder()
        .toFormat(OutputFormat.MARKDOWN)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

// 调用并获取结果
ConvertDocumentResponse response = api.convertSource(request);
System.out.println(response.getDocument().getMarkdownContent());

// 注意:记得关闭流
inputStream.close();

这种方式让 SDK 自动处理流数据,开发者只需传入 InputStream。SDK 内部会将流转换为 Base64,但开发者无需手动处理编码细节。

优点

  • 流式读取,内存占用可控
  • SDK 内部自动转 Base64,开发者无需手动编码
  • 更符合 Java IO 编程习惯
  • 适合网络上传流、管道式处理场景

缺点

  • SDK 内部仍然会转 Base64,大文件仍有内存压力
  • 需要管理流的关闭,增加代码复杂度
  • InputStream 一旦读取完毕无法重用

适用边界:中等文件(10MB - 100MB),或网络上传流场景。


3. File 本地文件:开发调试的便捷方案

完整调用示例

import java.io.File;
import java.net.URI;
import ai.docling.serve.api.DoclingServeApi;
import ai.docling.serve.api.convert.request.ConvertDocumentRequest;
import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions;
import ai.docling.serve.api.convert.request.options.OutputFormat;
import ai.docling.serve.api.convert.request.source.FileSource;
import ai.docling.serve.api.convert.request.target.InBodyTarget;
import ai.docling.serve.api.convert.response.ConvertDocumentResponse;

// 创建 Docling API 客户端
DoclingServeApi api = DoclingServeApi.builder()
    .baseUrl("http://localhost:8000")
    .build();

// 直接传入本地 File 对象
File file = new File("document.pdf");

// 构建 Request,一行代码完成文件供给
ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(FileSource.fromFile(file))
    .options(ConvertDocumentOptions.builder()
        .toFormat(OutputFormat.MARKDOWN)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

// 调用并获取结果
ConvertDocumentResponse response = api.convertSource(request);
System.out.println(response.getDocument().getMarkdownContent());

这种方式是本地开发最便捷的选择,SDK 自动处理文件读取和 Base64 编码,开发者只需一行代码。

优点

  • 一行代码完成文件供给,极低复杂度
  • 本地批处理脚本、文件扫描任务最适用
  • SDK 自动处理文件读取和编码

缺点

  • SDK 内部仍然转 Base64,不适合大文件
  • 仅适用于本地文件系统,生产环境不推荐
  • 文件路径依赖本地环境,部署时需调整

适用边界:本地开发调试、批处理脚本,不推荐生产环境。


4. URL 远程供给:推荐的主流方案

完整调用示例

import java.net.URI;
import ai.docling.serve.api.DoclingServeApi;
import ai.docling.serve.api.convert.request.ConvertDocumentRequest;
import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions;
import ai.docling.serve.api.convert.request.options.OutputFormat;
import ai.docling.serve.api.convert.request.source.HttpSource;
import ai.docling.serve.api.convert.request.target.InBodyTarget;
import ai.docling.serve.api.convert.response.ConvertDocumentResponse;

// 创建 Docling API 客户端
DoclingServeApi api = DoclingServeApi.builder()
    .baseUrl("http://localhost:8000")
    .logRequests()
    .logResponses()
    .prettyPrint()
    .build();

// 构建 Request,传入文件的 URL(推荐方式)
ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(HttpSource.builder()
        .url(URI.create("https://arxiv.org/pdf/2408.09869"))
        .build())
    .options(ConvertDocumentOptions.builder()
        .toFormat(OutputFormat.MARKDOWN)
        .includeImages(true)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

// 调用并获取结果(Docling 服务端直接从 URL 拉取文件)
ConvertDocumentResponse response = api.convertSource(request);
System.out.println(response.getDocument().getMarkdownContent());

这是生产环境推荐的主流方案。Docling 服务端直接从 URL 拉取文件,客户端零内存压力,避开了 Base64 编码的所有问题。

优点

  • 客户端零内存压力,文件由 Docling 服务端拉取
  • 无需 Base64 编码,避免数据膨胀和内存占用问题
  • 天然支持云存储(OSS、S3、CDN)
  • 不受客户端带宽限制
  • 处理速度更快,整体延迟更低

缺点

  • URL 必须公网可访问,或需配置鉴权
  • 增加 URL 管理复杂度(生成、鉴权、过期时间)
  • 依赖云存储基础设施

适用边界生产环境推荐方案,特别是大文件(> 50MB)、云存储集成的场景。


Source 的官方支持模式

根据官方文档,SDK 实际支持两种核心 Source 类型:

HttpSource:从 URL 获取内容

HttpSource.builder()
    .url(URI.create("https://example.com/document.pdf"))
    .build()

可选配置:自定义 HTTP Headers

FileSource:将内容以 Base64 编码嵌入

FileSource.builder()
    .filename("document.pdf")
    .base64String(base64)  // Base64 编码内容
    .build()

FileSource.fromFile(file)       // SDK 自动读取并转 Base64
FileSource.fromInputStream(is)  // SDK 自动处理流并转 Base64

核心特性:FileSource 会将文件内容以 Base64 编码嵌入到请求中


SDK 内部的 Base64 转换机制详解

官方文档明确指出:FileSource 将内容以 Base64 编码嵌入到文件名中。这意味着:

三种 Base64 处理方式对比

  1. 手动 Base64 方式
byte[] fileBytes = Files.readAllBytes(Paths.get("document.pdf"));
String base64 = Base64.getEncoder().encodeToString(fileBytes);

FileSource.builder()
    .filename("document.pdf")
    .base64String(base64)
    .build()

开发者显式控制:文件读取 → Base64编码 → 传入SDK

  1. SDK 自动转换(File)
FileSource.fromFile(file)

SDK 内部处理:File读取 → Base64编码 → 嵌入请求

  1. SDK 自动转换(InputStream)
FileSource.fromInputStream(inputStream, "document.pdf")

SDK 内部处理:InputStream读取 → Base64编码 → 嵌入请求

关键区别

  • 手动方式:开发者控制编码时机和内存占用,适合已有 Base64 数据
  • SDK 自动转换:开发者无需关心编码细节,但内存占用仍存在

官方文档说明:FileSource 会将内容以 Base64 编码嵌入到请求中,这是 SDK 的内部实现机制。

大文件的核心问题:无论手动还是自动,Base64 编码都在客户端内存中进行,大文件会导致内存压力。HttpSource 是唯一避免客户端内存压力的方案(Docling 服务端直接从 URL 拉取)。


Target 的三种结果返回方式

Target 决定了解析结果如何返回给客户端。根据官方文档,SDK 支持三种 Target 类型:


1. InBodyTarget:直接返回模式(默认用例)

Target target = InBodyTarget.builder().build();

解析结果直接封装在 HTTP Response Body 中返回,这是默认的方式。

特点:

  • 同步阻塞:请求期间客户端等待
  • 即时获取:无需二次请求
  • 内存敏感:大文档结果占用客户端内存

适用场景:小文档、即时处理、同步调用场景。


2. PutTarget:服务端上传模式

Target target = PutTarget.builder()
    .url(URI.create("https://your-storage.com/upload"))
    .build();

Docling 服务端通过 HTTP PUT 将解析结果上传到指定的 URI,客户端不直接接收文档内容,而是接收上传结果。 解析结果 → Docling 服务端通过 HTTP PUT 上传到指定 URI → 返回上传结果

特点:
- 服务端上传:Docling 主动将结果上传到指定存储
- 客户端接收上传结果,不直接接收文档内容
- 适合对接云存储(OSS、S3)的场景

适用场景:需要将解析结果直接存储到云存储的场景。

---

### 3. ZipTarget:压缩返回模式

```java
Target target = ZipTarget.builder().build();

解析结果压缩为 ZIP 文件后,通过 HTTP Response Body 返回。

特点:

  • 结果压缩:减少传输数据量
  • 适合包含图片、多文档的解析结果
  • 客户端接收 ZIP 文件,需要解压处理

适用场景:包含大量图片的文档解析、批量文档处理结果。


Target 的选择策略

InBodyTarget 是默认方式。

选择建议:

  • InBodyTarget:默认选择,适合大部分场景
  • PutTarget:需要直接存储到云存储时选择
  • ZipTarget:解析结果包含大量图片或需要批量处理时选择

组合模式矩阵:Source × Target

基于 Source 和 Target 的独立维度,可组合出多种实战方案:

组合 1:Base64 + InBodyTarget(快速集成)

ConvertDocumentRequest.builder()
    .source(FileSource.builder()
        .filename("test.pdf")
        .base64String(base64)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

适用场景:原型验证、单元测试、小文件处理。


组合 2:InputStream + InBodyTarget(流式上传)

ConvertDocumentRequest.builder()
    .source(FileSource.fromInputStream(inputStream, "upload.pdf"))
    .target(InBodyTarget.builder().build())
    .build();

适用场景:Web 上传接口、管道式处理链。


组合 3:URL + InBodyTarget(大文件推荐)

ConvertDocumentRequest.builder()
    .source(UrlSource.builder()
        .url("https://oss.example.com/large-doc.pdf")
        .build())
    .target(InBodyTarget.builder().build())
    .build();

适用场景:生产级大文件处理、云存储集成。


组合 4:File + InBodyTarget(本地批处理)

ConvertDocumentRequest.builder()
    .source(FileSource.fromFile(new File("/data/batch/doc.pdf")))
    .target(InBodyTarget.builder().build())
    .build();

适用场景:后台脚本、批量索引任务。


Options 的解析配置

ConvertDocumentOptions 控制文档解析的策略和行为,是 Source/Target/Options 三维度中"中间过程"的配置层。

根据官方文档,Options 支持丰富的配置项:

核心配置项

输出格式控制

ConvertDocumentOptions.builder()
    .toFormat(OutputFormat.MARKDOWN)  // 输出为 Markdown
    .toFormat(OutputFormat.HTML)      // 输出为 HTML
    .toFormat(OutputFormat.JSON)      // 输出为 JSON 结构
    .build()

OCR 配置

ConvertDocumentOptions.builder()
    .doOcr(true)              // 开启 OCR
    .forceOcr(true)           // 强制 OCR(即使有文本层)
    .ocrEngine("tesseract")   // OCR引擎选择
    .ocrLang("en")            // OCR语言设置
    .build()

PDF 处理配置

ConvertDocumentOptions.builder()
    .pdfBackend("pypdfium")   // PDF后端选择
    .build()

表格识别配置

ConvertDocumentOptions.builder()
    .doTableStructure(true)   // 开启表格识别
    .tableMode("accurate")    // 表格识别模式
    .tableCellMatching(true)  // 表格单元格匹配
    .build()

处理范围控制

ConvertDocumentOptions.builder()
    .pipeline("standard")         // 管道选择
    .pageRange("1-10")            // 页面范围限制
    .documentTimeout(300000)      // 文档处理超时(毫秒)
    .abortOnError(false)          // 错误时是否中止
    .build()

增强功能配置

ConvertDocumentOptions.builder()
    .includeImages(true)          // 包含图片
    .imageScale(2.0)              // 图片缩放比例
    .enableCodeDetection(true)    // 代码检测
    .enableFormulaDetection(true) // 公式检测
    .build()

完整配置示例

ConvertDocumentRequest request = ConvertDocumentRequest.builder()
    .source(HttpSource.builder()
        .url(URI.create("https://arxiv.org/pdf/2408.09869"))
        .build())
    .options(ConvertDocumentOptions.builder()
        .toFormat(OutputFormat.MARKDOWN)
        .includeImages(true)
        .doOcr(true)
        .ocrLang("en")
        .doTableStructure(true)
        .pageRange("1-5")
        .documentTimeout(60000)
        .build())
    .target(InBodyTarget.builder().build())
    .build();

项目自定义 Options vs 官方 Options

很多项目会自定义 Options DTO(如本项目定义的 DoclingOptions),通常只封装核心配置项:

@Data
@Builder
public class DoclingOptions {
    @Builder.Default
    private boolean ocr = true;
    
    @Builder.Default
    private boolean tables = true;
    
    @Builder.Default
    private boolean includeImages = true;
}

对比分析

  • 项目自定义:简化配置,聚焦核心需求,易于维护
  • 官方 SDK:配置全面,适合复杂场景,但配置项繁多

建议

  • 项目初期:使用自定义 Options,快速验证功能
  • 生产环境:根据业务需求,逐步引入官方 SDK 的高级配置

常见误区纠正:为什么"上传方式 ≠ Target"

错误认知链

看到代码:.target(InBodyTarget.builder().build())
产生误解:这是控制上传方式的配置
导致问题:混淆输入和输出的职责边界

正确认知链

看到代码:.target(InBodyTarget.builder().build())
正确解读:这是控制响应返回方式的配置
关联理解:上传方式在 Source 中决定(如 base64String 字段)

为什么会产生混淆?

因为 SDK 提供了"隐式转换":

FileSource.fromFile(file)  // SDK 自动:File → Base64

开发者看到一行代码就完成了文件到传输数据的转换,容易产生错觉:

"Target 控制了文件如何传输"

但实际上:

文件读取   → FileSource 内部处理
Base64编码 → FileSource 内部处理
HTTP传输   → SDK 底层实现
结果返回   → Target 控制

职责边界非常清晰

阶段负责组件开发者可见度
文件读取FileSource可选 API
数据编码FileSource隐式执行
HTTP请求SDK底层不可见
响应解析Target可配置

系统设计层面的思考:从 API 到架构

当你正确理解 Source/Target 后,下一步的设计重点不再是"怎么写代码",而是:

1. 任务控制问题

当前痛点:
    请求同步阻塞 → 处理中无法取消
    用户上传后 → 必须等待完成才能删除文件

架构解法

  • 引入任务队列(Task Queue)
  • 支持任务取消 API
  • 异步处理 + 通知回调

2. 大文件策略问题

当前痛点:
    Base64 方案 → 大文件内存爆炸
    同步等待 → 超时风险

架构解法

  • 自动 Source 切换策略:

    file.size < 10MB  → Base64Source
    file.size < 100MB → InputStreamSource
    file.size > 100MB → UrlSource(需 OSS 支持)
    
  • 引入任务 ID + 分片上传


3. 并发安全问题

当前痛点:
    多用户同时上传 → 文件生命周期混乱
    处理中删除 → 资源竞争

架构解法

  • 文件状态机管理:

    UPLOADED → PROCESSING → COMPLETED → CLEANED
    
  • 分布式锁(Redisson)保护处理状态

  • 任务取消时清理临时资源


最佳实践总结

开发阶段建议

  1. 原型开发:使用 Base64 + InBodyTarget,快速验证逻辑
  2. 集成测试:使用 InputStream + InBodyTarget,模拟真实上传流
  3. 性能测试:使用 UrlSource + InBodyTarget,验证大文件处理能力

生产环境建议

  1. 小文件场景(< 10MB):

    FileSource.fromInputStream(uploadStream, filename)
    
  2. 大文件场景(> 100MB):

    UrlSource.builder().url(ossUrl).build()
    
  3. 批处理场景

    FileSource.fromFile(localFile)
    

架构演进建议

  1. 短期

    • 封装 Source 选择策略
    • 添加文件大小检查拦截器
  2. 中期

    • 引入任务队列
    • 支持异步处理
  3. 长期

    • 实现可取消任务系统
    • 完善文件生命周期管理

终极记忆模型

Source 解决"我给你什么",Target 解决"你怎么还我"

当你下次看到这段代码时:

.source(FileSource.builder().base64String(base64).build())
.target(InBodyTarget.builder().build())

脑海中应该立刻浮现:

输入:我用 Base64 给你文件
输出:你直接把解析结果还给我
中间:Docling 按照 options 配置处理

而不是混淆为:

错误理解1:Target 控制上传方式
错误理解2:InBodyTarget 决定文件怎么传

结语

Docling 的 Source/Target 设计职责清晰、维度独立、组合灵活。

理解这一设计,不仅让你写出正确的集成代码,更重要的是:

  • 为后续架构设计打下正确基础
  • 避免"错误认知导致错误架构"的陷阱
  • 具备从 API 层面思考系统设计的能力