Skip to content
Spring AI 文档版本 2.1.0-SNAPSHOT 源快照 3b073065 更新于 2026-10-16

把 Anthropic 模块迁移到官方 Java SDK

在 2.0.0-M3 中,spring-ai-anthropic 被重写于官方 com.anthropic:anthropic-java SDK 之上,取代了手写的 RestClient / WebClient 实现。先前的 AnthropicApi 类是一个 2,300 行的文件,含 47 个嵌套 DTO record。

新模块是 SDK 之上的一层薄适配器,而非并行的 API。Spring AI 的价值在于它自己的抽象——ChatModel、ChatClient、顾问、可观测性、自动配置——以及跨服务商可用的特性。凡 SDK 已涵盖的关切(cache-control 建模、流式、速率限制处理),我们丢弃了先前模块的包装而非沿袭,因此应用直接使用 SDK 的类型。这让接口面保持小巧,并避免随 Anthropic 发布新 SDK 版本而产生漂移。

Maven 坐标、spring-ai-starter-model-anthropic Boot starter 和 spring.ai.anthropic.* 配置属性都未改变。ChatClient API 未变。ChatModel.call(Prompt) 与 ChatModel.stream(Prompt) 保持其签名。AnthropicChatOptions 保留所有既有字段,并为 skills、web search、service tier、inference geo 和 structured output 新增字段。

发生了什么变化

领域变更
AnthropicChatModel 构造公共构造器移除。使用 AnthropicChatModel.builder()。
org.springframework.ai.anthropic.api.AnthropicApi 及其嵌套 DTO移除。对于直接 API 访问,使用 SDK 的 com.anthropic.client.AnthropicClient。
AnthropicCacheOptions、AnthropicCacheStrategy、AnthropicCacheTtl、CacheBreakpointTracker、CacheEligibilityResolver从 org.springframework.ai.anthropic.api(及 api.utils)移出到根包 org.springframework.ai.anthropic。枚举值不变。
CitationDocument重命名为 AnthropicCitationDocument。
AnthropicCacheType、StreamHelper、metadata.AnthropicRateLimit移除,无直接替代。
默认 maxTokens从 500 改为 4096。
传递依赖 com.squareup.okhttp3:okhttp新增,由 com.anthropic:anthropic-java 引入。

若你只用 ChatClient 或 ChatModel

若你的代码看起来像这样,无需迁移:

java
@Autowired ChatClient.Builder builder;

String response = builder.build()
    .prompt("Tell me a joke")
    .call()
    .content();

自动配置会产出一个接线到新的、基于 SDK 实现的 AnthropicChatModel bean。调用代码不受影响。

需要留意的一处行为变更是新的默认 maxTokens 值(见 default-max-tokens)。

若你以编程方式构造 AnthropicChatModel

用构建器替换直接的构造器使用:

java
// Before
AnthropicApi anthropicApi = new AnthropicApi(apiKey);
AnthropicChatModel chatModel = new AnthropicChatModel(anthropicApi,
    AnthropicChatOptions.builder().model("claude-haiku-4-5").maxTokens(2048).build(),
    retryTemplate,
    toolCallingManager);

// After
AnthropicChatModel chatModel = AnthropicChatModel.builder()
    .apiKey(apiKey)
    .defaultOptions(AnthropicChatOptions.builder()
        .model("claude-haiku-4-5")
        .maxTokens(2048)
        .build())
    .toolCallingManager(toolCallingManager)
    .build();

构建器还接受 baseUrl、timeout、maxRetries、proxy、customHeaders、observationRegistry 和 observationConvention。没有 retryTemplate 构建器方法;重试现在由 SDK 处理(见 retry-behavior)。

若你导入了缓存或引用类型

缓存与引用辅助类从 api(及 api.utils)子包移出到根包 org.springframework.ai.anthropic。请如下更新导入:

旧导入新导入
org.springframework.ai.anthropic.api.AnthropicCacheOptionsorg.springframework.ai.anthropic.AnthropicCacheOptions
org.springframework.ai.anthropic.api.AnthropicCacheStrategyorg.springframework.ai.anthropic.AnthropicCacheStrategy
org.springframework.ai.anthropic.api.AnthropicCacheTtlorg.springframework.ai.anthropic.AnthropicCacheTtl
org.springframework.ai.anthropic.api.utils.CacheBreakpointTrackerorg.springframework.ai.anthropic.CacheBreakpointTracker
org.springframework.ai.anthropic.api.utils.CacheEligibilityResolverorg.springframework.ai.anthropic.CacheEligibilityResolver
org.springframework.ai.anthropic.api.CitationDocumentorg.springframework.ai.anthropic.AnthropicCitationDocument

AnthropicCacheStrategy(NONE、TOOLS_ONLY、SYSTEM_ONLY、SYSTEM_AND_TOOLS、CONVERSATION_HISTORY)和 AnthropicCacheTtl(FIVE_MINUTES、ONE_HOUR)的枚举值不变。plainText(...)、pdf(...) 和 customContent(...) 工厂方法在重命名后的 AnthropicCitationDocument 上仍然存在。

若你直接使用了 AnthropicApi

AnthropicApi、它的嵌套 DTO record 和 AnthropicCacheType 都没了。在动用 SDK 客户端之前,先考虑 AnthropicChatModel 是否涵盖了你在做的事。它通常可以,且你保留了框架集成。

AnthropicChatModel 在原始 AnthropicClient 之上额外提供:

  • 服务商中立的请求与响应类型(Prompt、ChatResponse、Generation、Usage),使应用代码不依赖 com.anthropic.*。
  • 与 ToolCallback 和 ToolCallingManager 循环集成的工具调用,包括自动多轮执行。
  • 以 Reactor Flux<ChatResponse> 而非 SDK 基于回调的 AsyncStreamResponse 提供的流式。
  • 带策略建模、TTL 控制和 4 断点强制的提示词缓存(AnthropicCacheOptions)。
  • 在 ChatResponseMetadata 下呈现的、带四种位置变体的 Citation。
  • 作为 AnthropicChatOptions 字段的 Skills、内建 web search、service tier、inference geo 和 structured output,都可从 spring.ai.anthropic.chat.* 绑定。
  • Spring Boot 自动配置与 Micrometer 观测。
  • 模型之上的 ChatClient 流水线(顾问、消息模板、RAG、对话记忆、结构化输出转换器)。
  • 服务商可移植性:同样的 ChatClient 代码可对接 OpenAI、Bedrock、Google GenAI 等运行。

对于典型的聊天用法,改用 AnthropicChatModel.builder()(见 programmatic-construction):

java
// Before
AnthropicApi api = new AnthropicApi(apiKey);
AnthropicApi.ChatCompletionRequest req = new AnthropicApi.ChatCompletionRequest(
    AnthropicApi.ChatModel.CLAUDE_HAIKU_4_5.getValue(),
    List.of(new AnthropicApi.AnthropicMessage(List.of(new AnthropicApi.ContentBlock("hello")), AnthropicApi.Role.USER)),
    null, 1024, null, 0.7, null, null, null, null, false);
ResponseEntity<AnthropicApi.ChatCompletionResponse> resp = api.chatCompletionEntity(req);

// After
AnthropicChatModel chatModel = AnthropicChatModel.builder()
    .apiKey(apiKey)
    .defaultOptions(AnthropicChatOptions.builder()
        .model("claude-haiku-4-5")
        .maxTokens(1024)
        .temperature(0.7)
        .build())
    .build();
ChatResponse response = chatModel.call(new Prompt("hello"));

如果你确实需要一个 AnthropicChatModel 未暴露的 Anthropic API 面(一个 beta 端点、files API、自定义 skills CRUD),则下沉到 SDK 客户端。那时你在框架之外——没有可观测性、没有服务商中立、没有 ChatClient 流水线:

java
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

AnthropicClient client = AnthropicOkHttpClient.builder().apiKey(apiKey).build();
MessageCreateParams params = MessageCreateParams.builder()
    .model(Model.CLAUDE_HAIKU_4_5)
    .maxTokens(1024)
    .temperature(0.7)
    .addUserMessage("hello")
    .build();
com.anthropic.models.messages.Message message = client.messages().create(params);

手写的 record 类型在 SDK 的 com.anthropic.models.messages.* 下有直接对应物:

移除的类型(旧 AnthropicApi.*)SDK 替代(com.anthropic.models.messages.*)
ChatCompletionRequestMessageCreateParams
ChatCompletionResponseMessage
AnthropicMessageMessageParam
ContentBlockContentBlock(sealed union:TextBlock、ToolUseBlock、ThinkingBlock、RedactedThinkingBlock、ServerToolUseBlock、WebSearchToolResultBlock、ContainerUploadBlock,……)
ToolTool
ToolChoiceAuto / ToolChoiceAny / ToolChoiceTool / ToolChoiceNoneToolChoice(带 ToolChoiceAuto、ToolChoiceAny、ToolChoiceTool、ToolChoiceNone 变体的 sealed union)
Source(图像 / PDF 媒体)Base64ImageSource、UrlImageSource、Base64PdfSource、UrlPdfSource
MessageStartEvent、ContentBlockStartEvent、ContentBlockDeltaEvent、MessageDeltaEvent,……RawMessageStreamEvent(sealed union)

NOTE

ToolUseBlock.input() 返回 SDK 的 JsonValue,而非一个 JSON 字符串。对 JsonValue 调用 .toString() 会产生 Java 的 map 语法({key=value}),看着像 JSON 但其实不是。用 JsonValue.Visitor<T> 遍历它,或通过 Jackson 序列化以得到真正的 JSON 字符串。

转而使用 SDK 等价物而移除

这些类型被丢弃,因为 SDK 已暴露同样的概念。直接使用 SDK 类型。

移除改用
org.springframework.ai.anthropic.api.AnthropicCacheTypecom.anthropic.models.messages.CacheControlEphemeral。旧的枚举只携带字面值 ephemeral,而这也是 API 唯一支持的 cache-control 类型。
org.springframework.ai.anthropic.api.StreamHelpercom.anthropic.core.http.AsyncStreamResponse<RawMessageStreamEvent>。StreamHelper 是旧 WebClient 流式路径的内部 SSE-合并辅助;SDK 现在原生交付流事件,Spring AI 在内部把它们桥接到一个 Reactor Flux。调用 ChatModel.stream(Prompt) 的代码不受影响。
org.springframework.ai.anthropic.metadata.AnthropicRateLimitcom.anthropic.errors.RateLimitException(在重试耗尽后由 SDK 抛出),加上 SDK 响应对象上的头部。把原先从 ChatResponseMetadata 读取速率限制元数据的代码替换为异常处理。

行为变更

提示词级选项不再与模型默认值合并

先前模块会通过 ModelOptionsUtils.copyToTarget(...) 和 ModelOptionsUtils.merge(...) 把提示词级 AnthropicChatOptions 合并进模型级默认,于是 model、temperature 及任何未设置的字段都会从模型默认补齐:

java
// Before: only maxTokens set; model + temperature inherited from defaults.
Prompt prompt = new Prompt(
    "Tell me a joke",
    AnthropicChatOptions.builder().maxTokens(2048).build());
chatModel.call(prompt);

新模块不做合并。提示词级的选项实例原样使用;若提示词没有选项,则使用模型默认。

java
// After: prompt-level options must be "full", or null.
Prompt prompt = new Prompt(
    "Tell me a joke",
    chatModel.getOptions().mutate().maxTokens(2048).build());
chatModel.call(prompt);

这是对 升级到 2.0.0-M5 — ChatOptions 处理 中更广泛变更的一次前向移植,为 Anthropic 提前落地。ChatClient 在到达模型之前会做自己的合并,因此使用 ChatClient 的调用者不受影响。

默认 maxTokens 现为 4096

AnthropicChatOptions 把 maxTokens 默认设为 4096 而非 500。先前的默认时常会截断响应;新值与其他 Spring AI 聊天模块一致。

若你依赖 500 来约束成本,请显式设置它:

properties
spring.ai.anthropic.chat.max-tokens=500

重试使用 SDK maxRetries,而非 RetryTemplate

先前模块在其构造器中接受一个 Spring Retry 的 RetryTemplate。重试现在由 SDK 处理,并通过 maxRetries(默认 2)配置:

properties
spring.ai.anthropic.max-retries=5

任何专为 Anthropic 模块接线的 RetryTemplate bean 都可移除。若要更细的控制,通过一个自定义的 AnthropicSetup 配置 SDK 客户端。

流式思考事件

有两处变更影响任何订阅了原始 Flux<ChatResponse> 流(而非让 ChatClient 或 MessageAggregator 折叠它)的人。

先前模块把思考块的文本与签名捆绑进单个 Generation。SDK 把它们作为独立事件交付,新模块照此转发:一个带 properties.signature 的 Generation 会在思考文本增量之后、任何后续文本增量之前到达。MessageAggregator 和 ChatClient 的内建聚合会透明地吸收这个额外的块。

思考文本增量现在还包含 properties.thinking = Boolean.TRUE。先前模块把它们作为纯内容发出,使调用者在流中途没有办法可靠地区分思考文本与响应文本。

完整的流式元数据键集合:

块Generation 携带
思考文本增量content = <thinking text>,properties.thinking = true(M3 新增)
思考签名增量空的 content,properties.signature = <signature>
涂黑的思考块空的 content,properties.data = <data>
同步思考块(非流式)content = <thinking text>,properties.signature = <signature>(单个 Generation)

提示词缓存变更

若你配置了 AnthropicCacheOptions,有三项行为需要知道:

  • 4 断点限制在 Spring AI 内强制,而非在 API。 Anthropic 每请求至多允许 4 个缓存断点。先前模块会把标记透传并让 API 拒绝超额。CacheBreakpointTracker 现在会计数并静默跳过第 4 个之后的新增,记录一次性的 WARN。最可能触顶的方式是把 SYSTEM_AND_TOOLS 与多块系统缓存和引用文档结合。那些此前以 API 错误失败的请求现在可能以减少的缓存成功,因此升级后请检查你的缓存命中率。
  • AnthropicCacheStrategy.NONE 意为“未设置”,而非“禁用”。 在提示词层级设置 NONE 会回退到模型默认。若模型默认开启了缓存而你想关闭它,请以 AnthropicCacheOptions.disabled() 作为默认构建第二个 AnthropicChatModel。
  • 工具的缓存 TTL 取自 MessageType.SYSTEM。 resolveToolCacheControl 无论策略如何都查 messageTypeTtl(MessageType.SYSTEM)。设置 messageTypeTtl(MessageType.USER, ONE_HOUR) 对工具缓存没有影响。

引用文档一致性在客户端校验

Anthropic API 要求单个请求中每个带引用配置的 DocumentBlockParam 都共享相同的 citations.enabled 值。AnthropicChatOptions.validateCitationConsistency() 现在强制这一点,并在请求发出前抛出 IllegalArgumentException。先前模块让 API 返回一个 HTTP 400。混用启用与禁用引用文档的测试或调用点,现在会在构建期失败而非在网络调用时。

新的 OkHttp 传递依赖

com.anthropic:anthropic-java 会引入 com.squareup.okhttp3:okhttp。多数应用不会察觉;若你有严格的依赖收敛规则或一个已有的 OkHttp 版本钉,你可能需要一个 <dependencyManagement> 条目。

新能力

此次迁移还启用了若干 Anthropic 特性。完整参考见 Anthropic 聊天。

  • 原生 skills(AnthropicSkill、AnthropicSkillContainer)。
  • 内建 web search 工具(AnthropicWebSearchTool)。
  • 服务层选择(AnthropicServiceTier)。
  • 用于数据驻留的 inference geo(us、eu)。
  • 通过 JsonOutputFormat 和 Effort 的原生结构化输出(需要 claude-sonnet-4-6 或更新)。
  • 扩展思考的显示模式(summarized / omitted)。
  • 带四种位置变体的 Citation 类型(CHAR_LOCATION、PAGE_LOCATION、CONTENT_BLOCK_LOCATION、WEB_SEARCH_RESULT_LOCATION)。
  • AnthropicChatOptions#httpHeaders 上的逐请求 HTTP 头,不同于 AbstractAnthropicOptions 上客户端级的 customHeaders。customHeaders 在客户端上设置一次并适用于每个请求;httpHeaders 逐 Prompt 设置并在请求构建时合并。对请求跟踪、beta-API 开关和路由很有用。

会静默失败之处

编译错误很容易发现。而下面这些不抛异常,而是产出不同的输出。

  • 部分提示词级选项。 new Prompt(text, AnthropicChatOptions.builder().maxTokens(2048).build()) 不再从模型默认继承 model、temperature 等(见 prompt-option-merging)。没有编译错误、没有异常;请求会以不同的值运行。若升级后输出漂移且你直接调用 ChatModel,先到此处排查。
  • 若升级后成本攀升,检查你是否依赖旧的 500 令牌 maxTokens 默认来约束响应。
  • 第 4 个之后的缓存断点被丢弃。 把多块系统缓存与工具和引用文档叠加,可能超过 Anthropic 的 4 断点上限。CacheBreakpointTracker 会跳过多余的并一次性记录 WARN。缓存命中率下降但没有错误。
  • 陈旧的 org.springframework.ai.anthropic.api.AnthropicCache* 导入是升级后多数编译错误的根源。一次全项目的查找替换即可修复。

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