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

Anthropic

Maven 依赖

xml
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-anthropic</artifactId>
    <version>1.22.0</version>
</dependency>

AnthropicChatModel

java
AnthropicChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName(CLAUDE_3_5_SONNET_20240620)
    .build();
String answer = model.chat("Say 'Hello World'");
System.out.println(answer);

定制 AnthropicChatModel

java
AnthropicChatModel model = AnthropicChatModel.builder()
    .httpClientBuilder(...)
    .baseUrl(...)
    .apiKey(...)
    .version(...)
    .beta(...)
    .modelName(...)
    .temperature(...)
    .topP(...)
    .topK(...)
    .maxTokens(...)
    .stopSequences(...)
    .toolSpecifications(...)
    .toolChoice(...)
    .toolChoiceName(...)
    .disableParallelToolUse(...)
    .serverTools(...)
    .returnServerToolResults(...)
    .toolMetadataKeysToSend(...)
    .cacheSystemMessages(...)
    .cacheTools(...)
    .cacheAutomatically(...)
    .cacheTtl(...)
    .returnCacheDiagnostics(...)
    .thinkingType(...)
    .thinkingBudgetTokens(...)
    .thinkingDisplay(...)
    .returnThinking(...)
    .sendThinking(...)
    .midConversationSystemMessages(...)
    .timeout(...)
    .maxRetries(...)
    .logRequests(...)
    .logResponses(...)
    .listeners(...)
    // You can also specify default chat request parameters using ChatRequestParameters or AnthropicChatRequestParameters
    .defaultRequestParameters(...)
    .userId(...)
    .customParameters(...)
    .build();

上文部分参数的说明见这里。

逐次请求参数

上面展示的 Anthropic 专有选项(cacheSystemMessages、cacheTools、cacheAutomatically、cacheTtl、returnCacheDiagnostics、thinkingType、thinkingBudgetTokens、sendThinking、returnThinking、midConversationSystemMessages、toolChoiceName、disableParallelToolUse 与 userId),以及 previousMessageId(仅请求,见缓存诊断),也可通过 AnthropicChatRequestParameters 逐次请求设置,覆盖在模型 builder 上配置的值。这让你能用单个共享模型实例在一次次调用间变化这些选项——例如,为一个长时间运行的智能体循环启用提示词缓存,而对一个廉价的一次性补全跳过它,无需构建第二个模型:

java
AnthropicChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName(CLAUDE_3_5_SONNET_20240620)
    .build();

AnthropicChatRequestParameters parameters = AnthropicChatRequestParameters.builder()
    .cacheSystemMessages(true)
    .cacheTools(true)
    .build();

ChatRequest chatRequest = ChatRequest.builder()
    .messages(systemMessage, userMessage)
    .parameters(parameters)
    .build();

ChatResponse chatResponse = model.chat(chatRequest);

请求上未设置的任何参数,都会回退到在模型 builder 上配置的值。

AnthropicStreamingChatModel

java
AnthropicStreamingChatModel model = AnthropicStreamingChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName(CLAUDE_3_5_SONNET_20240620)
    .build();

model.chat("Say 'Hello World'", new StreamingChatResponseHandler() {

    @Override
    public void onPartialResponse(String partialResponse) {
        // this method is called when a new partial response is available. It can consist of one or more tokens.
    }

    @Override
    public void onCompleteResponse(ChatResponse completeResponse) {
        // this method is called when the model has completed responding
    }

    @Override
    public void onError(Throwable error) {
        // this method is called when an error occurs
    }
});

定制 AnthropicStreamingChatModel

与 AnthropicChatModel 完全相同,见上文。

批处理 API

Message Batches API 以标准逐词元价格的 50%,异步处理大量聊天请求。AnthropicBatchChatModel 实现了核心的 BatchChatModel 接口(submit、retrieve、cancel、list)。每个请求都以与一次 AnthropicChatModel 调用相同的参数提交。

java
AnthropicBatchChatModel model = AnthropicBatchChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName("claude-sonnet-4-5")
    .maxTokens(1024)
    .build();

// Submit a batch of requests
BatchResponse<ChatResponse> submitted = model.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 (typically well under an hour)
BatchResponse<ChatResponse> batch = model.retrieve(batchId);
while (!batch.state().isTerminal()) {
    TimeUnit.SECONDS.sleep(30); // throws InterruptedException
    batch = model.retrieve(batchId);
}

// Read the per-request results, in submission order
for (BatchItemResult<ChatResponse> result : batch.results()) {
    if (result.isSuccess()) {
        System.out.println(result.response().aiMessage().text());
    } else {
        System.out.println("Failed: " + result.error().message());
    }
}

用 model.list(...) 可分页浏览近期的批次,用 model.cancel(batchId) 可取消一个仍在处理中的批次。你取消的那个批次在 Anthropic 侧也会以 ended 状态结束,并被上报为 BatchState.CANCELLED;它仍可能包含在取消生效前已完成的那些请求的结果。

诸如思考或提示词缓存之类的 Anthropic 专有选项,通过 defaultRequestParameters(...) 配置,与 AnthropicChatModel 完全一致,且可逐次请求覆盖:

java
AnthropicBatchChatModel model = AnthropicBatchChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName("claude-sonnet-4-5")
    .maxTokens(4096)
    .defaultRequestParameters(AnthropicChatRequestParameters.builder()
        .thinkingType("enabled")
        .thinkingBudgetTokens(2000)
        .cacheSystemMessages(true)
        .cacheTtl("1h") // batches can take longer than the default 5-minute cache TTL
        .build())
    .returnThinking(true) // store the returned thinking in AiMessage.thinking()
    .build();

工具

Anthropic 在流式与非流式模式下都支持工具。

Anthropic 关于工具的文档可在这里找到。

工具选择

Anthropic 的工具选择特性对流式与非流式交互都可用:

  • toolChoice(ToolChoice.REQUIRED) 强制模型调用可用工具之一,而不是用文本回答。
  • toolChoiceName("get_weather") 强制模型调用某个特定工具。它可以单独使用;而当 toolChoice(ToolChoice) 也被设置时,命名工具优先于它。

并行工具使用

默认情况下,Anthropic Claude 可能会用多个工具来回答用户查询,但你可以通过设置 disableParallelToolUse(true) 来禁用并行工具。

服务端工具

Anthropic 的服务端工具通过 serverTools 参数受支持,这里是一个使用网页搜索工具的示例:

java
AnthropicServerTool webSearchTool = AnthropicServerTool.builder()
        .type("web_search_20250305")
        .name("web_search")
        .addAttribute("max_uses", 5)
        .addAttribute("allowed_domains", List.of("accuweather.com"))
        .build();

ChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName("claude-sonnet-4-5")
        .serverTools(webSearchTool)
        .logRequests(true)
        .logResponses(true)
        .build();

String answer = model.chat("What is the weather in Munich?");

通过 serverTools 指定的工具会被包含在每次对 Anthropic API 的请求中。

获取服务端工具结果

要访问服务端工具的原始结果(例如网页搜索结果、代码执行输出、生成文件的 fileId),请启用 returnServerToolResults(true)。结果会在 AiMessage.attributes() 下的 "server_tool_results" 键中提供:

java
ChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName("claude-sonnet-4-5")
        .serverTools(webSearchTool)
        .returnServerToolResults(true)
        .build();

ChatResponse response = model.chat("What is the weather in Munich?");
AiMessage aiMessage = response.aiMessage();

List<AnthropicServerToolResult> results = aiMessage.attribute("server_tool_results", List.class);
for (AnthropicServerToolResult result : results) {
    System.out.println("Type: " + result.type());
    System.out.println("Tool Use ID: " + result.toolUseId());
    System.out.println("Content: " + result.content());
}

默认禁用,以避免把可能很大的数据存储在 ChatMemory 中。

技能

Anthropic 的 Agent Skills 让 Claude 能通过在代码执行容器内运行预构建的技能,生成可下载的真实文档(.xlsx、.pptx、.docx、.pdf)。通过带类型的 skills 参数启用它们:

java
AnthropicChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName("claude-opus-4-8")
        .maxTokens(4096)
        .beta("code-execution-2025-08-25,skills-2025-10-02,files-api-2025-04-14")
        .skills(AnthropicSkill.XLSX, AnthropicSkill.PPTX)
        .returnServerToolResults(true)
        .build();

ChatResponse response = model.chat("Create an Excel spreadsheet with the numbers 1 to 5 in column A");

启用技能会自动:

  • 在请求中加入 container.skills 块,
  • 加入所需的 code_execution 服务端工具(除非已通过 serverTools(...) 配置了一个)。

你必须自行通过 beta(...) 选择接入所需的 beta 特性,如上面所示。这些是 beta 头,且它们的值会随时间变化,所以不会为你自动注入——请查看 Agent Skills 文档了解当前的那一组。

结合 returnServerToolResults(true),可把生成的文件 id 呈现在 AiMessage.attributes() 的 "server_tool_results" 键下(见上文获取服务端工具结果);这些文件可通过 Anthropic 的 Files API 下载,有效期 24 小时。

技能在 Claude Sonnet 4 / 4.5、Opus 4 及更新版本上受支持。每次请求最多可启用 8 个技能。同一个 skills(...) 参数在 AnthropicStreamingChatModel 上也可用。

工具搜索工具

Anthropic 的工具搜索工具通过 serverTools、工具 metadata 与 toolMetadataKeysToSend 参数受支持。

下面是在使用高层 AI 服务与 @Tool API 时的一个示例:

java
AnthropicServerTool toolSearchTool = AnthropicServerTool.builder()
        .type("tool_search_tool_regex_20251119")
        .name("tool_search_tool_regex")
        .build();

class Tools {

    @Tool(metadata = "{\"defer_loading\": true}")
    String getWeather(String location) {
        return "sunny";
    }

    @Tool
    String getTime(String location) {
        return "12:34:56";
    }
}

ChatModel chatModel = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName(CLAUDE_SONNET_4_5_20250929)
        .beta("advanced-tool-use-2025-11-20")
        .serverTools(toolSearchTool)
        .toolMetadataKeysToSend("defer_loading") // need to specify it explicitly
        .logRequests(true)
        .logResponses(true)
        .build();

interface Assistant {

    @SystemMessage("Use tool search if needed")
    String chat(String userMessage);
}

Assistant assistant = AiServices.builder(Assistant.class)
        .chatModel(chatModel)
        .tools(new Tools())
        .build();

assistant.chat("What is the weather in Munich?");

下面是在使用低层 ChatModel 与 ToolSpecification API 时的一个示例:

java
AnthropicServerTool toolSearchTool = AnthropicServerTool.builder()
        .type("tool_search_tool_regex_20251119")
        .name("tool_search_tool_regex")
        .build();

Map<String, Object> toolMetadata = Map.of("defer_loading", true);

ToolSpecification weatherTool = ToolSpecification.builder()
        .name("get_weather")
        .parameters(JsonObjectSchema.builder()
                .addStringProperty("location")
                .required("location")
                .build())
        .metadata(toolMetadata)
        .build();

ToolSpecification timeTool = ToolSpecification.builder()
        .name("get_time")
        .parameters(JsonObjectSchema.builder()
                .addStringProperty("location")
                .required("location")
                .build())
        .build();

ChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName(CLAUDE_SONNET_4_5_20250929)
        .beta("advanced-tool-use-2025-11-20")
        .serverTools(toolSearchTool)
        .toolMetadataKeysToSend(toolMetadata.keySet()) // need to specify it explicitly
        .logRequests(true)
        .logResponses(true)
        .build();

ChatRequest chatRequest = ChatRequest.builder()
        .messages(UserMessage.from("What is the weather in Munich? Use tool search if needed."))
        .toolSpecifications(weatherTool, timeTool)
        .build();

ChatResponse chatResponse = model.chat(chatRequest);

程序化工具调用

Anthropic 的程序化工具调用通过 serverTools、工具 metadata 与 toolMetadataKeysToSend 参数受支持。

下面是在使用高层 AI 服务与 @Tool API 时的一个示例:

java
AnthropicServerTool codeExecutionTool = AnthropicServerTool.builder()
        .type("code_execution_20250825")
        .name("code_execution")
        .build();

class Tools {

    static final String TOOL_METADATA = "{\"allowed_callers\": [\"code_execution_20250825\"]}";
    static final String TOOL_DESCRIPTION = """
            Returns daily minimum and maximum temperatures recorded
            for a specified city for a specified number of previous days.
            Response format: [{"min":0.0,"max":10.0},{"min":0.0,"max":20.0},{"min":0.0,"max":30.0}]
            """;

    record TemperatureRange(double min, double max) {}

    @Tool(value = TOOL_DESCRIPTION, metadata = TOOL_METADATA)
    List<TemperatureRange> getDailyTemperatures(String city, int days) {
        if ("Munich".equals(city) && days == 5) {
            return List.of(
                    new TemperatureRange(0.0, 1.0),
                    new TemperatureRange(0.0, 2.0),
                    new TemperatureRange(0.0, 3.0),
                    new TemperatureRange(0.0, 4.0),
                    new TemperatureRange(0.0, 5.0)
            );
        }

        throw new IllegalArgumentException("Unknown city: " + city + " or days: " + days);
    }

    @Tool(value = "Calculates the average of the specified list of numbers", metadata = TOOL_METADATA)
    Double average(List<Double> numbers) {
        return numbers.stream()
                .mapToDouble(Double::doubleValue)
                .average()
                .orElseThrow();
    }
}

ChatModel chatModel = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName(CLAUDE_SONNET_4_5_20250929)
        .beta("advanced-tool-use-2025-11-20")
        .serverTools(codeExecutionTool)
        .toolMetadataKeysToSend("allowed_callers") // need to specify it explicitly
        .logRequests(true)
        .logResponses(true)
        .build();

interface Assistant {

    String chat(String userMessage);
}

Assistant assistant = AiServices.builder(Assistant.class)
        .chatModel(chatModel)
        .tools(new Tools())
        .build();

assistant.chat("What was the average max temperature in Munich in the last 5 days?");

查看工具搜索工具一节,看在低层 ToolSpecification API 中指定工具 metadata 的示例。

工具使用示例

Anthropic 的工具使用示例通过工具 metadata 与 toolMetadataKeysToSend 参数受支持。

下面是在使用高层 AI 服务与 @Tool API 时的一个示例:

java
enum Unit {
    CELSIUS, FAHRENHEIT
}

class Tools {

    // NOTE: if javac "-parameters" option is not enabled, you need to change "location" to "arg0"
    // and "unit" to "arg1" inside the TOOL_METADATA to make it work.
    public static final String TOOL_METADATA = """
            {
                "input_examples": [
                    {
                        "location": "San Francisco, CA",
                        "unit": "FAHRENHEIT"
                    },
                    {
                        "location": "Tokyo, Japan",
                        "unit": "CELSIUS"
                    },
                    {
                        "location": "New York, NY"
                    }
                ]
            }
            """;

    @Tool(metadata = TOOL_METADATA)
    String getWeather(String location, @P(description = "temperature unit", required = false) Unit unit) {
        return "sunny";
    }
}

ChatModel chatModel = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName(CLAUDE_SONNET_4_5_20250929)
        .beta("advanced-tool-use-2025-11-20")
        .toolMetadataKeysToSend("input_examples") // need to specify it explicitly
        .logRequests(true)
        .logResponses(true)
        .build();

interface Assistant {

    String chat(String userMessage);
}

Assistant assistant = AiServices.builder(Assistant.class)
        .chatModel(chatModel)
        .tools(new Tools())
        .build();

assistant.chat("What is the weather in Munich in Fahrenheit?");

查看工具搜索工具一节,看在低层 ToolSpecification API 中指定工具 metadata 的示例。

缓存

Anthropic 能缓存提示词的开头(工具、系统消息与较早的消息),从而让下一个以相同内容开始的请求从缓存读取,而不是重新处理。从缓存读取比重新处理相同词元要便宜、快得多,而写入缓存则比普通输入词元稍贵一些。因此,当同一个提示词前缀会被发送多次时,缓存才划算——多轮对话、调用工具的 AI 服务以及智能体都属于这种情况。

默认禁用缓存。它按提示词的各个部分用下述选项启用。Anthropic 严格按内容匹配缓存,顺序为 工具 → 系统消息 → 消息,因此请求之间会变化的任何东西(例如系统消息里的当前时间,或一组不同的工具)都会使其后所有内容无法命中缓存。短于模型特定的最小值(介于 512 与 4,096 词元之间)的提示词不会被缓存。

该用哪些选项:

  • 只要系统消息与工具在各请求之间保持一致,就启用 cacheSystemMessages 与 cacheTools(见下文)。它们对任何用法都划算,包括不带聊天记忆的独立调用。
  • 当对话历史被保留并从一次请求到下一次不断增长时(例如某个 AI 服务或智能体在循环中调用工具),再额外启用 cacheAutomatically(见自动缓存)。当对话开头在每个请求都变化时——例如聊天记忆每轮都淘汰旧消息(一个满的 MessageWindowChatMemory 或 TokenWindowChatMemory)——或对于不带聊天记忆的独立调用,请勿启用它:那样它花费多于省下。

Anthropic 每个请求最多允许 4 个缓存断点。cacheSystemMessages、cacheTools 与 cacheAutomatically 各用一个,每个带 cache_control 属性标记的消息也用一个。带更多断点的请求会被 Anthropic 拒绝。

被缓存的内容由 Anthropic 保存缓存 TTL那么久,且不与其他组织共享。细节参见提示词缓存文档。

AnthropicChatModel 与 AnthropicStreamingChatModel 会在响应中返回 AnthropicTokenUsage,它包含 cacheCreationInputTokens(写入缓存的词元)与 cacheReadInputTokens(从缓存读取的词元)。

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

缓存系统消息与工具

cacheSystemMessages 用 cache_control 标记最后一条系统消息,cacheTools 标记最后一个工具。由于工具排在系统消息之前,系统消息的断点会把两者都缓存。工具断点则额外能在系统消息在各请求间变化时仍保持工具被缓存。

这些断点在每个请求中都停留在相同位置,因此只要系统消息与工具保持一致就能划算,对不带聊天记忆的独立调用亦然:

java
ChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName("claude-opus-5-5")
    .cacheSystemMessages(true)
    .cacheTools(true)
    .build();

自动缓存

当启用 cacheAutomatically 时,Anthropic 会把缓存断点放在每个请求的最后一个块上,并随对话增长向前移动它,从而每个请求都把此前发送的一切从缓存读取。无需手工标记任何消息来缓存,这也让它能用于消息由 LangChain4j 创建的 AI 服务与智能体。

只有当每个请求都以先前请求发送的一切开头时,它才划算(见该用哪些选项)。否则,每个请求都会为整个提示词支付缓存写入价格而没有任何东西被读回,这比完全不缓存还贵。使用它时,请同时启用 cacheSystemMessages 与 cacheTools,以便即便对话开头发生变化也能保持系统消息与工具被缓存。

在下面的示例中,一次 assistant.chat(...) 调用内的每次工具调用都会累加到对话上,因此同一个工具循环中后续的请求会把较早的那些从缓存读取:

java
ChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName("claude-opus-5-5")
    .cacheSystemMessages(true)
    .cacheTools(true)
    .cacheAutomatically(true)
    .build();

Assistant assistant = AiServices.builder(Assistant.class)
    .chatModel(model)
    .tools(new MyTools())
    .build();

自动缓存是作为请求顶层的 cache_control 字段发送的。不支持该字段的 Anthropic 兼容网关与代理可能拒绝请求或忽略该字段。那种情况下,请改为缓存系统消息、工具与单独的消息。

缓存单独的消息

UserMessage、AiMessage 与 ToolExecutionResultMessage 各自都可以通过把 cache_control 属性设为 ephemeral 来标记为缓存。该缓存控制标记会自动应用到消息的最后一个内容块上(对 ToolExecutionResultMessage 而言,就是 tool_result 块本身)。

UserMessage 暴露一个可变的属性 map:

java
UserMessage userMessage = UserMessage.from("Hello cached world");
userMessage.attributes().put("cache_control", "ephemeral");

AiMessage 与 ToolExecutionResultMessage 携带一个不可变的属性 map,因此请通过 toBuilder() 设置它。要缓存一段每轮都在增长的对话,例如一个智能体工具执行循环,自动缓存更简单,因为无需标记任何消息。当你需要控制缓存断点位于何处时,标记单独的消息才有用。

java
AiMessage aiMessage = someAiMessage.toBuilder()
        .attributes(Map.of("cache_control", "ephemeral"))
        .build();

ToolExecutionResultMessage toolExecutionResultMessage = someToolExecutionResultMessage.toBuilder()
        .attributes(Map.of("cache_control", "ephemeral"))
        .build();

缓存 TTL

被缓存的内容默认保留 5 分钟,且每次缓存命中都会刷新这段时间。若共享同一提示词前缀的请求通常相隔超过 5 分钟(例如用户 20 分钟后回复,或批处理),缓存可以改为一小时:

java
ChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName("claude-opus-5-5")
    .cacheAutomatically(true)
    .cacheTtl("1h") // "5m" by default
    .build();

这两个值也可作为常量 AnthropicChatRequestParameters.CACHE_TTL_5M 与 AnthropicChatRequestParameters.CACHE_TTL_1H 使用。

TTL 适用于所有被缓存的内容:系统消息、工具、自动缓存的消息,以及带 cache_control 属性标记的消息。除非其中至少有一项被缓存,否则它不起作用。写入一小时缓存的成本是基础输入词元价格的 2 倍,相比之下五分钟缓存为 1.25 倍,因此只有当被缓存内容在一小时内至少被读回几次时,它才划算。

缓存诊断

Anthropic 的(beta)缓存诊断功能会上报为何未命中一次提示词缓存命中(模型、系统提示词、工具或消息历史发生了变化),而不只是显示 cacheReadInputTokens 降为零。

它需要 cache-diagnosis-2026-04-07 beta 头,并通过 returnCacheDiagnostics 启用。在对话的第一轮把 previousMessageId 作为 null 传入以选择接入,并在每一后续轮传入上一个响应的 id:

java
AnthropicChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .beta("cache-diagnosis-2026-04-07")
        .returnCacheDiagnostics(true)
        .build();

ChatResponse response1 = model.chat(ChatRequest.builder()
        .messages(UserMessage.from("Summarize section 1."))
        .build());
String previousMessageId = ((AnthropicChatResponseMetadata) response1.metadata()).id();

ChatResponse response2 = model.chat(ChatRequest.builder()
        .messages(UserMessage.from("Summarize section 1."), UserMessage.from("Now summarize section 2."))
        .parameters(AnthropicChatRequestParameters.builder()
                // returnCacheDiagnostics is already enabled on the model above, so on subsequent turns
                // you only need to supply the previousMessageId (it changes every turn).
                .previousMessageId(previousMessageId)
                .build())
        .build());

AnthropicCacheDiagnostics diagnostics = ((AnthropicChatResponseMetadata) response2.metadata()).cacheDiagnostics();
if (diagnostics != null && diagnostics.cacheMissReasonType() != null) {
    // e.g. "model_changed", "system_changed", "tools_changed", "messages_changed",
    // "previous_message_not_found" or "unavailable"
    System.out.println(diagnostics.cacheMissReasonType());
}

当未请求诊断或未发现问题时,cacheDiagnostics() 为 null。

思考

AnthropicChatModel 与 AnthropicStreamingChatModel 都支持扩展思考与自适应思考特性。

它由以下参数控制:

  • thinkingType 与 thinkingBudgetTokens:启用思考,更多细节见这里。
  • thinkingDisplay:控制 API 是否在思考签名旁返回可读的思考文本。有效值为 "summarized"(思考块包含推理的可读摘要)与 "omitted"(思考块只含空的思考文本,仅返回加密签名)。当未设置时,API 会挑选一个取决于模型的默认值:较新的 Claude 模型默认为 "omitted",较早的默认为 "summarized",见 Anthropic 文档。每当需要思考文本本身时——例如为了把它展示给终端用户——就设为 "summarized"。两种情况下模型都以相同方式思考并计费;改变的只是思考文本的可见性。
  • returnThinking:控制是否在 AiMessage.thinking() 中返回思考(若可用),以及在使用 AnthropicStreamingChatModel 时是否调用 StreamingChatResponseHandler.onPartialThinking() 与 TokenStream.onPartialThinking() 回调。默认禁用。若启用,思考签名也会被存储并返回在 AiMessage.attributes() 中。请注意,当 API 不返回思考文本时,AiMessage.thinking() 会保持为空,见上文的 thinkingDisplay。
  • sendThinking:控制是否在后续请求中把存储于 AiMessage 的思考与签名发送给 LLM。 默认启用。

要配置 effort 参数,请在构建模型时设置 customParameters:

java
ChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName("claude-sonnet-5")
        .customParameters(Map.of("output_config", Map.of("effort", "max")))
        ...
        .build();

下面是一个如何配置思考的示例:

java
ChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName("claude-sonnet-4-5-20250929")
        .thinkingType("enabled")
        .thinkingBudgetTokens(1024)
        .maxTokens(1024 + 100)
        .returnThinking(true)
        .sendThinking(true)
        .build();

较新的 Claude 模型除非 thinkingDisplay 索要,否则不返回思考文本,因此当它未设置时 AiMessage.thinking() 为空:

java
ChatModel model = AnthropicChatModel.builder()
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .modelName("claude-sonnet-5")
        .thinkingType("adaptive")
        .thinkingDisplay("summarized")
        .maxTokens(16000)
        .returnThinking(true)
        .sendThinking(true)
        .build();

对话中途的系统消息

默认情况下,每条 SystemMessage 无论出现在消息列表的何处,都会被折入顶层的 system 提示词。这符合 Anthropic 一贯的工作方式,未变。

Claude Opus 4.8 额外支持对话中途系统消息:一条出现在对话已开始之后的 SystemMessage 可以作为 messages 数组中的一个 system 条目内联发送,从而从对话中的那个点起生效(例如,在会话进行到一半时更改助手指令)。用 midConversationSystemMessages(true) 启用它:

java
AnthropicChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName("claude-opus-4-8")
    .midConversationSystemMessages(true)
    .build();

ChatResponse response = model.chat(ChatRequest.builder()
    .messages(
        SystemMessage.from("You are a helpful assistant."), // leading -> top-level "system" prompt
        UserMessage.from("Hello"),
        AiMessage.from("Hi! How can I help?"),
        SystemMessage.from("From now on, answer only in French."), // mid-conversation -> inline
        UserMessage.from("What is the capital of Spain?"))
    .build());

启用时,前置的 SystemMessage(那些在首个 user/assistant 消息之前的)仍会填充顶层的 system 提示词;只有在对话开始之后出现的那些才会内联发送。这不仅仅是约定——Anthropic 要求如此:一个 system 消息不能是 messages 数组中的首个条目,且基础系统提示词本就应待在稳定的、可缓存的前缀里。当该选项禁用(默认)时,行为不变,所有 SystemMessage 都进入顶层的 system 提示词。

它也可通过 AnthropicChatRequestParameters 逐次请求设置(见逐次请求参数)。

NOTE

Anthropic 对对话中途系统消息可放置的位置有所限制:它必须紧跟在一个 user 轮次之后(包括携带工具结果的 user 轮次),必须在 assistant 轮次之前或终结该数组,且不得置于一个 tool_use 块与其 tool_result 之间。也不允许连续的 system 消息。请注意,在选项禁用时,langchain4j 会把多条 SystemMessage 合并进顶层的 system 字段;而启用时,两条相邻的中途 SystemMessage 会作为连续的内联 system 条目被发送并被拒绝。langchain4j 不会重排或合并内联消息——它按你提供的位置发送——因此一个不受支持的模型或一个无效的放置会导致 Anthropic API 返回 400。

PDF 支持

Anthropic Claude 支持处理 PDF 文档。你可以通过 URL 或 base64 编码数据发送 PDF。

通过 URL 发送 PDF

java
UserMessage message = UserMessage.from(
    PdfFileContent.from(URI.create("https://example.com/document.pdf")),
    TextContent.from("What are the key findings in this document?")
);

ChatResponse response = model.chat(message);

通过 Base64 发送 PDF

java
String base64Data = Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("document.pdf")));

UserMessage message = UserMessage.from(
    PdfFileContent.from(base64Data, "application/pdf"),
    TextContent.from("Summarize this document.")
);

ChatResponse response = model.chat(message);

关于 PDF 支持的更多信息可在这里找到。

设置自定义聊天请求参数

在构建 AnthropicChatModel 与 AnthropicStreamingChatModel 时,你可以在 HTTP 请求的 JSON 体内为聊天请求配置自定义参数。这里是启用上下文编辑的一个示例:

java
record Edit(String type) {}
record ContextManagement(List<Edit> edits) { }
Map<String, Object> customParameters = Map.of("context_management", new ContextManagement(List.of(new Edit("clear_tool_uses_20250919"))));

ChatModel model = AnthropicChatModel.builder()
    .apiKey(System.getenv("ANTHROPIC_API_KEY"))
    .modelName(CLAUDE_SONNET_4_5_20250929)
    .beta("context-management-2025-06-27")
    .customParameters(customParameters)
    .logRequests(true)
    .logResponses(true)
    .build();

String answer = model.chat("Hi");

这会产出一个带如下请求体的 HTTP 请求:

json
{
    "model" : "claude-sonnet-4-5-20250929",
    "messages" : [ {
        "role" : "user",
        "content" : [ {
            "type" : "text",
            "text" : "Hi"
        } ]
    } ],
    "context_management" : {
        "edits" : [ {
            "type" : "clear_tool_uses_20250919"
        } ]
    }
}

或者,自定义参数也可以指定为嵌套 map 的结构:

java
Map<String, Object> customParameters = Map.of(
        "context_management",
        Map.of("edits", List.of(Map.of("type", "clear_tool_uses_20250919")))
);

访问原始 HTTP 响应与服务端事件流(SSE)

使用 AnthropicChatModel 时,你可以访问原始 HTTP 响应:

java
SuccessfulHttpResponse rawHttpResponse = ((AnthropicChatResponseMetadata) chatResponse.metadata()).rawHttpResponse();
System.out.println(rawHttpResponse.body());
System.out.println(rawHttpResponse.headers());
System.out.println(rawHttpResponse.statusCode());

使用 AnthropicStreamingChatModel 时,你可以访问原始 HTTP 响应(见上)以及原始服务端事件流:

java
List<ServerSentEvent> rawServerSentEvents = ((AnthropicChatResponseMetadata) chatResponse.metadata()).rawServerSentEvents();
System.out.println(rawServerSentEvents.get(0).data());
System.out.println(rawServerSentEvents.get(0).event());

AnthropicTokenCountEstimator

java
TokenCountEstimator tokenCountEstimator = AnthropicTokenCountEstimator.builder()
        .modelName(CLAUDE_3_OPUS_20240229)
        .apiKey(System.getenv("ANTHROPIC_API_KEY"))
        .logRequests(true)
        .logResponses(true)
        .build();

List<ChatMessage> messages = List.of(...);

int tokenCount = tokenCountEstimator.estimateTokenCountInMessages(messages);

Quarkus

更多细节见这里。

Spring Boot

导入 Anthropic 的 Spring Boot starter:

xml
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-anthropic-spring-boot4-starter</artifactId>
    <version>1.22.0-beta32</version>
</dependency>

NOTE

该 starter 需要 Spring Boot 4。在 Spring Boot 3 上,请改用 langchain4j-anthropic-spring-boot-starter。 详见 Spring Boot 集成。

配置 AnthropicChatModel bean:

langchain4j.anthropic.chat-model.api-key = ${ANTHROPIC_API_KEY}

配置 AnthropicStreamingChatModel bean:

langchain4j.anthropic.streaming-chat-model.api-key = ${ANTHROPIC_API_KEY}

示例

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