Skip to content
LangChain4j 文档版本 1.22.0 源快照 0085daf4 更新于 2026-10-14

OpenAI 官方 SDK

NOTE

这是 OpenAI 官方 SDK 集成的文档,它使用 官方 OpenAI Java SDK。

LangChain4j 提供了 3 种不同的 OpenAI 集成来使用聊天模型,这里是第 2 种:

  • OpenAI 使用对 OpenAI REST API 的自定义 Java 实现,最适合与 Quarkus(因其使用 Quarkus REST 客户端)以及 Spring(因其使用 Spring 的 RestClient)搭配。
  • OpenAI 官方 SDK 使用官方的 OpenAI Java SDK。
  • Azure OpenAI 使用微软的 Azure SDK,最适合在你使用微软 Java 技术栈(包括高级 Azure 认证机制)时。

本集成的适用场景

本集成使用 OpenAI Java SDK GitHub 仓库,适用于所有可由以下方提供的 OpenAI 模型:

  • OpenAI
  • Microsoft Foundry
  • GitHub Models

它也能与支持 OpenAI API 的模型配合使用,例如 DeepSeek。

OpenAI 文档

Maven 依赖

xml
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai-official</artifactId>
    <version>1.22.0-beta32</version>
</dependency>

配置模型

NOTE

本配置以及下一节关于其用法,都是针对非流式模式(也称"阻塞"或"同步"模式)。 流式模式在下文两节之后详述:它支持与模型实时对话,但用法更复杂。

要使用 OpenAI 模型,你通常需要一个端点 URL、一个 API 密钥和一个模型名。这取决于模型托管在哪里,本集成尝试通过一些自动配置让它更简单:

通用配置

java
import com.openai.models.ChatModel;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openaiofficial.OpenAiOfficialChatModel;

import static com.openai.models.ChatModel.GPT_5_MINI;

// ....

ChatModel model = OpenAiOfficialChatModel.builder()
        .baseUrl(System.getenv("OPENAI_BASE_URL"))
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_5_MINI)
        .build();

OpenAI 配置

OpenAI 的 baseUrl(https://api.openai.com/v1)是默认值,因此你可以省略它:

java
ChatModel model = OpenAiOfficialChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_5_MINI)
        .build();

Azure OpenAI 配置

通用配置

对于 Azure OpenAI,设置 baseUrl 是必需的,且若该 URL 以 openai.azure.com 结尾,Azure OpenAI 会被自动检测:

java
ChatModel model = OpenAiOfficialChatModel.builder()
        .baseUrl(System.getenv("AZURE_OPENAI_ENDPOINT"))
        .apiKey(System.getenv("AZURE_OPENAI_KEY"))
        .modelName(GPT_5_MINI)
        .build();

如果你想强制使用 Azure OpenAI,也可以用 isAzure() 方法:

java
ChatModel model = OpenAiOfficialChatModel.builder()
        .baseUrl(System.getenv("AZURE_OPENAI_ENDPOINT"))
        .apiKey(System.getenv("AZURE_OPENAI_KEY"))
        .isAzure(true)
        .modelName(GPT_5_MINI)
        .build();

无密码认证

你可以用"无密码"认证登录 Azure OpenAI,它更安全,因为你无需管理 API 密钥。

为此,你必须先配置你的 Azure OpenAI 实例以支持托管标识,然后授予该应用访问权限,例如:

bash
# Enable system managed identity on the Azure OpenAI instance
az cognitiveservices account identity assign \
    --name <your-openai-instance-name> \
    --resource-group <your-resource-group>

# Get your logged-in identity
az ad signed-in-user show \
    --query id -o tsv
    
# Give access to the Azure OpenAI instance
az role assignment create \
    --role "Cognitive Services OpenAI User" \
    --assignee <your-logged-identity-from-the-previous-command> \
    --scope "/subscriptions/<your-subscription-id>/resourceGroups/<your-resource-group>"

然后,你需要将 azure-identity 依赖添加到你的 Maven pom.xml:

xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
</dependency>

当未配置 API 密钥时,LangChain4j 会自动使用与 Azure OpenAI 的无密码认证。

GitHub Models 配置

对于 GitHub Models,你可以使用默认的 baseUrl(https://models.inference.ai.azure.com):

java
ChatModel model = OpenAiOfficialChatModel.builder()
        .baseUrl("https://models.inference.ai.azure.com")
        .apiKey(System.getenv("GITHUB_TOKEN"))
        .modelName(GPT_5_MINI)
        .build();

或者,你可以使用 isGitHubModels() 方法强制使用 GitHub Models,它会自动设置 baseUrl:

java
ChatModel model = OpenAiOfficialChatModel.builder()
        .apiKey(System.getenv("GITHUB_TOKEN"))
        .modelName(GPT_5_MINI)
        .isGitHubModels(true)
        .build();

由于 GitHub Models 通常用 GITHUB_TOKEN 环境变量配置,而在使用 GitHub Actions 或 GitHub Codespaces 时它会被自动填充,因此会被自动检测到:

java
ChatModel model = OpenAiOfficialChatModel.builder()
        .modelName(GPT_5_MINI)
        .isGitHubModels(true)
        .build();

最后这一种配置更易用、也更安全,因为 GITHUB_TOKEN 环境变量不会暴露在代码中或 GitHub 日志里。

使用模型

在上一节中,创建了一个 OpenAiOfficialChatModel 对象,它实现了 ChatModel 接口。

它既可以被某个 AI 服务使用,也可以直接在 Java 应用中使用。

在本例中,它作为一个 Spring Bean 被自动注入:

java
@RestController
class ChatModelController {

    ChatModel chatModel;

    ChatModelController(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @GetMapping("/model")
    public String model(@RequestParam(value = "message", defaultValue = "Hello") String message) {
        return chatModel.chat(message);
    }
}

结构化输出

结构化输出特性对工具与响应格式都受支持。

关于结构化输出的更多信息,见这里。

面向工具的结构化输出

要为工具启用结构化输出特性,请在构建模型时设置 .strictTools(true):

java
OpenAiOfficialChatModel.builder()
        // ...
        .strictTools(true)
        .build();

请注意,这会自动将所有工具参数变为必填(json schema 中的 required),并为 json schema 中的每个 object 设置 additionalProperties=false。这是由于当前 OpenAI 的限制所致。

面向响应格式的结构化输出

要在用 AI 服务时启用面向响应格式化的结构化输出特性,请在构建模型时设置 supportedCapabilities(Set.of(RESPONSE_FORMAT_JSON_SCHEMA)) 与 .strictJsonSchema(true):

java
import static dev.langchain4j.model.chat.Capability.RESPONSE_FORMAT_JSON_SCHEMA;

// ...

OpenAiChatModel.builder()
        // ...
        .supportedCapabilities(Set.of(RESPONSE_FORMAT_JSON_SCHEMA))
        .strictJsonSchema(true)
        .build();

这种情况下,AI 服务会自动从给定的 POJO 生成一个 JSON schema 并传给 LLM。

为流式配置模型

NOTE

在上面两节中,我们详述了如何为非流式模式(也称"阻塞"或"同步"模式)配置模型。本节针对流式模式,它支持与模型实时对话,但用法更复杂。

这与非流式模式类似,但你需要使用 OpenAiOfficialStreamingChatModel 类而非 OpenAiOfficialChatModel:

java
StreamingChatModel model = OpenAiOfficialStreamingChatModel.builder()
        .baseUrl(System.getenv("OPENAI_BASE_URL"))
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_5_MINI)
        .build();

你也可以用专门的 isAzure() 与 isGitHubModels() 方法来强制使用 Azure OpenAI 或 GitHub Models,如非流式配置一节所述。

提示词缓存

OpenAI 会缓存较长的、重复的提示词前缀,并按输入价的一小部分对缓存读取计费。下述控制项对 Chat Completions API 模型与 Responses API 模型都有效。

关于提示词缓存的更多信息可在这里找到。

promptCacheKey 与 promptCacheOptions

promptCacheKey 是一个可选字符串,用于引导路由,使相关的请求更可能到达一台持有该缓存条目的机器。它不会把请求钉在某台机器上,也不保证缓存命中。

gpt-5.6 及更新版本会在一个*断点(breakpoint)*处精确匹配缓存前缀,而不会回退到一个更短的未标记前缀。promptCacheOptions 控制断点来自何处:

  • implicit —— OpenAI 在最新一条符合条件消息的末尾放置一个断点。
  • explicit —— 只使用你设置的断点。若没有任何断点,则什么都不缓存。

对于 Responses API 模型,二者都可在模型 builder 上获得:

java
OpenAiOfficialResponsesChatModel model = OpenAiOfficialResponsesChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-5.6")
        .promptCacheKey("satisfaction_judge_v1")
        .promptCacheOptions(OpenAiOfficialPromptCacheOptions.builder()
                .mode(OpenAiOfficialPromptCacheOptions.MODE_EXPLICIT)
                .ttl(OpenAiOfficialPromptCacheOptions.TTL_30M)
                .build())
        .build();

对于 Chat Completions API 模型,它们通过 OpenAiOfficialChatRequestParameters 设置,可作为模型默认值或逐次请求设置:

java
OpenAiOfficialChatModel model = OpenAiOfficialChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-5.6")
        .defaultRequestParameters(OpenAiOfficialChatRequestParameters.builder()
                .promptCacheKey("satisfaction_judge_v1")
                .promptCacheOptions(OpenAiOfficialPromptCacheOptions.explicit())
                .build())
        .build();

OpenAiOfficialPromptCacheOptions.implicit() 与 OpenAiOfficialPromptCacheOptions.explicit() 是只设置模式的简写。

promptCacheOptions.ttl 会取代 promptCacheRetention(后者适用于比 gpt-5.6 更旧的模型)。OpenAI 会拒绝同时携带二者的请求。

promptCacheBreakpoint

SystemMessage、UserMessage 与 ToolExecutionResultMessage 各自都可被标记为一个提示词缓存断点。由于提示词缓存是基于前缀的,断点会应用在被标记消息的最后一个内容块上,从而使到该消息为止(含该消息)的一切都构成被缓存的前缀。

OpenAiOfficialPromptCacheBreakpoint.mark() 返回该消息的一个被标记副本,保持原消息不变:

java
SystemMessage systemMessage = OpenAiOfficialPromptCacheBreakpoint.mark(SystemMessage.from(SHARED_INSTRUCTIONS));

UserMessage userMessage = OpenAiOfficialPromptCacheBreakpoint.mark(UserMessage.from(LONG_DOCUMENT));

ToolExecutionResultMessage toolResult = OpenAiOfficialPromptCacheBreakpoint.mark(someToolExecutionResultMessage);

标记本质上只是消息上的一个属性,因此也可手动完成——例如当你本来就在构建该消息时:

java
SystemMessage systemMessage = SystemMessage.builder()
        .text(SHARED_INSTRUCTIONS)
        .attributes(Map.of(OpenAiOfficialPromptCacheBreakpoint.ATTRIBUTE_KEY,
                           OpenAiOfficialPromptCacheBreakpoint.MODE_EXPLICIT))
        .build();

标记一条消息会让 LangChain4j 以内容块列表的形式发送该消息的内容,因为纯字符串形式无法携带断点。

AiMessage 无法携带断点:助手输出的块不在 OpenAI 允许在其上放置断点的块类型之中。标记一个 AiMessage,或使用除 explicit 以外的任何模式,都会快速失败,而不是产生一个 HTTP 400。

每个请求最多支持四次缓存写入,其中一次会被 implicit 模式占用。

读取缓存词元数

OpenAiOfficialTokenUsage.InputTokensDetails 会上报有多少输入词元是从提示词缓存读取、以及写入其中的:

java
OpenAiOfficialTokenUsage tokenUsage = (OpenAiOfficialTokenUsage) chatResponse.tokenUsage();

tokenUsage.inputTokensDetails().cachedTokens();      // tokens read from the cache
tokenUsage.inputTokensDetails().cacheWriteTokens();  // tokens written to the cache

当模型提供者未上报 cacheWriteTokens() 时,它返回 null,这与上报为零是不同的。

OpenAI Responses API

NOTE

该特性尚属实验性,未来版本可能变化。

OpenAI 的 Responses API(/v1/responses)是 Chat Completions API 的一种替代方案。

创建 OpenAiOfficialResponsesChatModel

java
ChatModel model = OpenAiOfficialResponsesChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-5.4")
        .build();

创建 OpenAiOfficialResponsesStreamingChatModel

java
StreamingChatModel model = OpenAiOfficialResponsesStreamingChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(GPT_5_MINI)
        .build();

你也可以用 OpenAiOfficialResponsesChatRequestParameters 配置默认请求参数:

java
StreamingChatModel model = OpenAiOfficialResponsesStreamingChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .defaultRequestParameters(OpenAiOfficialResponsesChatRequestParameters.builder()
                .modelName("gpt-4o-mini")
                .previousResponseId("resp_abc123")
                .reasoningEffort("medium")
                .store(true)
                .build())
        .build();

OpenAiOfficialResponsesChatRequestParameters

OpenAiOfficialResponsesChatRequestParameters 在 DefaultChatRequestParameters 基础上扩展出 Responses API 专有字段:previousResponseId、maxToolCalls、parallelToolCalls、topLogprobs、truncation、include、serviceTier、safetyIdentifier、promptCacheKey、promptCacheRetention、promptCacheOptions、reasoningEffort、reasoningSummary、textVerbosity、streamIncludeObfuscation、store、strictTools、strictJsonSchema。

这些参数可在创建模型时配置为默认值(通过 builder 上的 defaultRequestParameters),或经 ChatRequest 逐次请求传入(逐次请求参数会覆盖默认值):

java
ChatRequest chatRequest = ChatRequest.builder()
        .messages(UserMessage.from("Hello"))
        .parameters(OpenAiOfficialResponsesChatRequestParameters.builder()
                .modelName("gpt-4o-mini")
                .previousResponseId("resp_abc123")
                .store(true)
                .build())
        .build();

思考 / 推理

OpenAI 推理模型(例如 gpt-5.4、gpt-5-mini)支持推理摘要,它会把模型内部推理的摘要暴露出来。

要启用推理摘要,请在 builder 上(或通过 OpenAiOfficialResponsesChatRequestParameters)将 reasoningSummary 设为 Reasoning.Summary.AUTO。你也可以用 reasoningEffort 控制模型在推理上投入多少精力。

java
ChatModel model = OpenAiOfficialResponsesChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-5-mini")
        .reasoningEffort(ReasoningEffort.LOW)
        .reasoningSummary(Reasoning.Summary.AUTO)
        .build();

ChatResponse response = model.chat("What is the capital of Germany?");
response.aiMessage().text();     // "The capital of Germany is Berlin."
response.aiMessage().thinking(); // reasoning summary text

当为 OpenAiOfficialResponsesStreamingChatModel 设置了 reasoningSummary 时,随着推理摘要词元的流式返回,StreamingChatResponseHandler.onPartialThinking() 回调会被调用:

java
StreamingChatModel model = OpenAiOfficialResponsesStreamingChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-5-mini")
        .reasoningEffort(ReasoningEffort.LOW)
        .reasoningSummary(Reasoning.Summary.AUTO)
        .build();

AiMessage.thinking() 中的推理摘要仅供参考,无需在后续请求中回传——OpenAI 会在轮次之间丢弃它。要真正在多轮之间(例如工具调用之间)保留模型的推理状态,请使用下文的加密推理。

加密推理(将推理保留在上下文中)

当 store 为 false(默认)或你的组织采用零数据保留时,模型的推理上下文会在轮次之间丢失。要保留它,请通过 include 参数请求加密推理内容:

java
ChatModel model = OpenAiOfficialResponsesChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-5-mini")
        .reasoningEffort(ReasoningEffort.MEDIUM)
        .include(List.of("reasoning.encrypted_content"))
        .build();

当 include 包含 "reasoning.encrypted_content" 时,响应的推理项会包含一个不透明的加密块。它会被自动存储在 AiMessage.attributes() 下的 "encrypted_reasoning" 键中。

当你在后续请求(例如工具调用之后)把那个 AiMessage 传回时,加密推理会被自动包含进请求,从而让模型得以恢复其推理上下文:

java
// Turn 1: model calls a tool
ChatResponse response1 = model.chat(ChatRequest.builder()
        .messages(userMessage)
        .parameters(ChatRequestParameters.builder()
                .toolSpecifications(weatherTool)
                .build())
        .build());

AiMessage aiMessage1 = response1.aiMessage();
// aiMessage1.attribute("encrypted_reasoning", String.class) is not null

// Turn 2: send tool result back — encrypted reasoning is sent automatically
ChatResponse response2 = model.chat(ChatRequest.builder()
        .messages(
                userMessage,
                aiMessage1, // contains encrypted reasoning in attributes
                ToolExecutionResultMessage.from(aiMessage1.toolExecutionRequests().get(0), "sunny"))
        .parameters(ChatRequestParameters.builder()
                .toolSpecifications(weatherTool)
                .build())
        .build());

这对 OpenAiOfficialResponsesStreamingChatModel 同样适用。

OpenAiOfficialResponsesChatResponseMetadata

Responses API 的响应元数据在标准 ChatResponseMetadata 之外提供了额外字段:

java
OpenAiOfficialResponsesChatResponseMetadata metadata =
        (OpenAiOfficialResponsesChatResponseMetadata) chatResponse.metadata();

metadata.id();               // Response ID (can be used as previousResponseId)
metadata.modelName();        // Model name used for the request
metadata.finishReason();     // Finish reason (STOP, LENGTH, TOOL_EXECUTION, CONTENT_FILTER, OTHER)
metadata.tokenUsage();       // Returns OpenAiOfficialTokenUsage with detailed token counts
metadata.createdAt();        // Timestamp when the response was created
metadata.completedAt();      // Timestamp when the response was completed
metadata.serviceTier();      // Service tier used for the request

批处理

OpenAiOfficialBatchChatModel 实现了核心的 BatchChatModel 接口,通过 OpenAI Batch API 异步处理大量聊天请求,按标准逐词元价格的 50% 计费。

请求会被写入一个 JSONL 文件,以 batch 用途通过 Files API 上传,并针对 /v1/chat/completions 端点运行。一批中的所有请求都必须解析到同一个模型。结果保持提交顺序,因此第 i 个结果对应第 i 个请求,无论它是成功还是失败。

java
OpenAiOfficialBatchChatModel batchModel = OpenAiOfficialBatchChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-4o-mini")
        .build();

BatchResponse<ChatResponse> submitted = batchModel.submit(new BatchRequest<>(List.of(
        ChatRequest.builder().messages(UserMessage.from("What is the capital of France?")).build(),
        ChatRequest.builder().messages(UserMessage.from("What is the capital of Germany?")).build())));

String batchId = submitted.batchId();

// Poll until the batch reaches a terminal state (SUCCEEDED, FAILED, CANCELLED, EXPIRED).
BatchResponse<ChatResponse> batch = batchModel.retrieve(batchId);
while (!batch.state().isTerminal()) {
    Thread.sleep(Duration.ofSeconds(30).toMillis());
    batch = batchModel.retrieve(batchId);
}

for (BatchItemResult<ChatResponse> result : batch.results()) {
    if (result.isSuccess()) {
        System.out.println(result.response().aiMessage().text());
    } else {
        System.out.println("Failed: " + result.error().message());
    }
}

一个正在运行的批次可以被取消,现有批次也可以分页列出:

java
batchModel.cancel(batchId);

BatchPage<ChatResponse> page = batchModel.list(new BatchPagination(20, null));

Azure OpenAI 也受支持——在那里模型以其 batch 部署名标识;任何实现了 Files 与 Batch API 的兼容 OpenAI 端点同样受支持。

批量专有的选项可以在 builder 上设置:

java
OpenAiOfficialBatchChatModel batchModel = OpenAiOfficialBatchChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-4o-mini")
        .completionWindow("24h")                          // defaults to 24h
        .batchMetadata(Map.of("owner", "nightly-job"))    // attached to the batch itself
        .inputFileExpiresAfter(Duration.ofDays(14))
        .outputExpiresAfter(Duration.ofDays(7))
        .build();

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。