CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-dev-langchain4j--langchain4j-bedrock

AWS Bedrock integration for LangChain4j enabling Java applications to interact with various LLM providers through a unified interface

Overview
Eval results
Files

granular-caching.mddocs/features/prompt-caching/

Granular Caching with BedrockSystemMessage

Fine-grained cache control for mixed static and dynamic content.

Overview

BedrockSystemMessage allows marking specific content blocks for caching. Use this when you need to mix static (cacheable) and dynamic (non-cacheable) content.

public class BedrockSystemMessage implements ChatMessage {
    public static final int MAX_CONTENT_BLOCKS = 10;
    public static final int MAX_CACHE_POINTS = 4;

    public List<BedrockSystemContent> contents();
    public boolean hasCachePoints();
    public int cachePointCount();

    public static Builder builder();
    public static BedrockSystemMessage from(String text);
    public static BedrockSystemMessage from(List<BedrockSystemContent> contents);
    public static BedrockSystemMessage from(SystemMessage systemMessage);
}

Important: BedrockSystemMessage is NOT a SystemMessage subclass. It implements ChatMessage directly.

Building Messages

public static class Builder {
    public Builder contents(List<BedrockSystemContent> contents);
    public Builder addContent(BedrockSystemContent content);
    public Builder addText(String text);                      // No cache point
    public Builder addTextWithCachePoint(String text);        // With cache point

    public BedrockSystemMessage build();
}

Basic Usage

import dev.langchain4j.model.bedrock.BedrockSystemMessage;

// Mix static and dynamic content
BedrockSystemMessage message = BedrockSystemMessage.builder()
    .addTextWithCachePoint(loadStaticKnowledgeBase())  // Static: cached
    .addText("Current date: " + LocalDate.now())       // Dynamic: not cached
    .addTextWithCachePoint(loadStaticInstructions())   // Static: cached
    .build();

ChatResponse response = model.chat(ChatRequest.builder()
    .messages(message, UserMessage.from("Question"))
    .build());

Content Blocks

public final class BedrockSystemTextContent implements BedrockSystemContent {
    public static final int MAX_TEXT_LENGTH = 1_000_000;

    public BedrockSystemTextContent(String text, boolean cachePoint);
    public BedrockSystemTextContent(String text);

    public String text();
    public boolean hasCachePoint();
    public BedrockSystemContentType type();

    public static BedrockSystemTextContent from(String text);
    public static BedrockSystemTextContent withCachePoint(String text);
}

Example: Knowledge Base + Dynamic Date

String knowledgeBase = loadLargeKnowledgeBase(); // >1024 tokens, static
String instructions = loadStaticInstructions();   // >1024 tokens, static
String currentDate = "Today is " + LocalDate.now(); // Dynamic

BedrockSystemMessage systemMessage = BedrockSystemMessage.builder()
    .addTextWithCachePoint(knowledgeBase)     // Cache point 1
    .addText(currentDate)                     // No cache point
    .addTextWithCachePoint(instructions)      // Cache point 2
    .build();

// Next day: date changes, but knowledge base and instructions still cached
String newDate = "Today is " + LocalDate.now();
BedrockSystemMessage updatedMessage = BedrockSystemMessage.builder()
    .addTextWithCachePoint(knowledgeBase)     // Same: cache hit
    .addText(newDate)                         // Different: not cached anyway
    .addTextWithCachePoint(instructions)      // Same: cache hit
    .build();

Maximum Cache Points

// Use all 4 cache points
BedrockSystemMessage message = BedrockSystemMessage.builder()
    .addTextWithCachePoint("Section 1: " + loadSection1())  // Cache point 1
    .addTextWithCachePoint("Section 2: " + loadSection2())  // Cache point 2
    .addTextWithCachePoint("Section 3: " + loadSection3())  // Cache point 3
    .addTextWithCachePoint("Section 4: " + loadSection4())  // Cache point 4
    .build();

// This would fail - exceeds 4 cache points
try {
    BedrockSystemMessage tooMany = BedrockSystemMessage.builder()
        .addTextWithCachePoint("Section 1")
        .addTextWithCachePoint("Section 2")
        .addTextWithCachePoint("Section 3")
        .addTextWithCachePoint("Section 4")
        .addTextWithCachePoint("Section 5")  // 5th cache point - error!
        .build();
} catch (IllegalStateException e) {
    // Exceeded MAX_CACHE_POINTS
}

Type System Gotchas

BedrockSystemMessage is NOT a SystemMessage:

BedrockSystemMessage bedrockMsg = BedrockSystemMessage.from("Test");
SystemMessage standardMsg = SystemMessage.from("Test");

// Type checking
boolean isSystemMessage = bedrockMsg instanceof SystemMessage; // false!

// Finding in message list
List<ChatMessage> messages = List.of(bedrockMsg, UserMessage.from("Hi"));
Optional<SystemMessage> found = SystemMessage.findFirst(messages); // empty!

// Must convert for ChatMemory or serialization
SystemMessage forPersistence = bedrockMsg.toSystemMessage(); // Loses cache points

Converting Between Types

// Standard SystemMessage → BedrockSystemMessage
SystemMessage standard = SystemMessage.from("Instructions");
BedrockSystemMessage bedrock = BedrockSystemMessage.from(standard);

// BedrockSystemMessage → Standard SystemMessage (loses cache points)
BedrockSystemMessage bedrockMsg = BedrockSystemMessage.builder()
    .addTextWithCachePoint("Cached content")
    .build();
SystemMessage standard = bedrockMsg.toSystemMessage(); // Cache points lost

Validation

// Valid
BedrockSystemTextContent valid = BedrockSystemTextContent.from("Good text");

// Invalid: blank text
try {
    BedrockSystemTextContent blank = BedrockSystemTextContent.from("");
} catch (IllegalArgumentException e) {
    // "Text must not be blank"
}

// Invalid: exceeds max length
String tooLong = "x".repeat(1_000_001);
try {
    BedrockSystemTextContent oversized = BedrockSystemTextContent.from(tooLong);
} catch (IllegalArgumentException e) {
    // "Text exceeds maximum length of 1,000,000 characters"
}

Best Practices

  1. Isolate dynamic content: Don't mix dynamic strings with static cache points
  2. Ensure minimum size: Each cached section should exceed ~1,024 tokens
  3. Use up to 4 cache points: Maximize cache granularity
  4. Order matters: Cache points mark the END of content blocks

Next: Best Practices for optimization tips

Install with Tessl CLI

npx tessl i tessl/maven-dev-langchain4j--langchain4j-bedrock@1.11.0

docs

index.md

README.md

tile.json