Spring AI 中对 AWS Bedrock 提示缓存的支持

工程 | Soby Chacko | 2025 年 10 月 30 日 | ...

在我们之前关于 Anthropic 提示缓存的博文中,我们探讨了提示缓存如何通过重用先前处理过的提示内容,显著降低 API 成本和延迟。我们介绍了 Spring AI 针对 Anthropic Claude 模型的五种策略性缓存模式,并展示了它们如何在尊重 4 个断点限制的同时自动处理缓存断点位置。

AWS Bedrock 将提示缓存引入更广泛的生态系统——同时支持 Claude 模型(通过 Bedrock 访问)和亚马逊自己的 Nova 系列。如果您正在考虑使用 Bedrock 或已经在使用它,您会发现 Spring AI 的相同缓存策略也适用,但有一些关键区别。

在这篇博文中,我们将解释 AWS Bedrock 中的提示缓存与 Anthropic 直接 API 相比有哪些不同,以及 Spring AI 如何在两个提供商之间保持一致的模式。

AWS Bedrock 增加了什么

AWS Bedrock 将提示缓存扩展到 Claude 之外,包括 Amazon Nova 模型

Claude 模型(通过 Bedrock)

  • Claude 3 Opus 4.1, Opus 4, Sonnet 4.5, Sonnet 4, Haiku 4.5
  • Claude 3.7 Sonnet, 3.5 Haiku
  • 完整的缓存支持,包括工具定义

Amazon Nova 模型:

  • Nova Micro, Lite, Pro, Premier
  • 仅支持系统和对话缓存

有关完整的模型详细信息,请参阅AWS Bedrock 支持的模型

与 Anthropic 直接 API 的主要区别

虽然核心缓存概念保持不变(如我们之前的博文所述),但 AWS Bedrock 有几个值得理解的区别。

固定的 5 分钟缓存 TTL

AWS Bedrock 使用固定的 5 分钟 TTL,没有配置选项,而 Anthropic 的直接 API 提供可选的 1 小时缓存。

// Anthropic direct API: optional TTL configuration
AnthropicCacheOptions.builder()
    .strategy(AnthropicCacheStrategy.SYSTEM_ONLY)
    .messageTypeTtl(MessageType.SYSTEM, AnthropicCacheTtl.ONE_HOUR)
    .build()

// AWS Bedrock: always 5 minutes
BedrockCacheOptions.builder()
    .strategy(BedrockCacheStrategy.SYSTEM_ONLY)
    .build()

对于高频工作负载(每隔几秒或几分钟请求一次),5 分钟 TTL 可以保持缓存的“热度”。对于请求间隔 5-30 分钟的应用程序,缓存条目可能会在请求之间过期。

Nova 不支持工具缓存

Amazon Nova 模型不支持工具缓存。尝试在 Nova 上使用 TOOLS_ONLYSYSTEM_AND_TOOLS 策略会抛出异常。

// Works with Claude models
BedrockChatOptions.builder()
    .model("anthropic.claude-sonnet-4-5-20250929-v1:0")
    .cacheOptions(BedrockCacheOptions.builder()
        .strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS)
        .build())
		.toolCallbacks(tools)
    .build()

// Throws exception with Nova models
BedrockChatOptions.builder()
    .model("us.amazon.nova-pro-v1:0")
    .cacheOptions(BedrockCacheOptions.builder()
        .strategy(BedrockCacheStrategy.TOOLS_ONLY)
        .build())
		.toolCallbacks(tools)
    .build()

// Use SYSTEM_ONLY for Nova
BedrockChatOptions.builder()
    .model("us.amazon.nova-pro-v1:0")
    .cacheOptions(BedrockCacheOptions.builder()
        .strategy(BedrockCacheStrategy.SYSTEM_ONLY)
        .build())
		.build()

模型特定的令牌阈值

模型 每个检查点的最小令牌数
Claude 3.7 Sonnet, 3.5 Sonnet v2, Opus 4, Sonnet 4, Sonnet 4.5 1,024
Claude 3.5 Haiku 2,048
Claude Haiku 4.5 4,096
Amazon Nova (所有变体) 1,000

有关详细信息,请参阅Bedrock 令牌限制文档

缓存指标命名

指标 Anthropic Direct AWS Bedrock
创建缓存条目 cacheCreationInputTokens cacheWriteInputTokens
从缓存读取 cacheReadInputTokens cacheReadInputTokens

跨提供商的相同 Spring AI 模式

Spring AI 在两个提供商之间使用相同的缓存策略

BedrockCacheStrategy.SYSTEM_ONLY           ←→ AnthropicCacheStrategy.SYSTEM_ONLY
BedrockCacheStrategy.TOOLS_ONLY            ←→ AnthropicCacheStrategy.TOOLS_ONLY
BedrockCacheStrategy.SYSTEM_AND_TOOLS      ←→ AnthropicCacheStrategy.SYSTEM_AND_TOOLS
BedrockCacheStrategy.CONVERSATION_HISTORY  ←→ AnthropicCacheStrategy.CONVERSATION_HISTORY

让我们看看代码是多么相似

// Anthropic direct API
ChatResponse response = anthropicChatModel.call(
				new Prompt(
						List.of(new SystemMessage(systemPrompt), new UserMessage(userQuery)),
						AnthropicChatOptions.builder()
								.model(AnthropicApi.ChatModel.CLAUDE_4_5_SONNET)
								.cacheOptions(AnthropicCacheOptions.builder()
										.strategy(AnthropicCacheStrategy.SYSTEM_ONLY)
										.build())
								.maxTokens(500)
								.build()
				)
		);

// AWS Bedrock (nearly identical)
ChatResponse response = bedrockChatModel.call(
		new Prompt(
				List.of(new SystemMessage(systemPrompt), new UserMessage(userQuery)),
				BedrockChatOptions.builder()
						.model("anthropic.claude-sonnet-4-5-20250929-v1:0")
						.cacheOptions(BedrockCacheOptions.builder()
								.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
								.build())
						.maxTokens(500)
						.build()
		)
);

唯一的区别:聊天模型实例、选项类和模型标识符格式。

提供商特性一览

特性 AWS Bedrock Anthropic Direct
缓存 TTL 5 分钟(固定) 5 分钟(默认),1 小时(可选)
模型 Claude + Nova 仅 Claude
工具缓存 仅 Claude 所有 Claude 模型
令牌指标 cacheWriteInputTokens, cacheReadInputTokens cacheCreationInputTokens, cacheReadInputTokens
定价 因区域/模型而异 按模型发布
成本模式 ~25% 写入溢价,~90% 读取节省 25% 写入溢价,90% 读取节省

示例:带缓存的文档分析

这是一个展示缓存有效性的实际示例

@Service
public class ContractAnalyzer {

	private final BedrockProxyChatModel chatModel;
	private final DocumentExtractor documentExtractor;

	public AnalysisReport analyzeContract(String contractId) {
		String contractText = documentExtractor.extract(contractId);

		String systemPrompt = """
				You are an expert legal analyst specializing in commercial contracts.
				Analyze the following contract and provide precise insights about
				terms, obligations, risks, and opportunities:
				
				CONTRACT:
				%s
				""".formatted(contractText);

		String[] questions = {
				"What are the key legal clauses and penalties?",
				"Summarize the payment terms and financial obligations.",
				"What intellectual property rights are defined?",
				"Identify potential compliance risks.",
				"What are the performance milestones?"
		};

		AnalysisReport report = new AnalysisReport();

		BedrockChatOptions options = BedrockChatOptions.builder()
				.model("anthropic.claude-sonnet-4-5-20250929-v1:0")
				.cacheOptions(BedrockCacheOptions.builder()
						.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
						.build())
				.maxTokens(1000)
				.build();

		for (int i = 0; i < questions.length; i++) {
			ChatResponse response = chatModel.call(
					new Prompt(
							List.of(new SystemMessage(systemPrompt), new UserMessage(questions[i])),
							options
					)
			);

			report.addSection(questions[i], response.getResult().getOutput().getText());
			logCacheMetrics(response, i);
		}

		return report;
	}

	private void logCacheMetrics(ChatResponse response, int questionNum) {
		Integer cacheWrite = (Integer) response.getMetadata()
				.getMetadata().get("cacheWriteInputTokens");
		Integer cacheRead = (Integer) response.getMetadata()
				.getMetadata().get("cacheReadInputTokens");

		if (questionNum == 0 && cacheWrite != null) {
			logger.info("Cache created: {} tokens", cacheWrite);
		} else if (cacheRead != null && cacheRead > 0) {
			logger.info("Cache hit: {} tokens", cacheRead);
		}
	}
}

AWS Bedrock 通过响应元数据提供缓存指标

第一个请求:cacheWriteInputTokens > 0, cacheReadInputTokens = 0

后续请求(在 TTL 内):cacheWriteInputTokens = 0, cacheReadInputTokens > 0

使用 3,500 令牌的系统提示,这使得缓存内容的成本降低约 65%(第一个问题支付约 1.25 倍,后续问题支付约 0.10 倍)。

在 Bedrock 上使用不同的模型

@Service
public class MultiModelService {

	// Nova: System prompt caching
	public String analyzeWithNova(String document, String query) {
		return chatClient.prompt()
                .system("You are an expert analyst. Context: " + document)
				.user(query)
				.options(BedrockChatOptions.builder()
						.model("us.amazon.nova-pro-v1:0")
						.cacheOptions(BedrockCacheOptions.builder()
								.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
								.build())
						.maxTokens(500)
						.build())
				.call()
				.content();
	}

	// Claude: System + tool caching
	public String analyzeWithTools(String document, String query,
			List<ToolCallback> tools) {
		return chatClient.prompt()
				.system("You are an expert analyst. Context: " + document)
				.user(query)
				.options(BedrockChatOptions.builder()
						.model("anthropic.claude-sonnet-4-5-20250929-v1:0")
						.cacheOptions(BedrockCacheOptions.builder()
								.strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS)
								.build())
						.toolCallbacks(tools)
						.maxTokens(500)
						.build())
				.call()
				.content();
	}
}

入门

添加 Spring AI Bedrock Converse starter

注意:AWS Bedrock 提示缓存支持在 Spring AI 1.1.0 及更高版本中可用。请使用最新的 1.1.0-SNAPSHOT 版本尝试。

<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-starter-model-bedrock-converse</artifactId>
</dependency>

配置 AWS 凭据

spring.ai.bedrock.aws.region=us-east-1
spring.ai.bedrock.aws.access-key=${AWS_ACCESS_KEY_ID}
spring.ai.bedrock.aws.secret-key=${AWS_SECRET_ACCESS_KEY}

然后您可以像上面示例中所示的那样,通过 AWS Bedrock 开始使用提示缓存。

策略选择参考

策略 使用场景 Claude Nova
SYSTEM_ONLY 大型稳定系统提示
TOOLS_ONLY 大型稳定工具,动态系统
SYSTEM_AND_TOOLS 两者都大且稳定
CONVERSATION_HISTORY 多轮对话
NONE 显式禁用缓存

有关详细的策略解释、缓存层次结构和级联失效模式,请参阅我们的Anthropic 提示缓存博文。这些概念在 AWS Bedrock 的情况下仍然适用。

结论

AWS Bedrock 将提示缓存扩展到 Amazon Nova 模型,同时保持对 Claude 模型的完全支持。与 Anthropic 直接 API 的主要区别是固定的 5 分钟 TTL,Nova 缺乏工具缓存支持,以及区域特定的定价。

Spring AI 在两个提供商之间提供相同的策略性缓存模式。无论您选择通过 Anthropic 的 Claude、通过 Bedrock 的 Claude 还是 Amazon Nova 模型,这五种缓存策略都能以最少的代码更改保持一致的工作。

提供商之间的选择取决于模型可用性(Nova 仅在 Bedrock 上)、缓存 TTL 要求和工具缓存需求(Nova 不支持)。

有关 Spring AI 对 AWS Bedrock 提示缓存支持的更多信息,请参阅Spring AI Bedrock 文档AWS Bedrock 提示缓存文档

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有