openai-java

GitHub
1.4k 219 简单 1 次阅读 昨天Apache-2.0语言模型开发框架
AI 解读 由 AI 自动生成,仅供参考

openai-java 是 OpenAI 官方推出的 Java 语言开发库,旨在帮助开发者轻松地在 Java 应用中集成 OpenAI 的强大能力。它封装了复杂的 REST API 调用细节,让程序员无需手动处理 HTTP 请求、参数构建或响应解析,即可直接通过简洁的代码调用 GPT 等模型进行文本生成、对话交互等操作。

对于使用 Java 技术栈的团队或个人开发者而言,openai-java 解决了原生调用接口繁琐、易出错且维护成本高的问题。它支持通过环境变量或系统属性灵活配置密钥与组织信息,并兼容主流的 Gradle 和 Maven 构建工具,安装便捷。此外,该库不仅覆盖了最新的 Responses API,也长期支持经典的 Chat Completions API,确保新旧项目都能平滑接入。

其技术亮点在于类型安全的 API 设计,利用 Java 的强类型特性在编译期即可发现潜在错误,同时提供完整的 Javadoc 文档和丰富的示例代码,大幅降低学习门槛。无论是需要快速原型验证的研究人员,还是致力于构建企业级 AI 应用的工程师,openai-java 都是连接 Java 生态与前沿大模型的理想桥梁。

使用场景

某金融科技公司后端团队正在构建一个基于 Java 的实时智能客服系统,需要让系统能够理解用户复杂的理财咨询并生成专业回复。

没有 openai-java 时

  • 开发人员必须手动拼接繁琐的 HTTP REST 请求报文,处理 JSON 序列化与反序列化极易出错,代码冗余且难以维护。
  • 每次调用 API 都需要重复编写鉴权逻辑(如 Header 设置、密钥管理),缺乏统一的安全配置入口,存在密钥泄露风险。
  • 面对 OpenAI 复杂的响应结构(如流式输出、错误码解析),需自行编写大量底层解析代码,导致新功能开发周期被严重拉长。
  • 缺乏类型安全支持,参数传递依赖字符串硬编码,编译期无法发现模型名称或参数类型的错误,线上故障排查困难。

使用 openai-java 后

  • 通过简洁的 Builder 模式构建请求(如 ChatCompletionCreateParams.builder()),SDK 自动处理底层 HTTP 通信与 JSON 转换,代码量减少 70%。
  • 利用 OpenAIOkHttpClient.fromEnv() 一键加载环境变量完成鉴权配置,统一管理 API Key 与组织 ID,显著提升系统安全性。
  • 直接调用强类型的 client.chat().completions().create() 方法获取结构化对象,内置完善的异常处理机制,快速实现流式回复功能。
  • 享受完整的 IDE 智能提示与编译期检查,模型版本(如 ChatModel.GPT_5_2)和参数校验在编码阶段即可完成,大幅降低运行时错误。

openai-java 将复杂的 API 交互转化为优雅的 Java 原生体验,让开发团队能专注于业务逻辑创新而非底层通信细节。

运行环境要求

操作系统
  • 未说明
GPU

未说明

内存

未说明

依赖
notes该工具是 Java SDK,非 Python 库,因此无 Python 版本及 GPU 显存需求。运行环境需安装 Java 8 或更高版本。支持通过 Maven 或 Gradle 引入。配置可通过环境变量(如 OPENAI_API_KEY)或系统属性完成。支持同步和异步调用,以及 Kubernetes、Azure、GCP 的工作负载身份认证。
python不适用
Java 8+
OkHttp (内置)
openai-java hero image

快速开始

OpenAI Java API 库

Maven Central javadoc

OpenAI Java SDK 为使用 Java 编写的应用程序提供了便捷的 OpenAI REST API 访问方式。

REST API 的文档可以在 platform.openai.com 上找到。Javadoc 可以在 javadoc.io 上查阅。

安装

如果您使用 Spring Boot,可以尝试 openai-java-spring-boot-starter

Gradle

implementation("com.openai:openai-java:4.32.0")

Maven

<dependency>
  <groupId>com.openai</groupId>
  <artifactId>openai-java</artifactId>
  <version>4.32.0</version>
</dependency>

要求

本库需要 Java 8 或更高版本。

使用方法

[!TIP] 请参阅 openai-java-example 目录,获取完整且可运行的示例!

与 OpenAI 模型交互的主要 API 是 Responses API。您可以通过以下代码从模型生成文本。

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;

// 使用 `OPENAI_API_KEY`、`OPENAI_ORG_ID` 和 `OPENAI_PROJECT_ID` 环境变量进行配置
OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ResponseCreateParams params = ResponseCreateParams.builder()
        .input("Say this is a test")
        .model(ChatModel.GPT_5_2)
        .build();
Response response = client.responses().create(params);

之前用于生成文本的标准(并将继续支持)是 Chat Completions API。您也可以使用该 API 通过以下代码从模型生成文本。

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

// 使用 `openai.apiKey`、`openai.orgId`、`openai.projectId`、`openai.webhookSecret` 和 `openai.baseUrl` 系统属性进行配置
// 或者使用 `OPENAI_API_KEY`、`OPENAI_ORG_ID`、`OPENAI_PROJECT_ID`、`OPENAI_WEBHOOK_SECRET` 和 `OPENAI_BASE_URL` 环境变量进行配置
OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .addUserMessage("Say this is a test")
    .model(ChatModel.GPT_5_2)
    .build();
ChatCompletion chatCompletion = client.chat().completions().create(params);

客户端配置

您可以使用系统属性或环境变量来配置客户端:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

// 使用 `openai.apiKey`、`openai.orgId`、`openai.projectId`、`openai.webhookSecret` 和 `openai.baseUrl` 系统属性进行配置
// 或者使用 `OPENAI_API_KEY`、`OPENAI_ORG_ID`、`OPENAI_PROJECT_ID`、`OPENAI_WEBHOOK_SECRET` 和 `OPENAI_BASE_URL` 环境变量进行配置
OpenAIClient client = OpenAIOkHttpClient.fromEnv();

或者手动配置:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .apiKey("My API Key")
    .build();

也可以结合两种方式:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
    // 使用 `openai.apiKey`、`openai.orgId`、`openai.projectId`、`openai.webhookSecret` 和 `openai.baseUrl` 系统属性进行配置
    // 或者使用 `OPENAI_API_KEY`、`OPENAI_ORG_ID`、`OPENAI_PROJECT_ID`、`OPENAI_WEBHOOK_SECRET` 和 `OPENAI_BASE_URL` 环境变量进行配置
    .fromEnv()
    .apiKey("My API Key")
    .build();

以下是可用选项的表格:

设置方法 系统属性 环境变量 必需 默认值
apiKey openai.apiKey OPENAI_API_KEY -
organization openai.orgId OPENAI_ORG_ID -
project openai.projectId OPENAI_PROJECT_ID -
webhookSecret openai.webhookSecret OPENAI_WEBHOOK_SECRET -
baseUrl openai.baseUrl OPENAI_BASE_URL "https://api.openai.com/v1"

系统属性优先于环境变量。

[!TIP] 不要在同一个应用程序中创建多个客户端。每个客户端都有连接池和线程池,共享这些资源可以提高效率。

修改配置

如果需要临时使用修改后的客户端配置,同时复用原有的连接池和线程池,可以在任何客户端或服务上调用 withOptions() 方法:

import com.openai.client.OpenAIClient;

OpenAIClient clientWithOptions = client.withOptions(optionsBuilder -> {
    optionsBuilder.baseUrl("https://example.com");
    optionsBuilder.maxRetries(42);
});

withOptions() 方法不会影响原始客户端或服务。

工作负载身份验证

工作负载身份验证允许在云环境(Kubernetes、Azure、GCP)中运行的应用程序使用由云提供商颁发的短期令牌进行身份验证,而不是长期有效的 API 密钥。

基本设置

import com.openai.auth.*;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

SubjectTokenProvider provider = K8sServiceAccountTokenProvider.builder().build();

WorkloadIdentity workloadIdentity = WorkloadIdentity.builder()
    .clientId("your-client-id")
    .identityProviderId("your-identity-provider-id")
    .serviceAccountId("your-service-account-id")
    .provider(provider)
    .build();

OpenAIClient client = OpenAIOkHttpClient.builder()
    .workloadIdentity(workloadIdentity)
    .build();

Kubernetes 服务账户令牌提供程序

// 使用默认令牌路径 (/var/run/secrets/kubernetes.io/serviceaccount/token)
SubjectTokenProvider provider = K8sServiceAccountTokenProvider.builder().build();
// 或者指定自定义令牌路径
SubjectTokenProvider provider = K8sServiceAccountTokenProvider.builder()
    .tokenPath("/custom/path/to/token")
    .build();

Azure 托管标识提供程序

import com.openai.auth.*;

// 使用默认值(资源:https://management.azure.com/,API 版本:2018-02-01)
SubjectTokenProvider provider = AzureManagedIdentityTokenProvider.builder()
    .build();
import com.openai.auth.*;

// 或者自定义
SubjectTokenProvider provider = AzureManagedIdentityTokenProvider.builder()
    .resource("https://management.azure.com/")
    .apiVersion("2018-02-01")
    .build();

GCP ID 令牌提供程序

import com.openai.auth.*;

SubjectTokenProvider provider = GcpIdTokenProvider.builder()
    .build();
import com.openai.auth.*;

// 或者自定义受众
SubjectTokenProvider provider = GcpIdTokenProvider.builder()
    .audience("https://api.openai.com/v1")
    .build();

请求与响应

要向 OpenAI API 发送请求,需要构建某个 Params 类的实例,并将其传递给相应的客户端方法。当收到响应时,它将被反序列化为 Java 类的一个实例。

例如,client.chat().completions().create(...) 应该使用 ChatCompletionCreateParams 的实例调用,并返回一个 ChatCompletion 的实例。

不可变性

SDK 中的每个类都配有对应的 构建器 或工厂方法来创建其实例。

每个类一旦构建完成就是 不可变的。如果类有对应的构建器,则会提供一个 toBuilder() 方法,可用于将其转换回构建器,从而创建修改后的副本。

由于每个类都是不可变的,因此对构建器的修改绝不会影响已经构建好的类实例。

异步执行

默认客户端是同步的。要切换到异步执行,可以调用 async() 方法:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.concurrent.CompletableFuture;

// 使用系统属性 openai.apiKey、openai.orgId、openai.projectId、openai.webhookSecret 和 openai.baseUrl 进行配置
// 或者使用环境变量 OPENAI_API_KEY、OPENAI_ORG_ID、OPENAI_PROJECT_ID、OPENAI_WEBHOOK_SECRET 和 OPENAI_BASE_URL 进行配置
OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .addUserMessage("Say this is a test")
    .model(ChatModel.GPT_5_2)
    .build();
CompletableFuture<ChatCompletion> chatCompletion = client.async().chat().completions().create(params);

或者从一开始就创建异步客户端:

import com.openai.client.OpenAIClientAsync;
import com.openai.client.okhttp.OpenAIOkHttpClientAsync;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.concurrent.CompletableFuture;

// 使用系统属性 openai.apiKey、openai.orgId、openai.projectId、openai.webhookSecret 和 openai.baseUrl 进行配置
// 或者使用环境变量 OPENAI_API_KEY、OPENAI_ORG_ID、OPENAI_PROJECT_ID、OPENAI_WEBHOOK_SECRET 和 OPENAI_BASE_URL 进行配置
OpenAIClientAsync client = OpenAIOkHttpClientAsync.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .addUserMessage("Say this is a test")
    .model(ChatModel.GPT_5_2)
    .build();
CompletableFuture<ChatCompletion> chatCompletion = client.chat().completions().create(params);

异步客户端支持与同步客户端相同的选项,只是大多数方法会返回 CompletableFuture 对象。

流式传输

SDK 定义了返回响应“分块”流的方法,每个分块在到达时即可单独处理,而无需等待整个响应完成。流式方法通常对应于 SSEJSONL 响应。

其中一些方法可能同时提供流式和非流式两种变体,但只要存在流式方法,其名称中就会带有 Streaming 后缀,即使没有对应的非流式版本也是如此。

这些流式方法会为同步客户端返回 StreamResponse

import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;

try (StreamResponse<ChatCompletionChunk> streamResponse = client.chat().completions().createStreaming(params)) {
    streamResponse.stream().forEach(chunk -> {
        System.out.println(chunk);
    });
    System.out.println("没有更多分块了!");
}

而对于异步客户端,则会返回 AsyncStreamResponse

import com.openai.core.http.AsyncStreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;
import java.util.Optional;

client.async().chat().completions().createStreaming(params).subscribe(chunk -> {
    System.out.println(chunk);
});

// 如果需要处理错误或流的结束
client.async().chat().completions().createStreaming(params).subscribe(new AsyncStreamResponse.Handler<>() {
    @Override
    public void onNext(ChatCompletionChunk chunk) {
        System.out.println(chunk);
    }

    @Override
    public void onComplete(Optional<Throwable> error) {
        if (error.isPresent()) {
            System.out.println("出错了!");
            throw new RuntimeException(error.get());
        } else {
            System.out.println("没有更多分块了!");
        }
    }
});

// 或者使用 Future
client.async().chat().completions().createStreaming(params)
    .subscribe(chunk -> {
        System.out.println(chunk);
    })
    .onCompleteFuture()
    .whenComplete((unused, error) -> {
        if (error != null) {
            System.out.println("出错了!");
            throw new RuntimeException(error);
        } else {
            System.out.println("没有更多分块了!");
        }
    });

异步流式传输使用一个专用于每个客户端的缓存线程池 Executor,以便在不阻塞当前线程的情况下进行流式传输。此默认配置适用于大多数场景。

若需使用其他 Executor,可通过 executor 参数配置订阅:

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

Executor executor = Executors.newFixedThreadPool(4);
client.async().chat().completions().createStreaming(params).subscribe(
    chunk -> System.out.println(chunk), executor
);

或者也可以通过 streamHandlerExecutor 方法全局配置客户端:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import java.util.concurrent.Executors;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    .streamHandlerExecutor(Executors.newFixedThreadPool(4))
    .build();

流式处理辅助工具

SDK 为流式聊天补全提供了便捷工具。一个 ChatCompletionAccumulator 可以在处理响应中的聊天补全过程块时,记录这些块并累积成一个与非流式 API 所返回的 ChatCompletion 对象类似的对象。

对于同步响应,在流管道中添加一个 Stream.peek() 调用来累积每个块:

import com.openai.core.http.StreamResponse;
import com.openai.helpers.ChatCompletionAccumulator;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionChunk;

ChatCompletionAccumulator chatCompletionAccumulator = ChatCompletionAccumulator.create();

try (StreamResponse<ChatCompletionChunk> streamResponse =
        client.chat().completions().createStreaming(createParams)) {
    streamResponse.stream()
            .peek(chatCompletionAccumulator::accumulate)
            .flatMap(completion -> completion.choices().stream())
            .flatMap(choice -> choice.delta().content().stream())
            .forEach(System.out::print);
}

ChatCompletion chatCompletion = chatCompletionAccumulator.chatCompletion();

对于异步响应,将 ChatCompletionAccumulator 添加到 subscribe() 调用中:

import com.openai.helpers.ChatCompletionAccumulator;
import com.openai.models.chat.completions.ChatCompletion;

ChatCompletionAccumulator chatCompletionAccumulator = ChatCompletionAccumulator.create();

client.chat()
        .completions()
        .createStreaming(createParams)
        .subscribe(chunk -> chatCompletionAccumulator.accumulate(chunk).choices().stream()
                .flatMap(choice -> choice.delta().content().stream())
                .forEach(System.out::print))
        .onCompleteFuture()
        .join();

ChatCompletion chatCompletion = chatCompletionAccumulator.chatCompletion();

SDK 还为流式响应提供了便捷工具。一个 ResponseAccumulator 可以在处理响应事件时记录这些事件,并累积成一个与非流式 API 所返回的 Response 对象类似的对象。

对于同步响应,在流管道中添加一个 Stream.peek() 调用来累积每个事件:

import com.openai.core.http.StreamResponse;
import com.openai.helpers.ResponseAccumulator;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseStreamEvent;

ResponseAccumulator responseAccumulator = ResponseAccumulator.create();

try (StreamResponse<ResponseStreamEvent> streamResponse =
        client.responses().createStreaming(createParams)) {
    streamResponse.stream()
            .peek(responseAccumulator::accumulate)
            .flatMap(event -> event.outputTextDelta().stream())
            .forEach(textEvent -> System.out.print(textEvent.delta()));
}

Response response = responseAccumulator.response();

对于异步响应,将 ResponseAccumulator 添加到 subscribe() 调用中:

import com.openai.helpers.ResponseAccumulator;
import com.openai.models.responses.Response;

ResponseAccumulator responseAccumulator = ResponseAccumulator.create();

client.responses()
        .createStreaming(createParams)
        .subscribe(event -> responseAccumulator.accumulate(event)
                .outputTextDelta().ifPresent(textEvent -> System.out.print(textEvent.delta())))
        .onCompleteFuture()
        .join();

Response response = responseAccumulator.response();

使用 JSON 模式的结构化输出

OpenAI 的 结构化输出 功能可确保模型始终生成符合所提供 JSON 模式 的响应。

可以通过创建一个 ResponseFormatJsonSchema 并将其设置到输入参数中来定义 JSON 模式。然而,为了更方便起见,也可以直接从任意 Java 类的结构自动生成 JSON 模式。随后,响应中的 JSON 内容将自动转换为该 Java 类的实例。使用任意 Java 类实现结构化输出的完整示例,请参阅 StructuredOutputsExample

Java 类可以包含声明为其他类实例的字段,并且可以使用集合(有关详细信息,请参阅定义 JSON 模式属性):

class Person {
    public String name;
    public int birthYear;
}

class Book {
    public String title;
    public Person author;
    public int publicationYear;
}

class BookList {
    public List<Book> books;
}

在构建参数时,将顶层类——本例中为 BookList——传递给 responseFormat(Class<T>),然后从响应中生成的消息内容中访问 BookList 的实例:

import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import com.openai.models.chat.completions.StructuredChatCompletionCreateParams;

StructuredChatCompletionCreateParams<BookList> params = ChatCompletionCreateParams.builder()
        .addUserMessage("列出一些著名的二十世纪末小说。")
        .model(ChatModel.GPT_5_2)
        .responseFormat(BookList.class)
        .build();

client.chat().completions().create(params).choices().stream()
        .flatMap(choice -> choice.message().content().stream())
        .flatMap(bookList -> bookList.books.stream())
        .forEach(book -> System.out.println(book.title + " 作者:" + book.author.name));

您可以从 ChatCompletionCreateParams.BuilderStructuredChatCompletionCreateParams.Builder 的实例开始构建参数。如果您从前者开始(这种方式代码更为简洁),当调用 ChatCompletionCreateParams.Builder.responseFormat(Class<T>) 时,构建器类型会自动切换为后者。

如果类中的某个字段是可选的,且不需要指定值,可以使用 java.util.Optional 类来表示。由 AI 模型决定是否为该字段提供值,或者将其留空。

import java.util.Optional;

class Book {
    public String title;
    public Person author;
    public int publicationYear;
    public Optional<String> isbn;
}

字段的泛型类型信息会保留在类的元数据中,但在其他作用域中则会发生“泛型类型擦除”。例如,虽然可以从具有 List<Book> 类型的 BookList.books 字段推导出描述书籍数组的 JSON 模式,但无法从相同类型的局部变量推导出有效的 JSON 模式,因此以下代码将无法正常工作:

List<Book> books = new ArrayList<>();

StructuredChatCompletionCreateParams<List<Book>> params = ChatCompletionCreateParams.builder()
        .responseFormat(books.getClass())
        // ...
        .build();

如果在将 JSON 响应转换为 Java 类实例时发生错误,错误消息中将包含原始的 JSON 响应,以帮助诊断问题。例如,如果响应被截断,JSON 数据就会不完整,从而无法转换为类实例。如果您的 JSON 响应可能包含敏感信息,请避免直接记录它,或确保从错误消息中删除任何敏感细节。

本地 JSON 模式验证

结构化输出支持 JSON Schema 语言的一个子集。系统会根据类自动生成与该子集兼容的模式。然而,由于类本身的固有结构,生成的模式仍可能违反某些 OpenAI 模式的限制,例如超过最大嵌套深度或使用不受支持的数据类型。

为便于合规性检查,responseFormat(Class<T>) 方法会对从指定类推导出的模式进行验证。此验证可确保所有限制均得到遵守。如果检测到任何问题,将抛出异常,并提供详细的失败原因说明。

  • 本地验证:验证过程在本地进行,即不会向远程 AI 模型发送请求。如果模式通过了本地验证,则很可能也能通过远程验证。
  • 远程验证:远程 AI 模型会在接收到请求中的 JSON 模式时自行进行验证。
  • 版本兼容性:有时会出现本地验证失败而远程验证成功的情况。这可能是由于 SDK 版本较旧,未能反映远程 AI 模型所执行的最新限制。
  • 禁用本地验证:如果您遇到兼容性问题并希望绕过本地验证,可以在构建参数时将 JsonSchemaLocalValidation.NO 传递给 responseFormat(Class<T>, JsonSchemaLocalValidation) 方法。(该参数的默认值为 JsonSchemaLocalValidation.YES。)
import com.openai.core.JsonSchemaLocalValidation;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import com.openai.models.chat.completions.StructuredChatCompletionCreateParams;

StructuredChatCompletionCreateParams<BookList> params = ChatCompletionCreateParams.builder()
        .addUserMessage("列出一些著名的二十世纪末小说。")
        .model(ChatModel.GPT_5_2)
        .responseFormat(BookList.class, JsonSchemaLocalValidation.NO)
        .build();

遵循这些指南,您可以确保您的结构化输出符合必要的模式要求,并最大限度地降低远程验证失败的风险。

与 Responses API 的用法

Structured Outputs 也支持 Responses API。使用方法与前面所述相同,只是 Responses API 在某些方面与 Chat Completions API 略有不同。构建参数时,将顶层类传递给 text(Class<T>),然后在响应中生成的消息内容中访问该类的实例。

你可以从 ResponseCreateParams.BuilderStructuredResponseCreateParams.Builder 的实例开始构建参数。如果你先使用前者(这种方式代码更简洁),当调用 ResponseCreateParams.Builder.text(Class<T>) 时,构建器类型会自动切换为后者。

有关 Structured Outputs 与 Responses API 结合使用的完整示例,请参阅 ResponsesStructuredOutputsExample

除了使用 ResponseCreateParams.text(Class<T>) 外,你还可以构建一个 StructuredResponseTextConfig,并通过 text(StructuredResponseTextConfig) 方法将其设置到 ResponseCreateParams 中。与使用 ResponseCreateParams 类似,你可以从 ResponseTextConfig.Builder 开始,其 format(Class<T>) 方法会将其转换为 StructuredResponseTextConfig.Builder。这样你还可以在将文本配置添加到 ResponseCreateParams 之前,设置 verbosity 配置参数。

有关 Structured OutputsResponseTextConfig 及其 verbosity 参数结合使用的完整示例,请参阅 ResponsesStructuredOutputsVerbosityExample

流式传输中的用法

Structured Outputs 也可以与 Streaming 和 Chat Completions API 一起使用。由于响应是以“块”形式返回的,因此必须先累积完整的响应,以拼接 JSON 字符串,然后再将其转换为任意 Java 类的实例。在累积 JSON 字符串的过程中,可以正常执行流式操作。

按照 Streaming helpers 部分的说明,使用 ChatCompletionAccumulator 来累积 JSON 字符串。累积完成后,使用 ChatCompletionAccumulator.chatCompletion(Class<T>) 将累积的 ChatCompletion 转换为 StructuredChatCompletion。随后,StructuredChatCompletion 可以自动将 JSON 字符串反序列化为你定义的 Java 类的实例。

有关 Structured Outputs 与 Streaming 和 Chat Completions API 结合使用的完整示例,请参阅 StructuredOutputsStreamingExample

对于 Responses API,在流式传输过程中使用 ResponseAccumulator 来累积事件。累积完成后,使用 ResponseAccumulator.response(Class<T>) 将累积的 Response 转换为 StructuredResponse。随后,StructuredResponse 可以自动将 JSON 字符串反序列化为你定义的 Java 类的实例。

有关 Structured Outputs 与 Streaming 和 Responses API 结合使用的完整示例,请参阅 ResponsesStructuredOutputsStreamingExample

定义 JSON 模式的属性

当 JSON 模式由你的 Java 类派生时,默认情况下,所有由 public 字段或 public getter 方法表示的属性都会包含在模式中。非 public 字段和 getter 方法则默认不会被包含。你可以通过分别使用 @JsonIgnore@JsonProperty 注解来排除 public 属性,或包含非 public 属性和 getter 方法(详情请参阅 注解类与 JSON 模式)。

如果你不想定义 public 字段,可以定义 private 字段并提供相应的 public getter 方法。例如,一个名为 myValueprivate 字段,搭配一个名为 getMyValue()public getter 方法,将会在 JSON 模式中生成一个 "myValue" 属性。如果你不希望使用传统的 Java “get” 前缀作为 getter 方法名,则必须使用 @JsonProperty 注解标注该方法,此时将直接使用完整的方法名作为属性名称。如果不需要 setter 方法,也可以不定义它们。

你的每个类都必须至少定义一个要包含在 JSON 模式中的属性。如果某个类没有任何字段或 getter 方法可用于派生模式属性,则会引发验证错误。这种情况可能发生在以下情形:

  • 类中既没有字段也没有 getter 方法。
  • 所有字段和 getter 方法都是 public 的,但都被标注了 @JsonIgnore
  • 所有字段和 getter 方法都是非 public 的,但都没有标注 @JsonProperty
  • 某个字段或 getter 方法声明为 Map 类型。由于 Map 被视为一个没有命名属性的独立类,因此会在 JSON 模式中生成一个空的 "properties" 字段。

注解类和 JSON 模式

你可以使用注解为从 Java 类派生的 JSON 模式添加更多信息,或者控制哪些字段或 getter 方法将包含在模式中。JSON 模式中捕获的注解细节可能会被 AI 模型用于改进其响应。SDK 支持使用 Jackson Databind 注解。

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

class Person {
    @JsonPropertyDescription("该人的名字和姓氏")
    public String name;
    public int birthYear;
    @JsonPropertyDescription("该人去世的年份,如果仍在世则为 'present'。")
    public String deathYear;
}

@JsonClassDescription("一本已出版书籍的详细信息")
class Book {
    public String title;
    public Person author;
    @JsonPropertyDescription("该书首次出版的年份。")
    public int publicationYear;
    @JsonIgnore public String genre;
}

class BookList {
    public List<Book> books;
}
  • 使用 @JsonClassDescription 为类添加详细描述。
  • 使用 @JsonPropertyDescription 为类的字段或 getter 方法添加详细描述。
  • 使用 @JsonIgnore 将类的 public 字段或 getter 方法排除在生成的 JSON 模式之外。
  • 使用 @JsonProperty 将类的非 public 字段或 getter 方法包含在生成的 JSON 模式中。

如果你使用 @JsonProperty(required = false)false 值将被忽略。OpenAI 的 JSON 模式必须将所有属性标记为 required,因此从你的 Java 类生成的模式会遵守这一限制,并忽略任何可能违反该限制的注解。

你还可以使用 OpenAPI Swagger 2@Schema@ArraySchema 注解。这些注解允许为你的模式属性添加特定于类型的约束。有关支持的约束的更多信息,请参阅 OpenAI 文档中的支持的属性部分。

import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.ArraySchema;

class Article {
    @ArraySchema(minItems = 1, maxItems = 10)
    public List<String> authors;

    @Schema(pattern = "^[A-Za-z ]+$")
    public String title;

    @Schema(format = "date")
    public String publicationDate;

    @Schema(minimum = "1")
    public int pageCount;
}

本地验证会检查你是否使用了不支持的约束关键字。然而,约束的具体值并不会在本地进行验证。例如,如果你为字符串属性的 "format" 约束使用了一个不在支持的格式名称列表中的值,那么本地验证将会通过,但 AI 模型可能会报告错误。

如果你同时使用 Jackson 和 Swagger 注解来设置同一个模式字段,Jackson 注解将优先生效。在下面的示例中,myProperty 的描述将被设置为“Jackson 描述”;“Swagger 描述”将被忽略:

import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.swagger.v3.oas.annotations.media.Schema;

class MyObject {
    @Schema(description = "Swagger 描述")
    @JsonPropertyDescription("Jackson 描述")
    public String myProperty;
}

使用 JSON 模式的函数调用

OpenAI 的 函数调用 功能使您能够将外部函数直接集成到语言模型的响应中。与生成纯文本不同,模型可以在适当的时候输出调用函数的指令(以及参数)。您需要为这些函数定义一个 JSON 模式,模型会根据该模式决定何时以及如何触发这些调用,从而实现更具交互性、数据驱动的应用程序。

通过 API 定义描述函数参数的 JSON 模式,可以构建一个包含 FunctionDefinitionChatCompletionTool,然后使用 addTool 方法将其设置到输入参数中。随后,AI 模型的响应可能包含调用您函数的请求,详细说明函数名称及其参数值,这些参数以符合函数定义中 JSON 模式的 JSON 数据形式呈现。您可以从该 JSON 中解析出参数值,调用您的函数,并将函数结果返回给 AI 模型。使用低级 API 实现完整功能的示例可在 FunctionCallingRawExample 中找到。

然而,为了更方便起见,SDK 可以根据任意 Java 类的结构自动推导出函数及其参数:类名即为函数名称,类的字段则定义了函数的参数。当 AI 模型以 JSON 形式返回参数值时,您可以轻松地将该 JSON 转换为 Java 类的实例,并利用这些参数值来调用自定义函数。使用 Java 类定义函数参数的完整示例可在 FunctionCallingExample 中查看。

结构化输出 类似,Java 类可以包含声明为其他类实例的字段,并且可以使用集合类型(有关详细信息,请参阅 定义 JSON 模式属性)。此外,还可以使用注解为函数(类)及其参数(字段)设置描述,以帮助 AI 模型理解函数的目的以及参数可能的取值范围。

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

@JsonClassDescription("获取给定 SDK 的质量评分。")
static class GetSdkQuality {
    @JsonPropertyDescription("SDK 的名称。")
    public String name;

    public SdkQuality execute() {
        return new SdkQuality(
                name, name.contains("OpenAI") ? "它非常稳健且完善!" : "*耸肩*");
    }
}

static class SdkQuality {
    public String quality;

    public SdkQuality(String name, String evaluation) {
        quality = name + ": " + evaluation;
    }
}

@JsonClassDescription("获取指定 SDK 的评分(满分 10 分)。")
static class GetSdkScore {
  public String name;

  public int execute() {
    return name.contains("OpenAI") ? 10 : 3;
  }
}

定义好函数后,使用 addTool(Class<T>) 将其添加到输入参数中,然后在 AI 模型的响应中被要求时调用它们。Function.arguments(Class<T>) 可用于将 JSON 格式的函数参数解析为定义函数的 Java 类的实例。该实例的字段将被设置为函数调用的参数值。

调用函数后,使用 ChatCompletionToolMessageParam.Builder.contentAsJson(Object) 将函数结果返回给 AI 模型。该方法会将结果转换为 JSON 格式,以便模型消费。Object 可以是任何对象,包括简单的 String 实例和基本类型的包装类。

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.*;
import java.util.Collection;

OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ChatCompletionCreateParams.Builder createParamsBuilder = ChatCompletionCreateParams.builder()
        .model(ChatModel.GPT_3_5_TURBO)
        .maxCompletionTokens(2048)
        .addTool(GetSdkQuality.class)
        .addTool(GetSdkScore.class)
        .addUserMessage("以下 SDK 的质量如何?评论者怎么说:OpenAI Java SDK、未知公司 SDK。");

client.chat().completions().create(createParamsBuilder.build()).choices().stream()
        .map(ChatCompletion.Choice::message)
        // 将每条助手消息添加到构建器中,以便我们跟踪对话,以便稍后提出后续问题。
        .peek(createParamsBuilder::addMessage)
        .flatMap(message -> {
            message.content().ifPresent(System.out::println);
            return message.toolCalls().stream().flatMap(Collection::stream);
        })
        .forEach(toolCall -> {
            Object result = callFunction(toolCall.function());
            // 将工具调用的结果添加到对话中。
            createParamsBuilder.addMessage(ChatCompletionToolMessageParam.builder()
                    .toolCallId(toolCall.id())
                    .contentAsJson(result)
                    .build());
        });

// 提出关于函数调用结果的后续问题。
createParamsBuilder.addUserMessage("你为什么这么说呢?");
client.chat().completions().create(createParamsBuilder.build()).choices().stream()
        .flatMap(choice -> choice.message().content().stream())
        .forEach(System.out::println);

static Object callFunction(ChatCompletionMessageToolCall.Function function) {
  switch (function.name()) {
    case "GetSdkQuality":
      return function.arguments(GetSdkQuality.class).execute();
    case "GetSdkScore":
      return function.arguments(GetSdkScore.class).execute();
    default:
      throw new IllegalArgumentException("未知函数: " + function.name());
  }
}

在上述代码中,每个函数的逻辑都封装在 execute() 方法中。然而,这并不是强制要求。您可以根据自己的使用场景,以任何最适合的方式实现函数逻辑。上述模式仅旨在提示一种合适的模式可能会使函数调用的过程更易于理解和实施。

与 Responses API 的使用

Function Calling 功能同样适用于 Responses API。使用方式与之前描述的相同,除非 Responses API 与 Chat Completions API 有细微差异。在构建参数时,将顶级类传递给 addTool(Class<T>)。在响应中,查找属于函数调用的 RepoonseOutputItem 实例。使用 ResponseFunctionToolCall.arguments(Class<T>) 将每个函数调用的参数解析为相应类的实例。最后,将每次调用的结果传回模型。

如需查看使用低级 API 定义和解析函数参数的 Function Calling 与 Responses API 结合使用的完整示例,请参阅 ResponsesFunctionCallingRawExample

如需查看使用 Java 类定义和解析函数参数的 Function Calling 与 Responses API 结合使用的完整示例,请参阅 ResponsesFunctionCallingExample

本地函数 JSON 模式验证

Structured Outputs 类似,您可以在本地进行验证,以确保从您的函数类派生的 JSON 模式符合 OpenAI 对此类模式施加的限制。本地验证默认启用,但可以通过在调用 addTool 时添加 JsonSchemaLocalValidation.NO 来禁用。

ChatCompletionCreateParams.Builder createParamsBuilder = ChatCompletionCreateParams.builder()
        .model(ChatModel.GPT_3_5_TURBO)
        .maxCompletionTokens(2048)
        .addTool(GetSdkQuality.class, JsonSchemaLocalValidation.NO)
        .addTool(GetSdkScore.class, JsonSchemaLocalValidation.NO)
        .addUserMessage("以下 SDK 的质量如何?评论者怎么说:OpenAI Java SDK、未知公司 SDK。");

有关本地模式验证的更多详细信息以及在何种情况下可能需要将其禁用,请参阅 本地 JSON 模式验证

注解函数类

您可以使用注解为从函数类派生的 JSON 模式添加更多关于函数的信息,或控制哪些字段或 getter 方法将用作函数的参数。JSON 模式中捕获的注解细节可能会被 AI 模型用于改进其响应。SDK 支持使用 Jackson Databind 注解。

  • 使用 @JsonClassDescription 为函数类添加描述,详细说明何时以及如何使用该函数。
  • 使用 @JsonTypeName 将函数名称设置为不同于类简单名称的内容,默认使用类简单名称。
  • 使用 @JsonPropertyDescription 为函数参数(即函数类中的字段或 getter 方法)添加详细描述。
  • 使用 @JsonIgnore 将类中的 public 字段或 getter 方法排除在函数参数生成的 JSON 模式之外。
  • 使用 @JsonProperty 将类中的非 public 字段或 getter 方法包含在函数参数生成的 JSON 模式中。

OpenAI 提供了一些 定义函数的最佳实践 ,可以帮助您理解如何有效地为您的函数使用上述注解。

另请参阅 定义 JSON 模式属性,了解如何使用字段和 getter 方法,并结合访问修饰符和注解来定义函数的参数。同样的规则适用于函数类以及该部分中描述的结构化输出类。

文件上传

SDK 定义了接受文件的方法。

要上传文件,可以传递一个 Path

import com.openai.models.files.FileCreateParams;
import com.openai.models.files.FileObject;
import com.openai.models.files.FilePurpose;
import java.nio.file.Paths;

FileCreateParams params = FileCreateParams.builder()
    .purpose(FilePurpose.FINE_TUNE)
    .file(Paths.get("input.jsonl"))
    .build();
FileObject fileObject = client.files().create(params);

或者任意类型的 InputStream

import com.openai.models.files.FileCreateParams;
import com.openai.models/files.FileObject;
import com.openai.models/files.FilePurpose;
import java.net.URL;

FileCreateParams params = FileCreateParams.builder()
    .purpose(FilePurpose.FINE_TUNE)
    .file(new URL("https://example.com/input.jsonl").openStream())
    .build();
FileObject fileObject = client.files().create(params);

也可以传递 byte[] 数组:

import com.openai.models/files.FileCreateParams;
import com.openai.models/files.FileObject;
import com.openai.models/files.FilePurpose;

FileCreateParams params = FileCreateParams.builder()
    .purpose(FilePurpose.FINE_TUNE)
    .file("content".getBytes())
    .build();
FileObject fileObject = client.files().create(params);

请注意,当传递非 Path 类型时,其文件名是未知的,因此不会包含在请求中。若要手动设置文件名,可以传递一个 MultipartField

import com.openai.core.MultipartField;
import com.openai.models/files.FileCreateParams;
import com.openai.models/files.FileObject;
import com.openai.models/files.FilePurpose;
import java.io.InputStream;
import java.net.URL;

FileCreateParams params = FileCreateParams.builder()
    .purpose(FilePurpose.FINE_TUNE)
    .file(MultipartField.<InputStream>builder()
        .value(new URL("https://example.com/input.jsonl").openStream())
        .filename("input.jsonl")
        .build())
    .build();
FileObject fileObject = client.files().create(params);

Webhook 验证

验证 webhook 签名是 可选但建议执行 的操作。

有关 webhook 的更多信息,请参阅 API 文档

解析 Webhook 负载

对于大多数用例,您可能希望同时验证 Webhook 并解析负载。为此,我们提供了 client.webhooks().unwrap() 方法,该方法会解析 Webhook 请求,并验证其是否由 OpenAI 发送。如果签名无效,此方法将抛出异常。

请注意,body 参数必须是服务器发送的原始 JSON 字符串(请勿先对其进行解析)。.unwrap() 方法会在验证 Webhook 确实来自 OpenAI 后,为您将此 JSON 解析为事件对象。

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.Headers;
import com.openai.models.webhooks.UnwrapWebhookEvent;
import java.util.Optional;

OpenAIClient client = OpenAIOkHttpClient.fromEnv(); // 默认使用 OPENAI_WEBHOOK_SECRET 环境变量

public void handleWebhook(String body, Map<String, String> headers) {
    try {
        Headers headersList = Headers.builder()
                .putAll(headers)
                .build();

        UnwrapWebhookEvent event = client.webhooks().unwrap(body, headersList, Optional.empty());

        if (event.isResponseCompletedWebhookEvent()) {
            System.out.println("响应已完成:" + event.asResponseCompletedWebhookEvent().data());
        } else if (event.isResponseFailed()) {
            System.out.println("响应失败:" + event.asResponseFailed().data());
        } else {
            System.out.println("未处理的事件类型:" + event.getClass().getSimpleName());
        }
    } catch (Exception e) {
        System.err.println("无效的 Webhook 签名:" + e.getMessage());
        // 处理无效签名
    }
}

直接验证 Webhook 负载

在某些情况下,您可能希望将 Webhook 的验证与负载解析分开进行。如果您更倾向于分别处理这些步骤,我们提供了 client.webhooks().verifySignature() 方法,用于仅验证 Webhook 请求的签名。与 .unwrap() 一样,如果签名无效,此方法也会抛出异常。

请注意,body 参数必须是服务器发送的原始 JSON 字符串(请勿先对其进行解析)。在验证签名之后,您需要自行解析请求体。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.Headers;
import com.openai.models.webhooks.WebhookVerificationParams;
import java.util.Optional;

OpenAIClient client = OpenAIOkHttpClient.fromEnv(); // 默认使用 OPENAI_WEBHOOK_SECRET 环境变量
ObjectMapper objectMapper = new ObjectMapper();

public void handleWebhook(String body, Map<String, String> headers) {
    try {
        Headers headersList = Headers.builder()
                .putAll(headers)
                .build();

        client.webhooks().verifySignature(
            WebhookVerificationParams.builder()
                .payload(body)
                .headers(headersList)
                .build()
        );

        // 验证后解析请求体
        Map<String, Object> event = objectMapper.readValue(body, Map.class);
        System.out.println("已验证的事件:" + event);
    } catch (Exception e) {
        System.err.println("无效的 Webhook 签名:" + e.getMessage());
        // 处理无效签名
    }
}

二进制响应

SDK 定义了返回二进制响应的方法,这些方法适用于那些无需解析的 API 响应,例如非 JSON 数据。

这些方法返回 HttpResponse

import com.openai.core.http.HttpResponse;
import com.openai.models.files.FileContentParams;

HttpResponse response = client.files().content("file_id");

要将响应内容保存到文件,可以使用 Files.copy(...) 方法:

import com.openai.core.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

try (HttpResponse response = client.files().content(params)) {
    Files.copy(
        response.body(),
        Paths.get(path),
        StandardCopyOption.REPLACE_EXISTING
    );
} catch (Exception e) {
    System.out.println("出错了!");
    throw new RuntimeException(e);
}

或者将响应内容传输到任何 OutputStream

import com.openai.core.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Paths;

try (HttpResponse response = client.files().content(params)) {
    response.body().transferTo(Files.newOutputStream(Paths.get(path)));
} catch (Exception e) {
    System.out.println("出错了!");
    throw new RuntimeException(e);
}

原始响应

SDK 定义了将响应反序列化为 Java 类实例的方法。然而,这些方法无法访问响应头、状态码或原始响应体。

要访问这些数据,可以在客户端或服务上的任何 HTTP 方法调用前添加 withRawResponse()

import com.openai.core.http.Headers;
import com.openai.core.http.HttpResponseFor;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .addUserMessage("说这是个测试")
    .model(ChatModel.GPT_5_2)
    .build();
HttpResponseFor<ChatCompletion> chatCompletion = client.chat().completions().withRawResponse().create(params);

int statusCode = chatCompletion.statusCode();
Headers headers = chatCompletion.headers();

如果需要,您仍然可以将响应反序列化为 Java 类的实例:

import com.openai.models.chat.completions.ChatCompletion;

ChatCompletion parsedChatCompletion = chatCompletion.parse();

请求 ID

更多关于调试请求的信息,请参阅 API 文档

在使用原始响应时,您可以使用 requestId() 方法访问 x-request-id 响应头:

import com.openai.core.http.HttpResponseFor;
import com.openai.models.chat.completions.ChatCompletion;
import java.util.Optional;

HttpResponseFor<ChatCompletion> chatCompletion = client.chat().completions().withRawResponse().create(params);
Optional<String> requestId = chatCompletion.requestId();

这可用于快速记录失败的请求,并将其报告回 OpenAI。

错误处理

SDK 会抛出自定义的未检查异常类型:

分页

SDK 定义了返回分页结果列表的方法。它提供了便捷的方式,既可以逐页访问结果,也可以跨所有页面逐项访问。

自动分页

要遍历所有页面中的全部结果,可以使用 autoPager() 方法,该方法会根据需要自动获取更多页面。

在使用同步客户端时,该方法返回一个 Iterable

import com.openai.models.finetuning.jobs.FineTuningJob;
import com.openai.models.finetuning.jobs.JobListPage;

JobListPage page = client.fineTuning().jobs().list();

// 作为 Iterable 处理
for (FineTuningJob job : page.autoPager()) {
    System.out.println(job);
}

// 作为 Stream 处理
page.autoPager()
    .stream()
    .limit(50)
    .forEach(job -> System.out.println(job));

在使用异步客户端时,该方法返回一个 AsyncStreamResponse

import com.openai.core.http.AsyncStreamResponse;
import com.openai.models.finetuning.jobs.FineTuningJob;
import com.openai.models.finetuning.jobs.JobListPageAsync;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

CompletableFuture<JobListPageAsync> pageFuture = client.async().fineTuning().jobs().list();

pageFuture.thenRun(page -> page.autoPager().subscribe(job -> {
    System.out.println(job);
}));

// 如果需要处理错误或流的完成
pageFuture.thenRun(page -> page.autoPager().subscribe(new AsyncStreamResponse.Handler<>() {
    @Override
    public void onNext(FineTuningJob job) {
        System.out.println(job);
    }

    @Override
    public void onComplete(Optional<Throwable> error) {
        if (error.isPresent()) {
            System.out.println("出错了!");
            throw new RuntimeException(error.get());
        } else {
            System.out.println("没有更多了!");
        }
    }
}));

// 或者使用 Future
pageFuture.thenRun(page -> page.autoPager()
    .subscribe(job -> {
        System.out.println(job);
    })
    .onCompleteFuture()
    .whenComplete((unused, error) -> {
        if (error != null) {
            System.out.println("出错了!");
            throw new RuntimeException(error);
        } else {
            System.out.println("没有更多了!");
        }
    }));

手动分页

要访问单个页面的项目并手动请求下一页,可以使用 items()hasNextPage()nextPage() 方法:

import com.openai.models.finetuning.jobs.FineTuningJob;
import com.openai.models.finetuning.jobs.JobListPage;

JobListPage page = client.fineTuning().jobs().list();
while (true) {
    for (FineTuningJob job : page.items()) {
        System.out.println(job);
    }

    if (!page.hasNextPage()) {
        break;
    }

    page = page.nextPage();
}

日志记录

SDK 使用标准的 OkHttp 日志拦截器

通过将 OPENAI_LOG 环境变量设置为 info 来启用日志记录:

export OPENAI_LOG=info

或者设置为 debug 以获得更详细的日志记录:

export OPENAI_LOG=debug

ProGuard 和 R8

尽管 SDK 使用反射,但它仍然可以与 ProGuardR8 一起使用,因为 openai-java-core 已经发布了一个包含 keep 规则配置文件

ProGuard 和 R8 应该能够自动检测并应用这些规则,但如果需要,您也可以手动复制 keep 规则。

GraalVM

尽管 SDK 使用了反射,但它仍然可以在 GraalVM 中使用,因为 openai-java-core 已经随附了 可达性元数据 发布。

GraalVM 应该能够自动检测并使用这些元数据,不过也可以进行手动配置

Spring Boot

如果你正在使用 Spring Boot,那么可以利用 SDK 的 Spring Boot 启动器,以简化配置并快速搭建项目。

安装

Gradle

implementation("com.openai:openai-java-spring-boot-starter:4.32.0")

Maven

<dependency>
  <groupId>com.openai</groupId>
  <artifactId>openai-java-spring-boot-starter</artifactId>
  <version>4.32.0</version>
</dependency>

配置

客户端的环境变量选项 可以在 application.propertiesapplication.yml 中进行配置。

application.properties

openai.base-url=https://api.openai.com/v1
openai.api-key=My API Key
openai.org-id=My Organization
openai.project-id=My Project
openai.webhook-secret=My Webhook Secret

application.yml

openai:
  base-url: https://api.openai.com/v1
  api-key: My API Key
  org-id: My Organization
  project-id: My Project
  webhook-secret: My Webhook Secret

其他配置

可以通过提供一个或多个 OpenAIClientCustomizer 实例来配置其他客户端选项。例如,以下是如何设置 maxRetries 的示例:

import com.openai.springboot.OpenAIClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenAIConfig {
    @Bean
    public OpenAIClientCustomizer customizer() {
        return builder -> builder.maxRetries(3);
    }
}

使用

OpenAIClient 注入到任何地方,即可开始使用!

Jackson

SDK 依赖于 Jackson 进行 JSON 的序列化和反序列化。它兼容 2.13.4 或更高版本,但默认依赖于 2.18.2 版本。

如果运行时检测到不兼容的 Jackson 版本(例如,在你的 Maven 或 Gradle 配置中覆盖了默认版本),SDK 将抛出异常。

如果 SDK 抛出了异常,但你_确定_版本是兼容的,则可以使用 OpenAIOkHttpClientOpenAIOkHttpClientAsync 中的 checkJacksonVersionCompatibility 方法来禁用版本检查。

[!CAUTION] 我们不保证在禁用 Jackson 版本检查的情况下,SDK 能够正常工作。

此外,请注意,较旧版本的 Jackson 存在一些可能影响 SDK 的缺陷。我们并不会针对所有 Jackson 缺陷进行修复(示例),而是建议用户自行升级 Jackson 来解决这些问题。

Microsoft Azure

要将此库与 Azure OpenAI 一起使用,可以使用相同的 OpenAI 客户端构建器,但需进行 Azure 特有的配置。

OpenAIClient client = OpenAIOkHttpClient.builder()
        // 分别从 `AZURE_OPENAI_KEY` 和 `OPENAI_BASE_URL` 环境变量中获取 API 密钥和端点
        .fromEnv()
        // 设置 Azure Entra ID 凭证
        .credential(BearerTokenCredential.create(AuthenticationUtil.getBearerTokenSupplier(
                new DefaultAzureCredentialBuilder().build(), "https://cognitiveservices.azure.com/.default")))
        .build();

完整的 Azure OpenAI 示例可在 openai-java-example 目录中找到。该目录中的其他示例只要客户端配置为使用 Azure,同样适用。

可选:URL 路径模式配置

ClientOptions 可以根据你的服务设置,对 Azure OpenAI 端点 URL 的处理方式进行配置。默认值为 AzureUrlPathMode.AUTO。若要自定义 SDK 行为,各模式的作用如下:

  • AzureUrlPathMode.LEGACY:强制将部署名称或模型名称放入路径中。
  • AzureUrlPathMode.UNIFIED:对于以 /openai/v1 结尾的新版端点,其服务行为与 OpenAI 一致,因此 AzureOpenAIServiceVersion 变得可选,模型将在请求对象中传递。
  • AzureUrlPathMode.AUTO:根据基础 URL 自动检测路径模式。为默认值。

网络选项

重试次数

SDK 默认会自动重试 2 次,每次请求之间采用短时间的指数退避策略。

仅以下错误类型会被重试:

  • 连接错误(例如,由于网络连接问题)
  • 408 请求超时
  • 409 冲突
  • 429 速率限制
  • 5xx 内部错误

API 也可能明确指示 SDK 是否需要重试请求。

要设置自定义的重试次数,可以使用 maxRetries 方法配置客户端:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    .maxRetries(4)
    .build();

超时时间

默认情况下,请求会在 10 分钟后超时。

要设置自定义超时时间,可以在方法调用时使用 timeout 方法进行配置:

import com.openai.models.chat.completions.ChatCompletion;

ChatCompletion chatCompletion = client.chat().completions().create(
  params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()
);

或者在客户端级别为所有方法调用设置默认超时时间:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import java.time.Duration;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    .timeout(Duration.ofSeconds(30))
    .build();

代理

要通过代理路由请求,请使用 proxy 方法配置客户端:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import java.net.InetSocketAddress;
import java.net.Proxy;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    .proxy(new Proxy(
      Proxy.Type.HTTP, new InetSocketAddress(
        "https://example.com", 8080
      )
    ))
    .build();

连接池

要自定义底层 OkHttp 连接池,可以使用 maxIdleConnectionskeepAliveDuration 方法配置客户端:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import java.time.Duration;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    // 如果设置了 `maxIdleConnections`,则必须同时设置 `keepAliveDuration`,反之亦然。
    .maxIdleConnections(10)
    .keepAliveDuration(Duration.ofMinutes(2))
    .build();

如果这两个选项均未设置,则将使用 OkHttp 的默认连接池设置。

HTTPS

[!注意] 大多数应用程序不应调用这些方法,而应使用系统默认设置。默认设置包含特殊的优化措施,若修改实现方式可能会导致这些优化失效。

要配置 HTTPS 连接的安全性,可以使用 sslSocketFactorytrustManagerhostnameVerifier 方法配置客户端:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    // 如果设置了 `sslSocketFactory`,则必须同时设置 `trustManager`,反之亦然。
    .sslSocketFactory(yourSSLSocketFactory)
    .trustManager(yourTrustManager)
    .hostnameVerifier(yourHostnameVerifier)
    .build();

自定义 HTTP 客户端

该 SDK 包含三个组件:

  • openai-java-core
    • 包含 SDK 核心逻辑
    • 不依赖于 OkHttp
    • 暴露了 OpenAIClientOpenAIClientAsyncOpenAIClientImplOpenAIClientAsyncImpl,这些类均可与任何 HTTP 客户端配合使用
  • openai-java-client-okhttp
    • 依赖于 OkHttp
    • 暴露了 OpenAIOkHttpClientOpenAIOkHttpClientAsync,它们分别提供了使用 OkHttp 构建 OpenAIClientImplOpenAIClientAsyncImpl 的方式
  • openai-java
    • 依赖并暴露了 openai-java-coreopenai-java-client-okhttp 的 API
    • 不包含自己的逻辑

这种结构允许在不引入不必要的依赖的情况下替换 SDK 的默认 HTTP 客户端。

自定义的 OkHttpClient

[!提示] 在替换默认客户端之前,请先尝试可用的 网络选项

要使用自定义的 OkHttpClient

  1. 将您的 openai-java 依赖项替换为 openai-java-core
  2. openai-java-client-okhttp 中的 OkHttpClient 类复制到您的代码中并进行自定义
  3. 使用您自定义的客户端,类似 OpenAIOkHttpClientOpenAIOkHttpClientAsync 的方式,构建 OpenAIClientImplOpenAIClientAsyncImpl

完全自定义的 HTTP 客户端

要使用完全自定义的 HTTP 客户端:

  1. 将您的 openai-java 依赖项替换为 openai-java-core
  2. 编写一个实现 HttpClient 接口的类
  3. 使用您的新客户端类,类似 OpenAIOkHttpClientOpenAIOkHttpClientAsync 的方式,构建 OpenAIClientImplOpenAIClientAsyncImpl

未文档化的 API 功能

该 SDK 经过类型化设计,旨在方便使用已文档化的 API。然而,它也支持与未文档化或尚未正式支持的 API 部分进行交互。

参数

要设置未公开的参数,可以在任何 Params 类上调用 putAdditionalHeaderputAdditionalQueryParamputAdditionalBodyProperty 方法:

import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .putAdditionalHeader("Secret-Header", "42")
    .putAdditionalQueryParam("secret_query_param", "42")
    .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))
    .build();

之后可以通过 _additionalHeaders()_additionalQueryParams()_additionalBodyProperties() 方法在构建好的对象上访问这些参数。

如果需要为嵌套的头部、查询参数或请求体类设置未公开的参数,可以在嵌套类上调用 putAdditionalProperty 方法:

import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .responseFormat(ChatCompletionCreateParams.ResponseFormat.builder()
        .putAdditionalProperty("secretProperty", JsonValue.from("42"))
        .build())
    .build();

这些属性可以在嵌套的构建对象上通过 _additionalProperties() 方法进行访问。

若要将已公开的参数或属性设置为尚未支持或未公开的值,可以将其值包装成一个 JsonValue 对象并传递给对应的 setter 方法:

import com.openai.core.JsonValue;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .messages(JsonValue.from(42))
    .model(ChatModel.GPT_5_2)
    .build();

创建 JsonValue 的最简单方式是使用其 from(...) 方法:

import com.openai.core.JsonValue;
import java.util.List;
import java.util.Map;

// 创建基本 JSON 值
JsonValue nullValue = JsonValue.from(null);
JsonValue booleanValue = JsonValue.from(true);
JsonValue numberValue = JsonValue.from(42);
JsonValue stringValue = JsonValue.from("Hello World!");

// 创建等价于 `["Hello", "World"]` 的 JSON 数组
JsonValue arrayValue = JsonValue.from(List.of(
  "Hello", "World"
));

// 创建等价于 `{ "a": 1, "b": 2 }` 的 JSON 对象
JsonValue objectValue = JsonValue.from(Map.of(
  "a", 1,
  "b", 2
));

// 创建一个任意嵌套的 JSON,等价于:
// {
//   "a": [1, 2],
//   "b": [3, 4]
// }
JsonValue complexValue = JsonValue.from(Map.of(
  "a", List.of(
    1, 2
  ),
  "b", List.of(
    3, 4
  )
));

通常情况下,Builder 类的 build 方法会在有任何必填参数或属性未设置时抛出 IllegalStateException

如果需要强制忽略某个必填参数或属性,可以传入 JsonMissing

import com.openai.core.JsonMissing;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .model(ChatModel.GPT_5_4)
    .messages(JsonMissing.of())
    .build();

响应属性

要访问未公开的响应属性,可以调用 _additionalProperties() 方法:

import com.openai.core.JsonValue;
import java.util.Map;

Map<String, JsonValue> additionalProperties = client.chat().completions().create(params)._additionalProperties();
JsonValue secretPropertyValue = additionalProperties.get("secretProperty");

String result = secretPropertyValue.accept(new JsonValue.Visitor<>() {
    @Override
    public String visitNull() {
        return "It's null!";
    }

    @Override
    public String visitBoolean(boolean value) {
        return "It's a boolean!";
    }

    @Override
    public String visitNumber(Number value) {
        return "It's a number!";
    }

    // 其他方法包括 `visitMissing`, `visitString`, `visitArray` 和 `visitObject`
    // 每个未实现方法的默认行为都会委托给 `visitDefault`,而后者默认会抛出异常,但也可以被重写。
});

要访问某个属性的原始 JSON 值(可能未公开),可以调用以 _ 开头的方法:

import com.openai.core.JsonField;
import com.openai.models.chat.completions.ChatCompletionMessageParam;
import java.util.Optional;

JsonField<List<ChatCompletionMessageParam>> messages = client.chat().completions().create(params)._messages();

if (messages.isMissing()) {
  // 该属性在 JSON 响应中不存在
} else if (messages.isNull()) {
  // 该属性被设置为字面量 null
} else {
  // 检查值是否以字符串形式提供
  // 其他方法包括 `asNumber()`, `asBoolean()` 等
  Optional<String> jsonString = messages.asString();

  // 尝试反序列化为自定义类型
  MyClass myObject = messages.asUnknown().orElseThrow().convert(MyClass.class);
}

响应验证

在极少数情况下,API 可能会返回与预期类型不符的响应。例如,SDK 可能期望某个属性包含一个 String,但 API 却返回了其他内容。

默认情况下,SDK 不会在这种情况下抛出异常,只有当你直接访问该属性时才会抛出 OpenAIInvalidDataException

如果你希望在一开始就完全确认响应的类型是否正确,可以调用 validate() 方法:

import com.openai.models.chat.completions.ChatCompletion;

ChatCompletion chatCompletion = client.chat().completions().create(params).validate();

或者通过 responseValidation 方法配置每次调用都进行响应验证:

import com.openai.models.chat.completions.ChatCompletion;

ChatCompletion chatCompletion = client.chat().completions().create(
  params, RequestOptions.builder().responseValidation(true).build()
);

又或者在客户端级别为所有方法调用设置默认验证:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .fromEnv()
    .responseValidation(true)
    .build();

常见问题解答

为什么你们不使用普通的 enum 类?

Java 的 enum 类并不容易实现向前兼容性(参见 Stainless 博客文章)。如果 SDK 中使用了 enum,当 API 更新并返回新的枚举值时,可能会导致运行时异常。

为什么你们使用 JsonField<T> 来表示字段,而不是直接使用普通的 T 呢?

使用 JsonField<T> 可以实现以下几点功能:

为什么不使用 Kotlin 的 data 呢?

data 类中添加新字段并不具备 向后兼容性,而我们不希望每次向类中添加字段时都引入破坏性变更。

为什么不用受检异常呢?

在 Java 编程语言中,受检异常被广泛认为是一种设计上的失误。事实上,Kotlin 也正因为这个原因而没有引入受检异常。

受检异常存在以下问题:

  • 处理起来过于冗长
  • 容易导致错误处理发生在不恰当的抽象层次上,在该层次上往往无法采取任何措施来解决错误
  • 由于 函数着色问题,传播受检异常非常繁琐
  • 与 Lambda 表达式配合不佳(同样是因为函数着色问题)

语义化版本控制

本包通常遵循 SemVer 规范,不过某些不兼容的变更可能会以次版本号的形式发布:

  1. 对库内部实现的更改,这些实现虽然技术上是公开的,但并非面向外部使用或未被文档化。(如果您依赖于此类内部实现,请务必提交一个 GitHub 问题告知我们。)
  2. 我们预计在实际应用中不会影响绝大多数用户的变更。

我们非常重视向后兼容性,并会尽力确保您能够获得顺畅的升级体验。

我们非常欢迎您的反馈,请随时在 GitHub 仓库的问题页面 上提交问题、报告 Bug 或提出建议。

版本历史

v4.32.02026/04/16
v4.31.02026/04/08
v4.30.02026/03/25
v4.29.12026/03/23
v4.29.02026/03/17
v4.28.02026/03/13
v4.27.02026/03/13
v4.26.02026/03/05
v4.25.02026/03/05
v4.24.12026/03/04
v4.24.02026/02/24
v4.23.02026/02/23
v4.22.02026/02/19
v4.21.02026/02/14
v4.20.02026/02/10
v4.19.02026/02/09
v4.18.02026/02/05
v4.17.02026/01/30
v4.16.12026/01/23
v4.16.02026/01/21

常见问题

相似工具推荐

openclaw

OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你

349.3k|★★★☆☆|1周前
Agent开发框架图像

stable-diffusion-webui

stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。

162.1k|★★★☆☆|2周前
开发框架图像Agent

everything-claude-code

everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上

160.8k|★★☆☆☆|今天
开发框架Agent语言模型

ComfyUI

ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。

109.2k|★★☆☆☆|昨天
开发框架图像Agent

gemini-cli

gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。

100.8k|★★☆☆☆|1周前
插件Agent图像

markitdown

MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器

93.4k|★★☆☆☆|1周前
插件开发框架