このバージョンはまだ開発中であり、まだ安定しているとは考えられていません。最新のスナップショットバージョンについては、Spring AI 1.1.2 を使用してください。

Bedrock Converse API

Amazon Bedrock コンバース API は、関数 / ツールの呼び出し、マルチモーダル入力、ストリーミングレスポンスなどの強化された機能を備えた会話型 AI モデル用の統合インターフェースを提供します。

Bedrock Converse API には、次のような高レベルの機能があります。

  • ツール / 関数の呼び出し: 会話中の機能定義とツールの使用をサポート

  • マルチモーダル入力: 会話中のテキストとイメージ入力の両方を処理する機能

  • ストリーミングサポート: モデルレスポンスのリアルタイムストリーミング

  • システムメッセージ: システムレベルの命令とコンテキスト設定のサポート

Bedrock Converse API は、AWS 固有の認証とインフラストラクチャに関する関心事に対応しながら、複数のモデルプロバイダー間で統一されたインターフェースを提供します。現在、Converse API 対応モデル [Amazon] には Amazon TitanAmazon NovaAI21 LabsAnthropic ClaudeCohere CommandMeta LlamaMistral AI が含まれています。

Bedrock の推奨事項に従い、Spring AI は、Spring AI のすべてのチャット会話実装に Amazon Bedrock の Converse API を使用するように移行しています。既存の InvokeModel API は会話アプリケーションをサポートしていますが、すべてのチャット会話モデルに Converse API を採用することを強くお勧めします。

Converse API は埋め込み操作をサポートしていないため、これらは現在の API に残り、既存の InvokeModel API の埋め込みモデル機能は維持されます。

前提条件

API アクセスの設定については Amazon Bedrock 入門 を参照してください

自動構成

Spring AI 自動構成、スターターモジュールのアーティファクト名に大きな変更がありました。詳細については、アップグレードノートを参照してください。

プロジェクトの Maven pom.xml または Gradle build.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 への接続を設定するためのプロパティプレフィックスです。

プロパティ 説明 デフォルト

spring.ai.bedrock.aws.region

使用する AWS リージョン

米国東部 -1

spring.ai.bedrock.aws.timeout

API 呼び出し全体の AWS 最大期間

5 分

spring.ai.bedrock.aws.connectionTimeout

接続を確立するまでの最大待機時間

5 秒

spring.ai.bedrock.aws.connectionAcquisitionTimeout

プールからの新しい接続を待つ最大時間

30 代

spring.ai.bedrock.aws.asyncReadTimeout

非同期レスポンスの読み取りに費やされた最大時間

30 代

spring.ai.bedrock.aws.access-key

AWS アクセスキー

-

spring.ai.bedrock.aws.secret-key

AWS 秘密鍵

-

spring.ai.bedrock.aws.session-token

一時認証情報用の AWS セッショントークン

-

spring.ai.bedrock.aws.profile.name

AWS プロファイル名。

-

spring.ai.bedrock.aws.profile.credentials-path

AWS 認証情報ファイルのパス。

-

spring.ai.bedrock.aws.profile.configuration-path

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。サポートされているモデルとモデル機能 [Amazon] を使用できます

なし。AWS Bedrock コンソールから modelId [Amazon] を選択します。

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

ランタイムオプション

ポータブル ChatOptions または BedrockChatOptions ポータブルビルダーを使用して、温度、maxToken、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’s prompt caching feature [Amazon] allows you to cache frequently used prompts to reduce costs and improve response times for repeated interactions. When you cache a prompt, subsequent identical requests can reuse the cached content, significantly reducing the number of input tokens processed.

対応モデル

プロンプトキャッシュは、AWS Bedrock を通じて利用可能な Claude 3.x、Claude 4.x、Amazon Nova モデルでサポートされています。

トークン要件

キャッシュの有効性に関する最小トークンしきい値はモデルによって異なります。- Claude Sonnet 4 およびほとんどのモデル: 1024+ トークン - モデル固有の要件は異なる場合があります - AWS Bedrock ドキュメントを参照してください

キャッシュ戦略

Spring AI は、BedrockCacheStrategy 列挙型を通じて戦略的なキャッシュ配置を提供します。

  • NONE: プロンプトのキャッシュを完全に無効にする (default)

  • SYSTEM_ONLY: システムメッセージの内容のみをキャッシュします

  • TOOLS_ONLY: ツール定義のみをキャッシュします (Claude models only)

  • SYSTEM_AND_TOOLS: システムメッセージとツール定義の両方をキャッシュします (Claude models only)

  • CONVERSATION_HISTORY: チャットメモリシナリオで会話履歴全体をキャッシュします

この戦略的なアプローチにより、AWS Bedrock の 4 つのブレークポイント制限内に留まりながら、最適なキャッシュブレークポイントの配置が保証されます。

Amazon Nova の制限

Amazon Nova モデル (Nova Micro、Lite、Pro、Premier) は、system および messages コンテンツのキャッシュのみをサポートします。tools のキャッシュはサポートしません。

Nova モデルで TOOLS_ONLY または SYSTEM_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 Fluent 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

トークン使用状況の追跡

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. Choose the Right Strategy :

    • 再利用可能なシステムプロンプトと指示には SYSTEM_ONLY を使用します (works with all models)

    • 大きな安定したツールがあるが、動的なシステムプロンプトがある場合は TOOLS_ONLY を使用します。(Claude only)

    • システムとツールの両方が大きく安定している場合は SYSTEM_AND_TOOLS を使用する (Claude only)

    • 複数ターンの会話には CONVERSATION_HISTORY と ChatClient メモリを使用します

    • NONE を使用してキャッシュを明示的に無効にする

  2. Meet Token Requirements : 最小トークン要件 (ほとんどのモデルでは 1024+ トークン) を満たすコンテンツのキャッシュに重点を置きます。

  3. Reuse Identical Content : キャッシュはプロンプトの内容が完全に一致する場合に最適に機能します。小さな変更でも、新しいキャッシュエントリが必要になります。

  4. Monitor Token Usage : メタデータメトリクスを使用してキャッシュの有効性を追跡します。

    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");
    }
  5. Strategic Cache Placement : この実装では、選択した戦略に基づいて最適な場所にキャッシュブレークポイントが自動的に配置され、AWS Bedrock の 4 つのブレークポイント制限に準拠します。

  6. Cache Lifetime : AWS Bedrock キャッシュの TTL(Time To Live)は 5 分に固定されています。キャッシュにアクセスするたびにタイマーがリセットされます。

  7. Model Compatibility : モデル固有の制限に注意してください:

    • Claude モデル : すべてのキャッシュ戦略をサポート

    • Amazon Nova モデル SYSTEM_ONLY と CONVERSATION_HISTORY のみサポート (tool caching not supported)

  8. Tool StabilityTOOLS_ONLYSYSTEM_AND_TOOLSCONVERSATION_HISTORY 戦略を使用する場合は、ツールが安定していることを確認してください。ツール定義を変更すると、カスケード無効化により、下流のすべてのキャッシュブレークポイントが無効になります。

キャッシュの無効化とカスケード動作

AWS Bedrock は、カスケード無効化を備えた階層型キャッシュモデルに従います。

Cache HierarchyTools → System → Messages

各レベルで変更を行うと、そのレベルとそれ以降のすべてのレベルが無効になります。

何が変わるのか ツールキャッシュ システムキャッシュ メッセージキャッシュ

ツール

❌ 無効

❌ 無効

❌ 無効

システム

✅ 有効

❌ 無効

❌ 無効

メッセージ

✅ 有効

✅ 有効

❌ 無効

Example with SYSTEM_AND_TOOLS strategy :

// 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. Strategic Cache Placement : キャッシュブレークポイントは、選択した戦略に基づいて最適な場所に自動的に配置され、AWS Bedrock の 4 つのブレークポイント制限に準拠します。

  2. Provider Portability : キャッシュ構成は個別のメッセージではなく BedrockChatOptions を通じて行われるため、異なる AI プロバイダー間で切り替えるときに互換性が維持されます。

  3. スレッドセーフ : キャッシュブレークポイントトラッキングは、同時リクエストを正しく処理するためのスレッドセーフメカニズムを使用して実装されています。

  4. UNION Type Pattern : AWS SDK は UNION 型を使用し、キャッシュポイントはプロパティではなく個別のブロックとして追加されます。これは直接的な API アプローチとは異なりますが、型安全性と API コンプライアンスを保証します。

  5. Incremental CachingCONVERSATION_HISTORY 戦略は、最後のユーザーメッセージにキャッシュブレークポイントを配置し、各会話ターンが前のキャッシュされたプレフィックスに基づいて構築される増分キャッシュを有効にします。

コストの考慮

AWS Bedrock pricing for prompt caching (approximate, varies by model):

  • Cache writes : ~25% more expensive than base input tokens

  • Cache reads : ~90% cheaper (only 10% of base input token price)

  • Break-even point : After just 1 cache read, you’ve saved money

Example cost calculation :

// 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 をツールとしても使用できます。

@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 などのビジョンマルチモダリティをサポートするモデル [Amazon] の場合、Bedrock Converse API Amazon を使用すると、ペイロードに複数のイメージを含めることができます。これらのモデルは、渡されたイメージを分析して質問に答えたり、イメージを分類したり、提供された指示に基づいてイメージを要約したりできます。

現在、Bedrock Converse は、image/jpegimage/pngimage/gifimage/webp MIME 型の base64 エンコードされたイメージをサポートしています。

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 :

Multimodal Test Image

「この写真に何が写っているか説明してください」というテキストメッセージとともに、次のようなレスポンスが生成されます。

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

ビデオ

Amazon Nova モデル を使用すると、ペイロードに 1 つのビデオを含めることができます。このビデオは、base64 形式または Amazon S3 URI を通じて提供できます。

現在、Bedrock Nova は video/x-matroskavideo/quicktimevideo/mp4video/webmvideo/x-flvvideo/mpegvideo/x-ms-wmvvideo/3gpp MIME 型のビデオをサポートしています。

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 :

Multimodal Test Video

「このビデオで何が見えますか?」というテキストメッセージとともに、次のようなレスポンスが生成されます。

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

文書

一部のモデルでは、Bedrock では、Converse API ドキュメントサポートを通じてペイロードにドキュメントを含めることができます。ドキュメントはバイト単位で提供できます。ドキュメントサポートには、以下で説明する 2 つの異なるバリエーションがあります。

  • テキストドキュメントの種類 (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 ドキュメントを受け取ります:

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