|
此版本仍在开发中,尚未被视为稳定版。如需最新的快照版本,请使用 Spring AI 1.1.3! |
Bedrock Converse API
Amazon Bedrock Converse API 提供了一个统一的接口,用于对话式AI模型,并包含增强功能,如函数/工具调用、多模态输入和流式响应。
The Bedrock Converse API 有以下高级特性:
-
工具/函数调用:支持在对话中定义和使用函数
-
多模态输入:能够在对话中处理文本和图像两种类型的输入
-
流式支持:实时流式传输模型响应
-
系统消息:支持系统级指令和上下文设置
The Bedrock Converse API 提供了一个跨多个模型提供商的统一接口,同时处理 AWS 特定的身份验证和基础设施问题。
目前,Converse API 支持的模型 包括:
Amazon Titan, Amazon Nova, AI21 Labs, Anthropic Claude, Cohere Command, Meta Llama, Mistral AI。 |
|
根据 Bedrock 推荐,Spring AI 正在转向使用 Amazon Bedrock 的 Converse API 来实现所有 Spring AI 的聊天对话功能。 虽然现有的 InvokeModel API 支持对话应用,但我们强烈建议采用 Converse API 用于所有的聊天对话模型。 The Converse API 不支持嵌入操作,因此这些功能将保持在当前 API 中,并且现有 |
前置条件
-
获得 AWS 凭证:如果您还没有 AWS 账户并且尚未配置 AWS CLI,请观看此视频指南帮助您进行配置:4 分钟内完成 AWS CLI & SDK 配置!。您应该能够获取您的访问和安全密钥。
-
启用模型:前往Amazon Bedrock,从左侧的模型访问菜单中配置对您将要使用的模型的访问权限。
Auto-configuration
|
Spring AI自动配置和starter模块的artifact名称有了重大变化。 请参阅升级说明获取更多信息。 |
将以下依赖添加到项目中的Mavenpom.xml或Gradlebuild.gradle构建文件中:
- Maven构建文件:
spring-ai-starter-model-bedrock-converse - Gradle构建文件:
spring-ai-starter-model-bedrock-converse
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-bedrock-converse</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-bedrock-converse'
}
| 请参阅依赖管理部分,将Spring AI BOM添加到您的构建文件中。 |
聊天属性
spring.ai.bedrock.aws 前缀是配置连接到 AWS Bedrock 的属性前缀。
| <property> </property> | <description> </description> | 默认 |
|---|---|---|
spring.ai.bedrock.aws.region |
使用的是 AWS 区域 |
us-east-1 |
spring.ai.bedrock.aws.timeout |
AWS 全部 API 调用的最大持续时间 |
5m |
spring.ai.bedrock.aws.connectionTimeout |
建立连接时的最大等待时间 |
5s |
spring.ai.bedrock.aws.connectionAcquisitionTimeout |
等待池中新连接的最大超时时间 |
30s |
spring.ai.bedrock.aws.asyncReadTimeout |
异步响应阅读的最大时长 |
30s |
spring.ai.bedrock.aws.access-key |
AWS访问密钥 |
- |
spring.ai.bedrock.aws.secret-key |
AWS密钥 |
- |
spring.ai.bedrock.aws.session-token |
AWS 会话Tokens(用于临时凭证) |
- |
spring.ai.bedrock.aws.profile.name |
AWS 账 profiel 名称。 |
- |
spring.ai.bedrock.aws.profile.credentials-path |
AWS凭证文件路径。 |
- |
spring.ai.bedrock.aws.profile.configuration-path |
AWS配置文件路径。 |
- |
|
现在通过带有前缀 要启用,请设置:spring.ai.model.chat=bedrock-converse(默认已启用) 要禁用,请设置 spring.ai.model.chat=none (或任何不匹配 bedrock-converse 的值) 此更改是为了允许配置多个模型。 |
spring.ai.bedrock.converse.chat 前缀是用于配置 Converse API 会话模型实现的属性前缀。
| <property> </property> | <description> </description> | 默认 |
|---|---|---|
spring.ai.bedrock.converse.chat.enabled (已移除且不再有效) |
启用Bedrock Converse 会话模型。 |
true |
spring.ai.model.chat |
启用Bedrock Converse 会话模型。 |
bedrock-converse |
spring.ai.bedrock.converse.chat.options.model |
使用要使用的模型ID。您可以查阅支持的模型和模型功能。 |
请选择您的modelId,从AWS Bedrock控制台。 |
spring.ai.bedrock.converse.chat.options.temperature |
控制输出的随机性。值可以在 [0.0,1.0] 范围内。 |
0.8 |
spring.ai.bedrock.converse.chat.options.top-p |
考虑采样时要考虑的Tokens累计概率的最大值。 |
AWS Bedrock默认设置 |
spring.ai.bedrock.converse.chat.options.top-k |
生成下一个-token-时的选择Tokens数量。 |
AWS Bedrock默认设置 |
spring.ai.bedrock.converse.chat.options.max-tokens |
生成响应中的最大Tokens数。 |
500 |
运行时选项
使用便携式ChatOptions或BedrockChatOptions构建器来创建模型配置,例如温度、最大词汇数、顶级P值等。
启动时,可以使用BedrockConverseProxyChatModel(api, options)构造函数或spring.ai.bedrock.converse.chat.options.*属性来配置默认选项。
运行时,您可以通过向Prompt调用添加新的、针对请求的选项来覆盖默认选项:
var options = BedrockChatOptions.builder()
.model("anthropic.claude-haiku-4-5-20251001-v1:0")
.temperature(0.6)
.maxTokens(300)
.toolCallbacks(List.of(FunctionToolCallback.builder("getCurrentWeather", new WeatherService())
.description("Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.")
.inputType(WeatherService.Request.class)
.build()))
.build();
String response = ChatClient.create(this.chatModel)
.prompt("What is current weather in Amsterdam?")
.options(options)
.call()
.content();
提示缓存
AWS Bedrock 的 提示缓存功能 允许您缓存经常使用的提示,以减少成本并提高重复交互的响应时间。 当您缓存一个提示时,后续相同的请求可以重用缓存的内容,显著减少了需要处理的输入标记的数量。
|
支持的模型 提示缓存支持Claude 3.x、Claude 4.x以及通过AWS Bedrock提供的Amazon Nova模型。 标签要求 不同的模型对于缓存有效性的最小标记阈值不同: - Claude Sonnet 4 和大多数模型:1024+ 标记 - 模型特定的要求可能有所不同 - 请参阅 AWS Bedrock 文档 |
缓存策略
Spring AI通过BedrockCacheStrategy枚举提供战略性的缓存放置:
-
NONE: 完全禁用提示缓存(默认设置) -
SYSTEM_ONLY: 只缓存系统消息内容 -
TOOLS_ONLY: 仅缓存工具定义(仅Claude模型) -
SYSTEM_AND_TOOLS: 缓存系统消息和工具定义(仅 Claude 模型) -
CONVERSATION_HISTORY: 在聊天记忆场景中缓存整个对话历史记录
此战略方法确保在遵守AWS Bedrock的4个断点限制的同时,实现最优的缓存断点放置。
|
Amazon Nova 限制 Amazon Nova 模型(Nova Micro、Lite、Pro、Premier)仅支持缓存内容为 如果您尝试使用 |
启用提示缓存
通过将cacheOptions设置在BedrockChatOptions上并选择一个strategy来启用提示缓存。
系统专用缓存
最常见的用例——在多次请求中缓存系统指令:
// Cache system message content
ChatResponse response = chatModel.call(
new Prompt(
List.of(
new SystemMessage("You are a helpful AI assistant with extensive knowledge..."),
new UserMessage("What is machine learning?")
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(500)
.build()
)
);
仅工具缓存
缓存大型工具定义同时保持系统提示动态(仅针对 Claude 模型):<br />
// Cache tool definitions only
ChatResponse response = chatModel.call(
new Prompt(
"What's the weather in San Francisco?",
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.TOOLS_ONLY)
.build())
.toolCallbacks(weatherToolCallbacks) // Large tool definitions
.maxTokens(500)
.build()
)
);
此策略仅支持Claude模型。
Amazon Nova模型将返回ValidationException。 |
系统和工具缓存
缓存系统指令和工具定义以实现最大程度的重复使用(仅限 Claude 模型):
// Cache system message and tool definitions
ChatResponse response = chatModel.call(
new Prompt(
List.of(
new SystemMessage("You are a weather analysis assistant..."),
new UserMessage("What's the weather like in Tokyo?")
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS)
.build())
.toolCallbacks(weatherToolCallbacks)
.maxTokens(500)
.build()
)
);
| 此策略使用2个缓存断点(一个用于工具,一个用于系统)。 仅在Claude模型上支持。 |
对话历史记录缓存
缓存多轮对话的历史记录以供聊天机器人和助手使用:
// Cache conversation history with ChatClient and memory
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultSystem("You are a personalized career counselor...")
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory)
.conversationId(conversationId)
.build())
.build();
String response = chatClient.prompt()
.user("What career advice would you give me?")
.options(BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.CONVERSATION_HISTORY)
.build())
.maxTokens(500)
.build())
.call()
.content();
使用 ChatClient 节流 API
String response = ChatClient.create(chatModel)
.prompt()
.system("You are an expert document analyst...")
.user("Analyze this large document: " + document)
.options(BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.build())
.call()
.content();
使用示例
这里是一个完整的示例,演示了带有成本跟踪的提示缓存:
// Create system content that will be reused multiple times
String largeSystemPrompt = "You are an expert software architect specializing in distributed systems...";
// (Ensure this is 1024+ tokens for cache effectiveness)
// First request - creates cache
ChatResponse firstResponse = chatModel.call(
new Prompt(
List.of(
new SystemMessage(largeSystemPrompt),
new UserMessage("What is microservices architecture?")
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(500)
.build()
)
);
// Access cache-related token usage from metadata
Integer cacheWrite1 = (Integer) firstResponse.getMetadata()
.getMetadata()
.get("cacheWriteInputTokens");
Integer cacheRead1 = (Integer) firstResponse.getMetadata()
.getMetadata()
.get("cacheReadInputTokens");
System.out.println("Cache creation tokens: " + cacheWrite1);
System.out.println("Cache read tokens: " + cacheRead1);
// Second request with same system prompt - reads from cache
ChatResponse secondResponse = chatModel.call(
new Prompt(
List.of(
new SystemMessage(largeSystemPrompt), // Same prompt - cache hit
new UserMessage("What are the benefits of event sourcing?")
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(500)
.build()
)
);
Integer cacheWrite2 = (Integer) secondResponse.getMetadata()
.getMetadata()
.get("cacheWriteInputTokens");
Integer cacheRead2 = (Integer) secondResponse.getMetadata()
.getMetadata()
.get("cacheReadInputTokens");
System.out.println("Cache creation tokens: " + cacheWrite2); // Should be 0
System.out.println("Cache read tokens: " + cacheRead2); // Should be > 0
Token 使用跟踪
AWS Bedrock 提供了通过响应获取的缓存特定指标。 缓存指标可以通过两种方法访问:
本地使用对象(推荐用于可观测性)
通过原生的TokenUsage对象访问缓存指标以实现可观测性和度量收集:
import software.amazon.awssdk.services.bedrockruntime.model.TokenUsage;
ChatResponse response = chatModel.call(/* ... */);
// Access cache metrics from native TokenUsage object
TokenUsage tokenUsage = (TokenUsage) response.getMetadata()
.getUsage()
.getNativeUsage();
if (tokenUsage != null) {
Integer cacheWrite = tokenUsage.cacheWriteInputTokens();
Integer cacheRead = tokenUsage.cacheReadInputTokens();
System.out.println("Cache write: " + cacheWrite + ", Cache read: " + cacheRead);
}
元数据映射(兼容向前)
缓存指标还通过元数据Map提供以保持向后兼容性:
ChatResponse response = chatModel.call(/* ... */);
// Access cache metrics from metadata Map
Integer cacheWrite = (Integer) response.getMetadata()
.getMetadata()
.get("cacheWriteInputTokens");
Integer cacheRead = (Integer) response.getMetadata()
.getMetadata()
.get("cacheReadInputTokens");
特定于缓存的指标包括:
-
cacheWriteInputTokens: 返回创建缓存条目时使用的标记数 -
cacheReadInputTokens: 从现有缓存条目中读取的Tokens数量
当您首次发送缓存提示时:
- cacheWriteInputTokens 将大于 0
- cacheReadInputTokens 将为 0
当您在同一缓存期内再次发送相同的提示(5分钟TTL)时:
- `cacheWriteInputTokens` 将为 `0`
- `cacheReadInputTokens` 将大于 `0`
实际应用场景
法律文件分析
通过在多个问题中缓存文档内容来高效分析大型法律合同或合规文件:
// Load a legal contract (PDF or text)
String legalContract = loadDocument("merger-agreement.pdf"); // ~3000 tokens
// System prompt with legal expertise
String legalSystemPrompt = "You are an expert legal analyst specializing in corporate law. " +
"Analyze the following contract and provide precise answers about terms, obligations, and risks: " +
legalContract;
// First analysis - creates cache
ChatResponse riskAnalysis = chatModel.call(
new Prompt(
List.of(
new SystemMessage(legalSystemPrompt),
new UserMessage("What are the key termination clauses and associated penalties?")
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(1000)
.build()
)
);
// Subsequent questions reuse cached document - 90% cost savings
ChatResponse obligationAnalysis = chatModel.call(
new Prompt(
List.of(
new SystemMessage(legalSystemPrompt), // Same content - cache hit
new UserMessage("List all financial obligations and payment schedules.")
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(1000)
.build()
)
);
批量代码审查
使用一致的评审标准处理多个代码文件,并缓存评审准则:
// Define comprehensive code review guidelines
String reviewGuidelines = """
You are a senior software engineer conducting code reviews. Apply these criteria:
- Security vulnerabilities and best practices
- Performance optimizations and memory usage
- Code maintainability and readability
- Testing coverage and edge cases
- Design patterns and architecture compliance
""";
List<String> codeFiles = Arrays.asList(
"UserService.java", "PaymentController.java", "SecurityConfig.java"
);
List<String> reviews = new ArrayList<>();
for (String filename : codeFiles) {
String sourceCode = loadSourceFile(filename);
ChatResponse review = chatModel.call(
new Prompt(
List.of(
new SystemMessage(reviewGuidelines), // Cached across all reviews
new UserMessage("Review this " + filename + " code:\n\n" + sourceCode)
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(800)
.build()
)
);
reviews.add(review.getResult().getOutput().getText());
}
// Guidelines cached after first request, subsequent reviews are faster and cheaper
知识库支持客户支持
创建一个客服系统,缓存您的产品知识库以提供一致且准确的响应:
// Load comprehensive product knowledge
String knowledgeBase = """
PRODUCT DOCUMENTATION:
- API endpoints and authentication methods
- Common troubleshooting procedures
- Billing and subscription details
- Integration guides and examples
- Known issues and workarounds
""" + loadProductDocs(); // ~2500 tokens
@Service
public class CustomerSupportService {
public String handleCustomerQuery(String customerQuery, String customerId) {
ChatResponse response = chatModel.call(
new Prompt(
List.of(
new SystemMessage("You are a helpful customer support agent. " +
"Use this knowledge base to provide accurate solutions: " + knowledgeBase),
new UserMessage("Customer " + customerId + " asks: " + customerQuery)
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(600)
.build()
)
);
return response.getResult().getOutput().getText();
}
}
// Knowledge base is cached across all customer queries
// Multiple support agents can benefit from the same cached content
多租户SaaS应用
缓存不同租户的共享工具定义,并为每个租户自定义系统提示词:<br>
// Shared tool definitions (cached once, used across all tenants)
List<FunctionToolCallback> sharedTools = createLargeToolRegistry(); // ~2000 tokens
// Tenant-specific configuration
@Service
public class MultiTenantAIService {
public String processRequest(String tenantId, String userQuery) {
// Load tenant-specific system prompt (changes per tenant)
String tenantPrompt = loadTenantSystemPrompt(tenantId);
ChatResponse response = chatModel.call(
new Prompt(
List.of(
new SystemMessage(tenantPrompt), // Tenant-specific, not cached
new UserMessage(userQuery)
),
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.TOOLS_ONLY)
.build())
.toolCallbacks(sharedTools) // Shared tools - cached
.maxTokens(500)
.build()
)
);
return response.getResult().getOutput().getText();
}
}
// Tools cached once, each tenant gets customized system prompt
最佳实践
-
选择合适的策略:
-
使用
SYSTEM_ONLY作为可重复使用的系统提示和指令(适用于所有模型) -
使用
TOOLS_ONLY当您有大型稳定的工具但动态系统提示时(仅对 Claude) -
使用
SYSTEM_AND_TOOLS当系统和工具都大型且稳定(仅Claude) -
使用
CONVERSATION_HISTORY与ChatClient内存进行多轮对话 -
使用
NONE显式禁用缓存
-
-
满足Token要求:专注于缓存符合最低Token要求的内容(大多数模型为1024+ Token)。
-
重复使用相同内容:缓存最适合于精确匹配提示内容。 即使有小的更改也需要一个新的缓存条目。
-
监控Tokens使用情况:通过元数据指标跟踪缓存有效性:
Integer cacheWrite = (Integer) response.getMetadata().getMetadata().get("cacheWriteInputTokens"); Integer cacheRead = (Integer) response.getMetadata().getMetadata().get("cacheReadInputTokens"); if (cacheRead != null && cacheRead > 0) { System.out.println("Cache hit: " + cacheRead + " tokens saved"); } -
战略缓存放置:实现会根据您选择的策略自动在最优位置放置缓存断点,确保符合AWS Bedrock的4个断点限制。
-
缓存生命周期:AWS Bedrock 缓存具有固定的 5 分钟 TTL(时间到期时间)。每次缓存访问都会重置计时器。
-
模型兼容性: 了解特定模型的限制:
-
Claude 模型: 支持所有缓存策略
-
Amazon Nova模型:仅支持
SYSTEM_ONLY和CONVERSATION_HISTORY(工具缓存不支持)
-
-
工具稳定性: 当使用
TOOLS_ONLY、SYSTEM_AND_TOOLS或CONVERSATION_HISTORY策略时,请确保工具保持稳定。 更改工具定义将由于级联无效化而使所有下游缓存断点失效。
缓存失效和级联行为
AWS Bedrock 沿用了带有级联无效化的分层缓存模型:
缓存层次结构: Tools → System → Messages
每一级的变化都会使该级别及其之后的所有级别失效:
| 什么是变化 | 工具缓存 | 系统缓存 | 消息缓存 |
|---|---|---|---|
工具 |
❌ 无效 |
❌ 无效 |
❌ 无效 |
系统 |
✅ 有效 |
❌ 无效 |
❌ 无效 |
消息 |
✅ 有效 |
✅ 有效 |
❌ 无效 |
强度为SYSTEM_AND_TOOLS的策略示例:
// Request 1: Cache both tools and system
ChatResponse r1 = chatModel.call(
new Prompt(
List.of(new SystemMessage("System prompt"), new UserMessage("Question")),
BedrockChatOptions.builder()
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS)
.build())
.toolCallbacks(tools)
.build()
)
);
// Result: Both caches created
// Request 2: Change only system prompt (tools same)
ChatResponse r2 = chatModel.call(
new Prompt(
List.of(new SystemMessage("DIFFERENT system prompt"), new UserMessage("Question")),
BedrockChatOptions.builder()
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS)
.build())
.toolCallbacks(tools) // SAME tools
.build()
)
);
// Result: Tools cache HIT (reused), system cache MISS (recreated)
// Request 3: Change tools (system same as Request 2)
ChatResponse r3 = chatModel.call(
new Prompt(
List.of(new SystemMessage("DIFFERENT system prompt"), new UserMessage("Question")),
BedrockChatOptions.builder()
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_AND_TOOLS)
.build())
.toolCallbacks(newTools) // DIFFERENT tools
.build()
)
);
// Result: BOTH caches MISS (tools change invalidates everything downstream)
实施细节
Spring AI 框架中提示缓存的实现遵循以下关键设计原则:
-
战略缓存放置:根据选择的策略自动在最优位置放置缓存断点,确保符合AWS Bedrock的4个缓存断点限制。
-
Provider Portability: 缓存配置是通过
BedrockChatOptions完成的,而不是个别消息,从而在切换不同的AI提供商时保持兼容性。 -
线程安全: 缓存断点跟踪通过使用线程安全机制来正确处理并发请求。
-
联合类型模式:AWS SDK 使用联合类型,在此情况下,缓存点被作为单独的块添加而不是属性。 这与直接的API方法不同,但确保了类型安全和API合规性。
-
增量缓存:
CONVERSATION_HISTORY策略在最后一个用户消息处放置缓存断点,启用增量缓存,在这种情况下,每次对话轮次都会基于之前的缓存前缀进行构建。
成本考虑
AWS Bedrock定价(提示缓存,仅供参考,不同模型有所不同):
-
缓存写入: 比基础输入Tokens大约贵25%
-
缓存读取:大约便宜90%(只需基础输入Tokens价格的10%)
-
盈亏平衡点:仅通过一次缓存读取,您就已经节省了开支
例示费用计算:
// System prompt: 2000 tokens
// User question: 50 tokens
// Without caching (5 requests):
// Cost: 5 × (2000 + 50) = 10,250 tokens at base rate
// With caching (5 requests):
// Request 1: 2000 tokens × 1.25 (cache write) + 50 = 2,550 tokens
// Requests 2-5: 4 × (2000 × 0.10 (cache read) + 50) = 4 × 250 = 1,000 tokens
// Total: 2,550 + 1,000 = 3,550 tokens equivalent
// Savings: (10,250 - 3,550) / 10,250 = 65% cost reduction
工具调用
The Bedrock Converse API 支持工具调用能力,允许模型在对话中使用工具。 以下是定义和使用基于 @Tool 的工具的示例:
public class WeatherService {
@Tool(description = "Get the weather in location")
public String weatherByLocation(@ToolParam(description= "City or state name") String location) {
...
}
}
String response = ChatClient.create(this.chatModel)
.prompt("What's the weather like in Boston?")
.tools(new WeatherService())
.call()
.content();
您可以将 Java.util.function 工具作为 Beans 使用:
@Bean
@Description("Get the weather in location. Return temperature in 36°F or 36°C format.")
public Function<Request, Response> weatherFunction() {
return new MockWeatherService();
}
String response = ChatClient.create(this.chatModel)
.prompt("What's the weather like in Boston?")
.toolNames("weatherFunction")
.inputType(Request.class)
.call()
.content();
在工具文档中查找更多内容。
结构化输出
AWS Bedrock 通过 JSON Schema 支持原生结构化输出,确保模型生成的响应严格符合您指定的结构。 此功能适用于支持的模型,包括 Anthropic Claude 和 Amazon Nova。
使用 ChatClient 与原生结构化输出
使用结构化输出最简单的方式是通过高级API ChatClient 和顾问 ENABLE_NATIVE_STRUCTURED_OUTPUT:
record ActorsFilms(String actor, List<String> movies) {}
ActorsFilms actorsFilms = ChatClient.create(chatModel).prompt()
.options(ToolCallingChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.build())
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
.user("Generate the filmography for a random actor.")
.call()
.entity(ActorsFilms.class);
这种方法会自动:
-
从您的 Java 类生成 JSON 架构
-
通过 AWS Bedrock
OutputConfigAPI 在BedrockChatOptions上设置outputSchema -
将 JSON 响应解析为您指定的类型
直接使用 outputSchema
为了获得更精细的控制,您可以直接在 BedrockChatOptions 上设置 JSON 架构:
String jsonSchema = """
{
"type": "object",
"properties": {
"actor": { "type": "string" },
"movies": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["actor", "movies"],
"additionalProperties": false
}
""";
ChatResponse response = chatModel.call(
new Prompt("Generate the filmography for a random actor.",
BedrockChatOptions.builder()
.model("us.anthropic.claude-haiku-4-5-20251001-v1:0")
.outputSchema(jsonSchema)
.build()));
String content = response.getResult().getOutput().getText();
AWS Bedrock 结构化输出在构建 OutputConfig 时,内部使用固定的架构名称 response_schema。
架构 JSON 会直接传递给 AWS SDK 的 JsonSchemaDefinition。 |
更多信息,请参阅 结构化输出转换器 文档。
多模态
多模态指的是模型同时理解和处理来自各种来源的信息的能力,包括文本、图像、视频、PDF、DOC、HTML、MD以及其他数据格式。
The Bedrock Converse API 支持多模态输入,包括文本和图像输入,并可以根据结合输入生成文本响应。
您需要一个支持多模态输入的模型,例如Anthropic Claude或Amazon Nova模型。
图片
对于支持视觉多模态的模型,例如Amazon Nova、Anthropic Claude、Llama 3.2以及Bedrock Converse API Amazon允许您在负载中包含多个图像。这些模型可以分析传递过来的图像,并回答问题、对图像进行分类,以及根据提供的说明总结图像。
当前,Bedrock Converse 支持的 base64 编码图片的 MIME 类型包括 image/jpeg、image/png、image/gif 和 image/webp。
Spring AI的Message接口通过引入Media类型支持多模态AI模型。
它包含了消息中媒体附件的数据和信息,使用了Spring的org.springframework.util.MimeType和一个java.lang.Object来处理原始媒体数据。
以下是一个简单的代码示例,演示了用户文本与图片的结合。
String response = ChatClient.create(chatModel)
.prompt()
.user(u -> u.text("Explain what do you see on this picture?")
.media(Media.Format.IMAGE_PNG, new ClassPathResource("/test.png")))
.call()
.content();
logger.info(response);
它将输入test.png图像:
<p>along with the text message "Explain what do you see on this picture?", 和生成类似下面的响应:</p>
The image shows a close-up view of a wire fruit basket containing several pieces of fruit. ...
视频
The Amazon Nova模型 允许您在负载中包含单个视频,该视频可以以base64格式提供或通过Amazon S3 URI提供。
当前,Bedrock Nova 支持的视频类型包括 video/x-matroska、video/quicktime、video/mp4、video/webm、video/x-flv、video/mpeg、video/x-ms-wmv 和 video/3gpp。
Spring AI的Message接口通过引入Media类型支持多模态AI模型。
它包含了消息中媒体附件的数据和信息,使用了Spring的org.springframework.util.MimeType和一个java.lang.Object来处理原始媒体数据。
以下是简单的代码示例,演示了用户文本与视频的结合。
String response = ChatClient.create(chatModel)
.prompt()
.user(u -> u.text("Explain what do you see in this video?")
.media(Media.Format.VIDEO_MP4, new ClassPathResource("/test.video.mp4")))
.call()
.content();
logger.info(response);
它将输入test.video.mp4图像:
<p>与文本消息“请解释你在视频中看到了什么?”一同出现,并生成类似于以下内容的响应:</p>
The video shows a group of baby chickens, also known as chicks, huddled together on a surface ...
_documents_
对于某些模型,Bedrock 允许您通过 Converse API 文档支持在负载中包含文档,这些文档可以以字节形式提供。 文档支持有两种不同的变体,如下所述:
-
文本文档类型(txt、csv、html、md等),强调对文本的理解。这些用例包括基于文档中的文本元素进行回答。
-
媒体文档类型(pdf、docx、xlsx),其中重点是基于视觉的理解来回答问题。这些用例包括根据图表、图形等回答问题。
当前,Anthropic 的 PDF 支持(Beta 版本) 和 Amazon Bedrock Nova 模型支持文档的多媒体特性。
以下是一个简单的代码示例,演示了用户文本与媒体文档的结合。
String response = ChatClient.create(chatModel)
.prompt()
.user(u -> u.text(
"You are a very professional document summarization specialist. Please summarize the given document.")
.media(Media.Format.DOC_PDF, new ClassPathResource("/spring-ai-reference-overview.pdf")))
.call()
.content();
logger.info(response);
它接受一个输入参数 spring-ai-reference-overview.pdf 的文档:
<p>您是一位非常专业的文档摘要专家,请总结给定的文档。</p>
**Introduction:** - Spring AI is designed to simplify the development of applications with artificial intelligence (AI) capabilities, aiming to avoid unnecessary complexity. ...
样本控制器
创建一个新的Spring Boot项目,并在依赖中添加spring-ai-starter-model-bedrock-converse。
在src/main/resources下添加一个application.properties文件:
spring.ai.bedrock.aws.region=eu-central-1
spring.ai.bedrock.aws.timeout=10m
spring.ai.bedrock.aws.access-key=${AWS_ACCESS_KEY_ID}
spring.ai.bedrock.aws.secret-key=${AWS_SECRET_ACCESS_KEY}
# session token is only required for temporary credentials
spring.ai.bedrock.aws.session-token=${AWS_SESSION_TOKEN}
spring.ai.bedrock.converse.chat.options.temperature=0.8
spring.ai.bedrock.converse.chat.options.top-k=15
这里是一个使用聊天模型的控制器示例:
@RestController
public class ChatController {
private final ChatClient chatClient;
@Autowired
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", this.chatClient.prompt(message).call().content());
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return this.chatClient.prompt(message).stream().content();
}
}