跳到主要内容

Bedrock Converse API

Deepseek 3.2 中英对照 Amazon Bedrock Converse Bedrock Converse API

Amazon Bedrock Converse API 为对话式 AI 模型提供了一个统一的接口,并增强了包括函数/工具调用、多模态输入和流式响应在内的能力。

Bedrock Converse API 具备以下高级特性:

  • 工具/函数调用:支持在对话中定义和使用函数

  • 多模态输入:能够在对话中处理文本和图像输入

  • 流式传输支持:模型响应的实时流式传输

  • 系统消息:支持系统级指令和上下文设置

提示

Bedrock Converse API 为多个模型提供商提供了统一的接口,同时处理 AWS 特定的身份验证和基础设施问题。目前,Converse API 支持的模型 包括:Amazon TitanAmazon NovaAI21 LabsAnthropic ClaudeCohere CommandMeta LlamaMistral AI

备注

根据Bedrock的建议,Spring AI正在向使用Amazon Bedrock的Converse API过渡,以用于Spring AI中所有聊天对话的实现。虽然现有的InvokeModel API支持对话应用,但我们强烈建议为所有Chat对话模型采用Converse API。

Converse API不支持嵌入操作,因此这些操作将保留在当前API中,并且现有InvokeModel API中的嵌入模型功能将得以保留。

前提条件

请参考 Amazon Bedrock 入门指南 来设置 API 访问权限。

  • 获取 AWS 凭证:如果你还没有 AWS 账户和配置好的 AWS CLI,这个视频指南可以帮助你进行配置:在 4 分钟内完成 AWS CLI 和 SDK 设置!。你应该能够获取到你的访问密钥和安全密钥。

  • 启用要使用的模型:前往 Amazon Bedrock,然后从左边的 模型访问 菜单中,配置对你将要使用的模型的访问权限。

自动配置

备注

Spring AI 的自动配置和 starter 模块的 artifact 名称发生了显著变化。更多信息请参阅升级说明

spring-ai-starter-model-bedrock-converse 依赖项添加至您项目的 Maven pom.xml 或 Gradle build.gradle 构建文件中:

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

:::提示
请参考依赖管理部分,将 Spring AI BOM 添加到您的构建文件中。
:::

聊天属性

前缀 spring.ai.bedrock.aws 是用于配置连接到 AWS Bedrock 的属性前缀。

属性描述默认值
spring.ai.bedrock.aws.region使用的 AWS 区域us-east-1
spring.ai.bedrock.aws.timeout整个 API 调用的 AWS 最大持续时间5m
spring.ai.bedrock.aws.connectionTimeout建立连接时等待的最长持续时间5s
spring.ai.bedrock.aws.connectionAcquisitionTimeout等待从连接池获取新连接的最长持续时间30s
spring.ai.bedrock.aws.asyncReadTimeout读取异步响应所花费的最长持续时间30s
spring.ai.bedrock.aws.access-keyAWS 访问密钥-
spring.ai.bedrock.aws.secret-keyAWS 秘密密钥-
spring.ai.bedrock.aws.session-token用于临时凭证的 AWS 会话令牌-

:::注意
聊天自动配置的启用与禁用现在通过以 spring.ai.model.chat 为前缀的顶层属性进行配置。

如需启用,请设置 spring.ai.model.chat=bedrock-converse(默认已启用)

如需禁用,请设置 spring.ai.model.chat=none(或任何与 bedrock-converse 不匹配的值)

此项变更是为了支持配置多个模型。
:::

前缀 spring.ai.bedrock.converse.chat 是用于配置 Converse API 聊天模型实现的属性前缀。

属性描述默认值
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。您可以参考 支持的模型和模型功能无。请从 AWS Bedrock 控制台中选择您的 modelId
spring.ai.bedrock.converse.chat.options.temperature控制输出的随机性。取值范围为 [0.0, 1.0]。0.8
spring.ai.bedrock.converse.chat.options.top-p采样时考虑的最大累积令牌概率。AWS Bedrock 默认值
spring.ai.bedrock.converse.chat.options.top-k用于生成下一个令牌的令牌选择数量。AWS Bedrock 默认值
spring.ai.bedrock.converse.chat.options.max-tokens生成响应中的最大令牌数。500

运行时选项

使用可移植的 ChatOptionsBedrockChatOptions 构建器来创建模型配置,例如温度、最大令牌数、topP 等。

在启动时,可以通过 BedrockConverseProxyChatModel(api, options) 构造函数或 spring.ai.bedrock.converse.chat.options.* 属性来配置默认选项。

在运行时,你可以通过向 Prompt 调用添加新的、特定于请求的选项来覆盖默认选项:

var options = BedrockChatOptions.builder()
.model("anthropic.claude-3-5-sonnet-20240620-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的提示词缓存功能允许您缓存常用的提示词,以降低成本并提升重复交互的响应速度。当您缓存一个提示词后,后续的相同请求可以重用缓存内容,从而显著减少需要处理的输入令牌数量。

备注

支持的模型

Prompt 缓存功能支持通过 AWS Bedrock 提供的 Claude 3.x、Claude 4.x 以及 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)仅支持对 systemmessages 内容进行缓存。它们支持对 tools 进行缓存。

如果您尝试在 Nova 模型上使用 TOOLS_ONLYSYSTEM_AND_TOOLS 策略,AWS 将返回 ValidationException。对于 Amazon Nova 模型,请使用 SYSTEM_ONLY 策略。

启用提示缓存

通过设置BedrockChatOptions上的cacheOptions并选择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-3-7-sonnet-20250219-v1:0")
.cacheOptions(BedrockCacheOptions.builder()
.strategy(BedrockCacheStrategy.SYSTEM_ONLY)
.build())
.maxTokens(500)
.build()
)
);

仅工具缓存

缓存大型工具定义,同时保持系统提示动态(仅限 Claude 模型):

// Cache tool definitions only
ChatResponse response = chatModel.call(
new Prompt(
"What's the weather in San Francisco?",
BedrockChatOptions.builder()
.model("us.anthropic.claude-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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 通过响应元数据提供缓存相关指标。缓存指标可通过元数据映射访问:

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: 返回从现有缓存条目读取的令牌数量

当你首次发送一个已缓存的提示时:- 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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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-3-7-sonnet-20250219-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 应用程序

在不同租户间共享工具定义的同时,为每个租户定制系统提示:

// 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-3-7-sonnet-20250219-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

最佳实践

  1. 选择合适的策略:

    • 使用 SYSTEM_ONLY 处理可复用的系统提示和指令(适用于所有模型)

    • 当您拥有大型稳定工具但系统提示动态变化时,使用 TOOLS_ONLY(仅限 Claude 模型)

    • 当系统和工具都庞大且稳定时,使用 SYSTEM_AND_TOOLS(仅限 Claude 模型)

    • 结合 ChatClient 内存使用 CONVERSATION_HISTORY 处理多轮对话

    • 使用 NONE 显式禁用缓存

  2. 满足令牌要求: 专注于缓存满足最低令牌要求的内容(大多数模型要求 1024+ 个令牌)。

  3. 复用相同内容: 缓存机制在提示内容完全匹配时效果最佳。即使微小改动也需要新的缓存条目。

  4. 监控令牌使用情况: 使用元数据指标跟踪缓存效果:

    Integer cacheWrite = (Integer) response.getMetadata().getMetadata().get("cacheWriteInputTokens");
    Integer cacheRead = (Integer) response.getMetadata().getMetadata().get("cacheReadInputTokens");
    if (cacheRead != null && cacheRead > 0) {
    System.out.println("缓存命中: 节省了 " + cacheRead + " 个令牌");
    }
  5. 策略性缓存放置: 实现会根据您选择的策略在最优位置自动放置缓存断点,确保符合 AWS Bedrock 的 4 个断点限制。

  6. 缓存生命周期: AWS Bedrock 缓存具有固定的 5 分钟 TTL(存活时间)。每次缓存访问都会重置计时器。

  7. 模型兼容性: 注意模型特定的限制:

    • Claude 模型: 支持所有缓存策略

    • Amazon Nova 模型: 仅支持 SYSTEM_ONLYCONVERSATION_HISTORY(不支持工具缓存)

  8. 工具稳定性: 使用 TOOLS_ONLYSYSTEM_AND_TOOLSCONVERSATION_HISTORY 策略时,请确保工具保持稳定。更改工具定义将由于级联失效而使所有下游缓存断点失效。

缓存失效与级联行为

AWS Bedrock 采用分层缓存模型,并具备级联失效机制:

缓存层级结构工具 → 系统 → 消息

每一级别的变动都会使该级别及之后的所有级别失效:

变更内容工具缓存系统缓存消息缓存
工具❌ 失效❌ 失效❌ 失效
系统✅ 有效❌ 失效❌ 失效
消息✅ 有效✅ 有效❌ 失效

使用 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中的提示词缓存实现遵循以下核心设计原则:

  1. 策略性缓存放置:缓存断点会根据所选策略自动放置于最佳位置,确保符合 AWS Bedrock 的 4 个断点限制。

  2. 供应商可移植性:缓存配置通过 BedrockChatOptions 完成,而非针对单个消息,从而在切换不同 AI 供应商时保持兼容性。

  3. 线程安全性:缓存断点跟踪采用线程安全机制实现,以正确处理并发请求。

  4. UNION 类型模式:AWS SDK 使用 UNION 类型,缓存点作为独立的块添加,而非属性。这与直接 API 方法不同,但确保了类型安全与 API 合规性。

  5. 增量缓存CONVERSATION_HISTORY 策略将缓存断点置于最后一条用户消息上,实现增量缓存,使得每次对话轮次都基于先前缓存的上下文前缀构建。

成本考量

AWS Bedrock 提示缓存的定价(近似值,因模型而异):

  • 缓存写入:比基础输入词元成本高出约 25%

  • 缓存读取:比基础输入词元成本低约 90%(仅为基础输入词元价格的 10%)

  • 盈亏平衡点:仅需 1 次缓存读取即可实现成本节省

成本计算示例

// 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

工具调用

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包中的函数式接口作为工具使用:

@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();

更多信息请参阅 工具 文档。

多模态

多模态指的是模型同时理解并处理来自不同来源信息的能力,这些来源包括文本、图像、视频、pdf、doc、html、md 等多种数据格式。

Bedrock Converse API 支持多模态输入,包括文本和图像输入,并能够基于组合输入生成文本响应。

你需要一个支持多模态输入的模型,例如Anthropic Claude或Amazon Nova模型。

图片

对于支持视觉多模态的模型,例如 Amazon Nova、Anthropic Claude、Llama 3.2,Bedrock Converse API 允许您在载荷中包含多张图像。这些模型能够分析传入的图像并回答问题、对图像进行分类,以及根据提供的指令总结图像内容。

目前,Bedrock Converse 支持 image/jpegimage/pngimage/gifimage/webp MIME 类型的 base64 编码图像。

Spring AI的Message接口通过引入Media类型来支持多模态AI模型。它包含消息中媒体附件的数据和信息,使用Spring的org.springframework.util.MimeTypejava.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 图像作为输入:

多模态测试图像

伴随着文字信息"解释一下你在这张图片上看到了什么?",生成类似这样的回应:

The image shows a close-up view of a wire fruit basket containing several pieces of fruit.
...

视频

Amazon Nova 模型允许你在有效负载中包含一个视频,该视频可以以 base64 格式或通过 Amazon S3 URI 提供。

目前,Bedrock Nova 支持 MIME 类型为 video/x-matroskavideo/quicktimevideo/mp4video/webmvideo/x-flvvideo/mpegvideo/x-ms-wmvvideo/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 图像作为输入:

多模态测试视频

同时附上文字信息“解释一下你在这个视频中看到了什么?”,并生成类似这样的回应:

The video shows a group of baby chickens, also known as chicks, huddled together on a surface
...

文档

对于某些模型,Bedrock 允许您通过 Converse API 文档支持在有效负载中包含文档,这些文档可以以字节形式提供。文档支持有两种不同的变体,具体说明如下:

  • 文本类文档类型(txt、csv、html、md 等),重点在于文本理解。这类用例包括基于文档的文本元素回答问题。

  • 媒体类文档类型(pdf、docx、xlsx),重点在于基于视觉的理解来回答问题。这类用例包括基于图表、图形等回答问题。

目前,Anthropic 的 PDF 支持(测试版) 和 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 文档作为输入:

多模态测试 PNG

随附的文本信息是:"您是一位非常专业的文档摘要专家。请对给定的文档进行总结。",并生成类似于这样的回复:

**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();
}
}