Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:28:30 +08:00
commit 171acedaa4
220 changed files with 85967 additions and 0 deletions

View File

@@ -0,0 +1,274 @@
# Advanced Model Patterns
## Model-Specific Configuration
### Claude Models Configuration
```java
// Claude 3 Sonnet
public String invokeClaude3Sonnet(BedrockRuntimeClient client, String prompt) {
String modelId = "anthropic.claude-3-sonnet-20240229-v1:0";
JSONObject payload = new JSONObject()
.put("anthropic_version", "bedrock-2023-05-31")
.put("max_tokens", 1000)
.put("temperature", 0.7)
.put("top_p", 1.0)
.put("messages", new JSONObject[]{
new JSONObject()
.put("role", "user")
.put("content", prompt)
});
InvokeModelResponse response = client.invokeModel(request -> request
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payload.toString())));
JSONObject responseBody = new JSONObject(response.body().asUtf8String());
return responseBody.getJSONArray("content")
.getJSONObject(0)
.getString("text");
}
// Claude 3 Haiku (faster, cheaper)
public String invokeClaude3Haiku(BedrockRuntimeClient client, String prompt) {
String modelId = "anthropic.claude-3-haiku-20240307-v1:0";
JSONObject payload = new JSONObject()
.put("anthropic_version", "bedrock-2023-05-31")
.put("max_tokens", 400)
.put("messages", new JSONObject[]{
new JSONObject()
.put("role", "user")
.put("content", prompt)
});
// Similar invocation pattern as above
}
```
### Llama Models Configuration
```java
// Llama 3 70B
public String invokeLlama3_70B(BedrockRuntimeClient client, String prompt) {
String modelId = "meta.llama3-70b-instruct-v1:0";
JSONObject payload = new JSONObject()
.put("prompt", prompt)
.put("max_gen_len", 512)
.put("temperature", 0.7)
.put("top_p", 0.9)
.put("stop", new String[]{"[INST]", "[/INST]"}); // Custom stop tokens
InvokeModelResponse response = client.invokeModel(request -> request
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payload.toString())));
JSONObject responseBody = new JSONObject(response.body().asUtf8String());
return responseBody.getString("generation");
}
```
## Multi-Model Service Layer
```java
@Service
public class MultiModelService {
private final BedrockRuntimeClient bedrockRuntimeClient;
private final ObjectMapper objectMapper;
public MultiModelService(BedrockRuntimeClient bedrockRuntimeClient,
ObjectMapper objectMapper) {
this.bedrockRuntimeClient = bedrockRuntimeClient;
this.objectMapper = objectMapper;
}
public String invokeModel(String modelId, String prompt, Map<String, Object> additionalParams) {
Map<String, Object> payload = createModelPayload(modelId, prompt, additionalParams);
try {
InvokeModelResponse response = bedrockRuntimeClient.invokeModel(
request -> request
.modelId(modelId)
.body(SdkBytes.fromUtf8String(objectMapper.writeValueAsString(payload))));
return extractResponseContent(modelId, response.body().asUtf8String());
} catch (Exception e) {
throw new RuntimeException("Model invocation failed: " + e.getMessage(), e);
}
}
private Map<String, Object> createModelPayload(String modelId, String prompt,
Map<String, Object> additionalParams) {
Map<String, Object> payload = new HashMap<>();
if (modelId.startsWith("anthropic.claude")) {
payload.put("anthropic_version", "bedrock-2023-05-31");
payload.put("messages", List.of(Map.of("role", "user", "content", prompt)));
// Add common parameters with defaults
payload.putIfAbsent("max_tokens", 1000);
payload.putIfAbsent("temperature", 0.7);
} else if (modelId.startsWith("meta.llama")) {
payload.put("prompt", prompt);
payload.putIfAbsent("max_gen_len", 512);
payload.putIfAbsent("temperature", 0.7);
} else if (modelId.startsWith("amazon.titan")) {
payload.put("inputText", prompt);
payload.putIfAbsent("textGenerationConfig",
Map.of("maxTokenCount", 512, "temperature", 0.7));
}
// Add additional parameters
if (additionalParams != null) {
payload.putAll(additionalParams);
}
return payload;
}
}
```
## Advanced Error Handling
```java
@Component
public class BedrockErrorHandler {
@Retryable(value = {SdkClientException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public String invokeWithRetry(BedrockRuntimeClient client, String modelId,
String payloadJson) {
try {
InvokeModelResponse response = client.invokeModel(request -> request
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payloadJson)));
return response.body().asUtf8String();
} catch (ThrottlingException e) {
// Exponential backoff for throttling
throw new RuntimeException("Rate limit exceeded, please try again later", e);
} catch (ValidationException e) {
throw new IllegalArgumentException("Invalid request: " + e.getMessage(), e);
} catch (SdkException e) {
throw new RuntimeException("AWS SDK error: " + e.getMessage(), e);
}
}
}
```
## Batch Processing
```java
@Service
public class BedrockBatchService {
public List<String> processBatch(BedrockRuntimeClient client, String modelId,
List<String> prompts) {
return prompts.parallelStream()
.map(prompt -> invokeModelWithTimeout(client, modelId, prompt, 30))
.collect(Collectors.toList());
}
private String invokeModelWithTimeout(BedrockRuntimeClient client, String modelId,
String prompt, int timeoutSeconds) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
JSONObject payload = new JSONObject()
.put("prompt", prompt)
.put("max_tokens", 500);
InvokeModelResponse response = client.invokeModel(request -> request
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payload.toString())));
return response.body().asUtf8String();
});
try {
return future.get(timeoutSeconds, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
throw new RuntimeException("Model invocation timed out");
} catch (Exception e) {
throw new RuntimeException("Batch processing error", e);
} finally {
executor.shutdown();
}
}
}
```
## Model Performance Optimization
```java
@Configuration
public class BedrockOptimizationConfig {
@Bean
public BedrockRuntimeClient optimizedBedrockRuntimeClient() {
return BedrockRuntimeClient.builder()
.region(Region.US_EAST_1)
.overrideConfiguration(ClientOverrideConfiguration.builder()
.apiCallTimeout(Duration.ofSeconds(30))
.apiCallAttemptTimeout(Duration.ofSeconds(20))
.build())
.httpClient(ApacheHttpClient.builder()
.connectionTimeout(Duration.ofSeconds(10))
.socketTimeout(Duration.ofSeconds(30))
.build())
.build();
}
}
```
## Custom Response Parsing
```java
public class BedrockResponseParser {
public static TextResponse parseTextResponse(String modelId, String responseBody) {
try {
switch (getModelProvider(modelId)) {
case ANTHROPIC:
return parseAnthropicResponse(responseBody);
case META:
return parseMetaResponse(responseBody);
case AMAZON:
return parseAmazonResponse(responseBody);
default:
throw new IllegalArgumentException("Unsupported model: " + modelId);
}
} catch (Exception e) {
throw new ResponseParsingException("Failed to parse response for model: " + modelId, e);
}
}
private static TextResponse parseAnthropicResponse(String responseBody) throws JSONException {
JSONObject json = new JSONObject(responseBody);
JSONArray content = json.getJSONArray("content");
String text = content.getJSONObject(0).getString("text");
int usage = json.getJSONObject("usage").getInt("input_tokens");
return new TextResponse(text, usage, "anthropic");
}
private static TextResponse parseMetaResponse(String responseBody) throws JSONException {
JSONObject json = new JSONObject(responseBody);
String text = json.getString("generation");
// Note: Meta doesn't provide token usage in basic response
return new TextResponse(text, 0, "meta");
}
private enum ModelProvider {
ANTHROPIC, META, AMAZON
}
public record TextResponse(String content, int tokensUsed, String provider) {}
}
```

View File

@@ -0,0 +1,372 @@
# Advanced Amazon Bedrock Topics
This document covers advanced patterns and topics for working with Amazon Bedrock using AWS SDK for Java 2.x.
## Multi-Model Service Pattern
Create a service that can handle multiple foundation models with unified interfaces.
```java
@Service
public class MultiModelAIService {
private final BedrockRuntimeClient bedrockRuntimeClient;
public MultiModelAIService(BedrockRuntimeClient bedrockRuntimeClient) {
this.bedrockRuntimeClient = bedrockRuntimeClient;
}
public GenerationResult generate(GenerationRequest request) {
String modelId = request.getModelId();
String prompt = request.getPrompt();
switch (getModelProvider(modelId)) {
case ANTHROPIC:
return generateWithAnthropic(modelId, prompt, request.getConfig());
case AMAZON:
return generateWithAmazon(modelId, prompt, request.getConfig());
case META:
return generateWithMeta(modelId, prompt, request.getConfig());
default:
throw new IllegalArgumentException("Unsupported model provider: " + modelId);
}
}
private GenerationProvider getModelProvider(String modelId) {
if (modelId.startsWith("anthropic.")) return GenerationProvider.ANTHROPIC;
if (modelId.startsWith("amazon.")) return GenerationProvider.AMazon;
if (modelId.startsWith("meta.")) return GenerationProvider.META;
throw new IllegalArgumentException("Unknown provider for model: " + modelId);
}
}
```
## Advanced Error Handling with Retries
Implement robust error handling with exponential backoff:
```java
import software.amazon.awssdk.core.retry.RetryPolicy;
import software.amazon.awssdk.core.retry.backoff.BackoffStrategy;
import software.amazon.awssdk.core.retry.conditions.RetryCondition;
import software.amazon.awssdk.core.retry.predicates.RetryExceptionPredicates;
public class BedrockWithRetry {
private final BedrockRuntimeClient client;
private final RetryPolicy retryPolicy;
public BedrockWithRetry(BedrockRuntimeClient client) {
this.client = client;
this.retryPolicy = RetryPolicy.builder()
.numRetries(3)
.retryCondition(RetryExceptionPredicates.equalTo(
ThrottlingException.class))
.backoffStrategy(BackoffStrategy.defaultStrategy())
.build();
}
public String invokeModelWithRetry(String modelId, String payload) {
try {
InvokeModelRequest request = InvokeModelRequest.builder()
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payload))
.build();
InvokeModelResponse response = client.invokeModel(request);
return response.body().asUtf8String();
} catch (ThrottlingException e) {
throw new BedrockThrottledException("Rate limit exceeded for model: " + modelId, e);
} catch (ValidationException e) {
throw new BedrockValidationException("Invalid request for model: " + modelId, e);
}
}
}
```
## Batch Processing Strategies
Process multiple requests efficiently:
```java
@Service
public class BatchGenerationService {
private final BedrockRuntimeClient bedrockRuntimeClient;
public BatchGenerationService(BedrockRuntimeClient bedrockRuntimeClient) {
this.bedrockRuntimeClient = bedrockRuntimeClient;
}
public List<BatchResult> processBatch(List<BatchRequest> requests) {
// Process in parallel
return requests.parallelStream()
.map(this::processSingleRequest)
.collect(Collectors.toList());
}
private BatchResult processSingleRequest(BatchRequest request) {
try {
InvokeModelRequest modelRequest = InvokeModelRequest.builder()
.modelId(request.getModelId())
.body(SdkBytes.fromUtf8String(request.getPayload()))
.build();
InvokeModelResponse response = bedrockRuntimeClient.invokeModel(modelRequest);
return BatchResult.success(
request.getRequestId(),
response.body().asUtf8String()
);
} catch (Exception e) {
return BatchResult.failure(request.getRequestId(), e.getMessage());
}
}
}
```
## Performance Optimization Techniques
### Connection Pooling
```java
import software.amazon.awssdk.http.nio.apache.ApacheHttpClient;
import software.amazon.awssdk.http.apache.ProxyConfiguration;
import software.amazon.awssdk.regions.Region;
public class BedrockClientFactory {
public static BedrockRuntimeClient createOptimizedClient() {
ApacheHttpClient httpClient = ApacheHttpClient.builder()
.connectionPoolMaxConnections(50)
.socketTimeout(Duration.ofSeconds(30))
.connectionTimeout(Duration.ofSeconds(30))
.build();
return BedrockRuntimeClient.builder()
.region(Region.US_EAST_1)
.httpClient(httpClient)
.build();
}
}
```
### Response Caching
```java
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
@Service
public class CachedAIService {
private final BedrockRuntimeClient bedrockRuntimeClient;
private final Cache<String, String> responseCache;
public CachedAIService(BedrockRuntimeClient bedrockRuntimeClient) {
this.bedrockRuntimeClient = bedrockRuntimeClient;
this.responseCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(1, TimeUnit.HOURS)
.build();
}
public String generateText(String prompt, String modelId) {
String cacheKey = modelId + ":" + prompt.hashCode();
return responseCache.get(cacheKey, key -> {
String payload = createPayload(modelId, prompt);
InvokeModelRequest request = InvokeModelRequest.builder()
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payload))
.build();
InvokeModelResponse response = bedrockRuntimeClient.invokeModel(request);
return response.body().asUtf8String();
});
}
}
```
## Custom Response Parsing
Create specialized parsers for different model responses:
```java
public interface ResponseParser {
String parse(String responseJson);
}
public class AnthropicResponseParser implements ResponseParser {
@Override
public String parse(String responseJson) {
try {
JSONObject jsonResponse = new JSONObject(responseJson);
return jsonResponse.getJSONArray("content")
.getJSONObject(0)
.getString("text");
} catch (Exception e) {
throw new ResponseParsingException("Failed to parse Anthropic response", e);
}
}
}
public class AmazonTitanResponseParser implements ResponseParser {
@Override
public String parse(String responseJson) {
try {
JSONObject jsonResponse = new JSONObject(responseJson);
return jsonResponse.getJSONArray("results")
.getJSONObject(0)
.getString("outputText");
} catch (Exception e) {
throw new ResponseParsingException("Failed to parse Amazon Titan response", e);
}
}
}
public class LlamaResponseParser implements ResponseParser {
@Override
public String parse(String responseJson) {
try {
JSONObject jsonResponse = new JSONObject(responseJson);
return jsonResponse.getString("generation");
} catch (Exception e) {
throw new ResponseParsingException("Failed to parse Llama response", e);
}
}
}
```
## Metrics and Monitoring
Implement comprehensive monitoring:
```java
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
@Service
public class MonitoredAIService {
private final BedrockRuntimeClient bedrockRuntimeClient;
private final Timer generationTimer;
private final Counter errorCounter;
public MonitoredAIService(BedrockRuntimeClient bedrockRuntimeClient,
MeterRegistry meterRegistry) {
this.bedrockRuntimeClient = bedrockRuntimeClient;
this.generationTimer = Timer.builder("bedrock.generation.time")
.description("Time spent generating text with Bedrock")
.register(meterRegistry);
this.errorCounter = Counter.builder("bedrock.generation.errors")
.description("Number of generation errors")
.register(meterRegistry);
}
public String generateText(String prompt, String modelId) {
return generationTimer.record(() -> {
try {
String payload = createPayload(modelId, prompt);
InvokeModelRequest request = InvokeModelRequest.builder()
.modelId(modelId)
.body(SdkBytes.fromUtf8String(payload))
.build();
InvokeModelResponse response = bedrockRuntimeClient.invokeModel(request);
return response.body().asUtf8String();
} catch (Exception e) {
errorCounter.increment();
throw new GenerationException("Failed to generate text", e);
}
});
}
}
```
## Advanced Configuration Management
```java
@Configuration
@ConfigurationProperties(prefix = "bedrock")
public class AdvancedBedrockConfiguration {
private String defaultRegion = "us-east-1";
private int maxRetries = 3;
private Duration timeout = Duration.ofSeconds(30);
private boolean enableMetrics = true;
private int maxCacheSize = 1000;
private Duration cacheExpireAfter = Duration.ofHours(1);
@Bean
@Primary
public BedrockRuntimeClient bedrockRuntimeClient() {
BedrockRuntimeClient.Builder builder = BedrockRuntimeClient.builder()
.region(Region.of(defaultRegion));
if (enableMetrics) {
builder.overrideConfiguration(c -> c.putAdvancedProperty(
"metrics.enabled", "true"));
}
return builder.build();
}
// Getters and setters
}
```
## Streaming Response Handling
Advanced streaming with proper backpressure handling:
```java
@Service
public class StreamingAIService {
private final BedrockRuntimeClient bedrockRuntimeClient;
public StreamingAIService(BedrockRuntimeClient bedrockRuntimeClient) {
this.bedrockRuntimeClient = bedrockRuntimeClient;
}
public Flux<String> streamResponse(String modelId, String prompt) {
InvokeModelWithResponseStreamRequest request =
InvokeModelWithResponseStreamRequest.builder()
.modelId(modelId)
.body(SdkBytes.fromUtf8String(createPayload(modelId, prompt)))
.build();
return Mono.fromCallable(() ->
bedrockRuntimeClient.invokeModelWithResponseStream(request))
.flatMapMany(responseStream -> Flux.defer(() ->
Flux.create(sink -> {
responseStream.stream().forEach(event -> {
if (event instanceof PayloadPart) {
PayloadPart payloadPart = (PayloadPart) event;
String chunk = payloadPart.bytes().asUtf8String();
processChunk(chunk, sink);
}
});
sink.complete();
}))
)
.onErrorResume(e -> Flux.error(new StreamingException("Stream failed", e)));
}
private void processChunk(String chunk, FluxSink<String> sink) {
try {
JSONObject chunkJson = new JSONObject(chunk);
if (chunkJson.getString("type").equals("content_block_delta")) {
String text = chunkJson.getJSONObject("delta").getString("text");
sink.next(text);
}
} catch (Exception e) {
sink.error(new ChunkProcessingException("Failed to process chunk", e));
}
}
}
```

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<!DOCTYPE HTML><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Amazon Bedrock</title><meta xmlns="" name="subtitle" content="API Reference"><meta xmlns="" name="abstract" content="Details about operations and parameters in the Amazon Bedrock API Reference"><meta http-equiv="refresh" content="10;URL=welcome.html"><script type="text/javascript"><!--
var myDefaultPage = "welcome.html";
var myPage = document.location.search.substr(1);
var myHash = document.location.hash;
if (myPage == null || myPage.length == 0) {
myPage = myDefaultPage;
} else {
var docfile = myPage.match(/[^=\;\/?:\s]+\.html/);
if (docfile == null) {
myPage = myDefaultPage;
} else {
myPage = docfile + myHash;
}
}
self.location.replace(myPage);
--></script></head><body></body></html>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<!DOCTYPE HTML><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Amazon Bedrock</title><meta xmlns="" name="subtitle" content="User Guide"><meta xmlns="" name="abstract" content="User Guide for the Amazon Bedrock service."><meta http-equiv="refresh" content="10;URL=what-is-bedrock.html"><script type="text/javascript"><!--
var myDefaultPage = "what-is-bedrock.html";
var myPage = document.location.search.substr(1);
var myHash = document.location.hash;
if (myPage == null || myPage.length == 0) {
myPage = myDefaultPage;
} else {
var docfile = myPage.match(/[^=\;\/?:\s]+\.html/);
if (docfile == null) {
myPage = myDefaultPage;
} else {
myPage = docfile + myHash;
}
}
self.location.replace(myPage);
--></script></head><body></body></html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,148 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<!-- Generated by javadoc (23) on Tue Oct 28 00:04:26 UTC 2025 -->
<title>software.amazon.awssdk.services.bedrock (AWS SDK for Java - 2.36.3)</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="dc.created" content="2025-10-28">
<meta name="description" content="declaration: package: software.amazon.awssdk.services.bedrock">
<meta name="generator" content="javadoc/PackageWriter">
<link rel="stylesheet" type="text/css" href="../../../../../resource-files/jquery-ui.min.css" title="Style">
<link rel="stylesheet" type="text/css" href="../../../../../resource-files/stylesheet.css" title="Style">
<link rel="stylesheet" type="text/css" href="../../../../../resource-files/aws-sdk-java-v2-javadoc.css" title="Style">
<script type="text/javascript" src="../../../../../script-files/script.js"></script>
<script type="text/javascript" src="../../../../../script-files/jquery-3.7.1.min.js"></script>
<script type="text/javascript" src="../../../../../script-files/jquery-ui.min.js"></script>
</head>
<body class="package-declaration-page">
<script type="text/javascript">const pathtoroot = "../../../../../";
loadScripts(document, 'script');</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<header role="banner">
<nav role="navigation">
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="top-nav" id="navbar-top">
<div class="nav-content">
<div class="nav-menu-button"><button id="navbar-toggle-button" aria-controls="navbar-top" aria-expanded="false" aria-label="Toggle navigation links"><span class="nav-bar-toggle-icon">&nbsp;</span><span class="nav-bar-toggle-icon">&nbsp;</span><span class="nav-bar-toggle-icon">&nbsp;</span></button></div>
<div class="skip-nav"><a href="#skip-navbar-top" title="Skip navigation links">Skip navigation links</a></div>
<ul id="navbar-top-firstrow" class="nav-list" title="Navigation">
<li><a href="../../../../../index.html">Overview</a></li>
<li class="nav-bar-cell1-rev">Package</li>
<li><a href="../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../search.html">Search</a></li>
<li><a href="../../../../../help-doc.html#package">Help</a></li>
</ul>
<div class="about-language"><h2>AWS SDK for Java API Reference - 2.36.3</h2></div>
</div>
</div>
<div class="sub-nav">
<div class="nav-content">
<ol class="sub-nav-list">
<li><a href="package-summary.html" class="current-selection">software.amazon.awssdk.services.bedrock</a></li>
</ol>
<div class="nav-list-search">
<input type="text" id="search-input" disabled placeholder="Search" aria-label="Search in documentation" autocomplete="off">
<input type="reset" id="reset-search" disabled value="Reset">
</div>
</div>
</div>
<!-- ========= END OF TOP NAVBAR ========= -->
<span class="skip-nav" id="skip-navbar-top"></span></nav>
</header>
<div class="main-grid">
<nav role="navigation" class="toc" aria-label="Table of contents">
<div class="toc-header">Contents</div>
<button class="hide-sidebar"><span>Hide sidebar&nbsp;</span>&#10094;</button><button class="show-sidebar">&#10095;<span>&nbsp;Show sidebar</span></button>
<ol class="toc-list">
<li><a href="#" tabindex="0">Description</a></li>
<li><a href="#related-package-summary" tabindex="0">Related Packages</a></li>
<li><a href="#class-summary" tabindex="0">Classes and Interfaces</a></li>
</ol>
</nav>
<main role="main">
<div class="header">
<h1 title="Package software.amazon.awssdk.services.bedrock" class="title">Package software.amazon.awssdk.services.bedrock</h1>
</div>
<hr>
<div class="horizontal-scroll">
<div class="package-signature">package <span class="element-name">software.amazon.awssdk.services.bedrock</span></div>
<section class="package-description" id="package-description">
<div class="block"><p>
Describes the API operations for creating, managing, fine-turning, and evaluating Amazon Bedrock models.
</p></div>
</section>
</div>
<section class="summary">
<ul class="summary-list">
<li>
<div id="related-package-summary">
<div class="caption"><span>Related Packages</span></div>
<div class="summary-table two-column-summary">
<div class="table-header col-first">Package</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color"><a href="endpoints/package-summary.html">software.amazon.awssdk.services.bedrock.endpoints</a></div>
<div class="col-last even-row-color">&nbsp;</div>
<div class="col-first odd-row-color"><a href="internal/package-summary.html">software.amazon.awssdk.services.bedrock.internal</a></div>
<div class="col-last odd-row-color">&nbsp;</div>
<div class="col-first even-row-color"><a href="model/package-summary.html">software.amazon.awssdk.services.bedrock.model</a></div>
<div class="col-last even-row-color">&nbsp;</div>
<div class="col-first odd-row-color"><a href="paginators/package-summary.html">software.amazon.awssdk.services.bedrock.paginators</a></div>
<div class="col-last odd-row-color">&nbsp;</div>
<div class="col-first even-row-color"><a href="transform/package-summary.html">software.amazon.awssdk.services.bedrock.transform</a></div>
<div class="col-last even-row-color">&nbsp;</div>
</div>
</div>
</li>
<li>
<div id="class-summary">
<div class="table-tabs" role="tablist" aria-orientation="horizontal"><button id="class-summary-tab0" role="tab" aria-selected="true" aria-controls="class-summary.tabpanel" tabindex="0" onkeydown="switchTab(event)" onclick="show('class-summary', 'class-summary', 2)" class="active-table-tab">All Classes and Interfaces</button><button id="class-summary-tab1" role="tab" aria-selected="false" aria-controls="class-summary.tabpanel" tabindex="-1" onkeydown="switchTab(event)" onclick="show('class-summary', 'class-summary-tab1', 2)" class="table-tab">Interfaces</button><button id="class-summary-tab2" role="tab" aria-selected="false" aria-controls="class-summary.tabpanel" tabindex="-1" onkeydown="switchTab(event)" onclick="show('class-summary', 'class-summary-tab2', 2)" class="table-tab">Classes</button></div>
<div id="class-summary.tabpanel" role="tabpanel" aria-labelledby="class-summary-tab0">
<div class="summary-table two-column-summary">
<div class="table-header col-first">Class</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color class-summary class-summary-tab1"><a href="BedrockAsyncClient.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockAsyncClient</a></div>
<div class="col-last even-row-color class-summary class-summary-tab1">
<div class="block">Service client for accessing Amazon Bedrock asynchronously.</div>
</div>
<div class="col-first odd-row-color class-summary class-summary-tab1"><a href="BedrockAsyncClientBuilder.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockAsyncClientBuilder</a></div>
<div class="col-last odd-row-color class-summary class-summary-tab1">
<div class="block">A builder for creating an instance of <a href="BedrockAsyncClient.html" title="interface in software.amazon.awssdk.services.bedrock"><code>BedrockAsyncClient</code></a>.</div>
</div>
<div class="col-first even-row-color class-summary class-summary-tab1"><a href="BedrockBaseClientBuilder.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockBaseClientBuilder</a>&lt;B extends <a href="BedrockBaseClientBuilder.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockBaseClientBuilder</a>&lt;B,<wbr>C&gt;,<wbr>C&gt;</div>
<div class="col-last even-row-color class-summary class-summary-tab1">
<div class="block">This includes configuration specific to Amazon Bedrock that is supported by both <a href="BedrockClientBuilder.html" title="interface in software.amazon.awssdk.services.bedrock"><code>BedrockClientBuilder</code></a> and
<a href="BedrockAsyncClientBuilder.html" title="interface in software.amazon.awssdk.services.bedrock"><code>BedrockAsyncClientBuilder</code></a>.</div>
</div>
<div class="col-first odd-row-color class-summary class-summary-tab1"><a href="BedrockClient.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockClient</a></div>
<div class="col-last odd-row-color class-summary class-summary-tab1">
<div class="block">Service client for accessing Amazon Bedrock.</div>
</div>
<div class="col-first even-row-color class-summary class-summary-tab1"><a href="BedrockClientBuilder.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockClientBuilder</a></div>
<div class="col-last even-row-color class-summary class-summary-tab1">
<div class="block">A builder for creating an instance of <a href="BedrockClient.html" title="interface in software.amazon.awssdk.services.bedrock"><code>BedrockClient</code></a>.</div>
</div>
<div class="col-first odd-row-color class-summary class-summary-tab2"><a href="BedrockServiceClientConfiguration.html" title="class in software.amazon.awssdk.services.bedrock">BedrockServiceClientConfiguration</a></div>
<div class="col-last odd-row-color class-summary class-summary-tab2">
<div class="block">Class to expose the service client settings to the user.</div>
</div>
<div class="col-first even-row-color class-summary class-summary-tab1"><a href="BedrockServiceClientConfiguration.Builder.html" title="interface in software.amazon.awssdk.services.bedrock">BedrockServiceClientConfiguration.Builder</a></div>
<div class="col-last even-row-color class-summary class-summary-tab1">
<div class="block">A builder for creating a <a href="BedrockServiceClientConfiguration.html" title="class in software.amazon.awssdk.services.bedrock"><code>BedrockServiceClientConfiguration</code></a></div>
</div>
</div>
</div>
</div>
</li>
</ul>
</section>
<footer role="contentinfo">
<hr>
<p class="legal-copy"><small><div style="margin:1.2em;"><h3><a id="fdbk" target="_blank">Provide feedback</a><h3></div> <span id="awsdocs-legal-zone-copyright"></span> <script type="text/javascript">document.addEventListener("DOMContentLoaded",()=>{ var a=document.createElement("meta"),b=document.createElement("meta"),c=document.createElement("script"), h=document.getElementsByTagName("head")[0],l=location.href,f=document.getElementById("fdbk"); a.name="guide-name",a.content="API Reference";b.name="service-name",b.content="AWS SDK for Java"; c.setAttribute("type","text/javascript"),c.setAttribute("src", "https://docs.aws.amazon.com/assets/js/awsdocs-boot.js");h.appendChild(a);h.appendChild(b); h.appendChild(c);f.setAttribute("href", "https://docs-feedback.aws.amazon.com/feedback.jsp?hidden_service_name="+ encodeURI("AWS SDK for Java")+"&topic_url="+encodeURI(l))}); </script></small></p>
</footer>
</main>
</div>
</body>
</html>

View File

@@ -0,0 +1,340 @@
# Model Reference
## Supported Foundation Models
### Amazon Models
#### Amazon Titan Text
**Model ID:** `amazon.titan-text-express-v1`
- **Description:** High-quality text generation model
- **Context Window:** Up to 8K tokens
- **Languages:** English, Spanish, French, German, Italian, Portuguese
**Payload Format:**
```json
{
"inputText": "Your prompt here",
"textGenerationConfig": {
"maxTokenCount": 512,
"temperature": 0.7,
"topP": 0.9
}
}
```
**Response Format:**
```json
{
"results": [{
"outputText": "Generated text"
}]
}
```
#### Amazon Titan Text Lite
**Model ID:** `amazon.titan-text-lite-v1`
- **Description:** Cost-effective text generation model
- **Context Window:** Up to 4K tokens
- **Use Case:** Simple text generation tasks
#### Amazon Titan Embeddings
**Model ID:** `amazon.titan-embed-text-v1`
- **Description:** High-quality text embeddings
- **Context Window:** 8K tokens
- **Output:** 1024-dimensional vector
**Payload Format:**
```json
{
"inputText": "Your text here"
}
```
**Response Format:**
```json
{
"embedding": [0.1, -0.2, 0.3, ...]
}
```
#### Amazon Titan Image Generator
**Model ID:** `amazon.titan-image-generator-v1`
- **Description:** High-quality image generation
- **Image Size:** 512x512, 1024x1024
- **Use Case:** Text-to-image generation
**Payload Format:**
```json
{
"taskType": "TEXT_IMAGE",
"textToImageParams": {
"text": "Your description"
},
"imageGenerationConfig": {
"numberOfImages": 1,
"quality": "standard",
"cfgScale": 8.0,
"height": 512,
"width": 512,
"seed": 12345
}
}
```
### Anthropic Models
#### Claude 3.5 Sonnet
**Model ID:** `anthropic.claude-3-5-sonnet-20241022-v2:0`
- **Description:** High-performance model for complex reasoning, analysis, and creative tasks
- **Context Window:** 200K tokens
- **Languages:** Multiple languages supported
- **Use Case:** Code generation, complex analysis, creative writing, research
- **Features:** Tool use, function calling, JSON mode
**Payload Format:**
```json
{
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
"messages": [{
"role": "user",
"content": "Your message"
}]
}
```
**Response Format:**
```json
{
"content": [{
"text": "Response content"
}],
"usage": {
"input_tokens": 10,
"output_tokens": 20
}
}
```
#### Claude 3.5 Haiku
**Model ID:** `anthropic.claude-3-5-haiku-20241022-v2:0`
- **Description:** Fast and affordable model for real-time applications
- **Context Window:** 200K tokens
- **Use Case:** Real-time applications, chatbots, quick responses
- **Features:** Tool use, function calling, JSON mode
#### Claude 3 Opus
**Model ID:** `anthropic.claude-3-opus-20240229-v1:0`
- **Description:** Most capable model
- **Context Window:** 200K tokens
- **Use Case:** Complex reasoning, analysis
#### Claude 3 Sonnet (Legacy)
**Model ID:** `anthropic.claude-3-sonnet-20240229-v1:0`
- **Description:** Previous generation model
- **Context Window:** 200K tokens
- **Use Case:** General purpose applications
### Meta Models
#### Llama 3.1 70B
**Model ID:** `meta.llama3-1-70b-instruct-v1:0`
- **Description:** Latest generation large open-source model
- **Context Window:** 128K tokens
- **Use Case:** General purpose instruction following, complex reasoning
- **Features:** Improved instruction following, larger context window
#### Llama 3.1 8B
**Model ID:** `meta.llama3-1-8b-instruct-v1:0`
- **Description:** Latest generation small fast model
- **Context Window:** 8K tokens
- **Use Case:** Fast inference, lightweight applications
#### Llama 3 70B
**Model ID:** `meta.llama3-70b-instruct-v1:0`
- **Description:** Previous generation large open-source model
- **Context Window:** 8K tokens
- **Use Case:** General purpose instruction following
**Payload Format:**
```json
{
"prompt": "[INST] Your prompt here [/INST]",
"max_gen_len": 512,
"temperature": 0.7,
"top_p": 0.9
}
```
**Response Format:**
```json
{
"generation": "Generated text"
}
```
#### Llama 3 8B
**Model ID:** `meta.llama3-8b-instruct-v1:0`
- **Description:** Smaller, faster version
- **Context Window:** 8K tokens
- **Use Case:** Fast inference, lightweight applications
### Stability AI Models
#### Stable Diffusion XL
**Model ID:** `stability.stable-diffusion-xl-v1`
- **Description:** High-quality image generation
- **Image Size:** Up to 1024x1024
- **Use Case:** Text-to-image generation, art creation
**Payload Format:**
```json
{
"text_prompts": [{
"text": "Your description"
}],
"style_preset": "photographic",
"seed": 12345,
"cfg_scale": 10,
"steps": 50
}
```
**Response Format:**
```json
{
"artifacts": [{
"base64": "base64-encoded-image-data",
"finishReason": "SUCCESS"
}]
}
```
### Other Models
#### Cohere Command
**Model ID:** `cohere.command-text-v14`
- **Description:** Text generation model
- **Context Window:** 128K tokens
- **Use Case:** Content generation, summarization
#### Mistral Models
**Model ID:** `mistral.mistral-7b-instruct-v0:2`
- **Description:** High-performing open-source model
- **Context Window:** 32K tokens
- **Use Case:** Instruction following, code generation
**Model ID:** `mistral.mixtral-8x7b-instruct-v0:1`
- **Description:** Mixture of experts model
- **Context Window:** 32K tokens
- **Use Case:** Complex reasoning tasks
## Model Selection Guide
### Use Case Recommendations
| Use Case | Recommended Models | Notes |
|----------|-------------------|-------|
| **General Chat/Chatbots** | Claude 3.5 Haiku, Llama 3 8B | Fast response times |
| **Content Creation** | Claude 3.5 Sonnet, Cohere | Creative, coherent outputs |
| **Code Generation** | Claude 3.5 Sonnet, Llama 3.1 70B | Excellent understanding |
| **Analysis & Reasoning** | Claude 3 Opus, Claude 3.5 Sonnet | Complex reasoning |
| **Real-time Applications** | Claude 3.5 Haiku, Titan Lite | Fast inference |
| **Cost-sensitive Apps** | Titan Lite, Claude 3.5 Haiku | Lower cost per token |
| **High Quality** | Claude 3 Opus, Claude 3.5 Sonnet | Premium quality |
### Performance Characteristics
| Model | Speed | Cost | Quality | Context Window |
|-------|-------|------|---------|----------------|
| Claude 3 Opus | Slow | High | Excellent | 200K |
| Claude 3.5 Sonnet | Medium | Medium | Excellent | 200K |
| Claude 3.5 Haiku | Fast | Low | Good | 200K |
| Claude 3 Sonnet (Legacy) | Medium | Medium | Good | 200K |
| Llama 3.1 70B | Medium | Medium | Good | 128K |
| Llama 3.1 8B | Fast | Low | Fair | 8K |
| Llama 3 70B | Medium | Medium | Good | 8K |
| Llama 3 8B | Fast | Low | Fair | 8K |
| Titan Express | Fast | Medium | Good | 8K |
| Titan Lite | Fast | Low | Fair | 4K |
## Model Comparison Matrix
| Feature | Claude 3 | Llama 3 | Titan | Stability |
|---------|----------|---------|-------|-----------|
| **Streaming** | ✅ | ✅ | ✅ | ❌ |
| **Tool Use** | ✅ | ❌ | ❌ | ❌ |
| **Image Generation** | ❌ | ❌ | ✅ | ✅ |
| **Embeddings** | ❌ | ❌ | ✅ | ❌ |
| **Multiple Languages** | ✅ | ✅ | ✅ | ✅ |
| **Context Window** | 200K | 8K | 8K | N/A |
| **Open Source** | ❌ | ✅ | ❌ | ✅ |
## Model Configuration Templates
### Text Generation Template
```java
private static JSONObject createTextGenerationPayload(String modelId, String prompt) {
JSONObject payload = new JSONObject();
if (modelId.startsWith("anthropic.claude")) {
payload.put("anthropic_version", "bedrock-2023-05-31");
payload.put("max_tokens", 1000);
payload.put("messages", new JSONObject[]{new JSONObject()
.put("role", "user")
.put("content", prompt)
});
} else if (modelId.startsWith("meta.llama")) {
payload.put("prompt", "[INST] " + prompt + " [/INST]");
payload.put("max_gen_len", 512);
} else if (modelId.startsWith("amazon.titan")) {
payload.put("inputText", prompt);
payload.put("textGenerationConfig", new JSONObject()
.put("maxTokenCount", 512)
.put("temperature", 0.7)
);
}
return payload;
}
```
### Image Generation Template
```java
private static JSONObject createImageGenerationPayload(String modelId, String prompt) {
JSONObject payload = new JSONObject();
if (modelId.equals("amazon.titan-image-generator-v1")) {
payload.put("taskType", "TEXT_IMAGE");
payload.put("textToImageParams", new JSONObject().put("text", prompt));
payload.put("imageGenerationConfig", new JSONObject()
.put("numberOfImages", 1)
.put("quality", "standard")
.put("height", 512)
.put("width", 512)
);
} else if (modelId.equals("stability.stable-diffusion-xl-v1")) {
payload.put("text_prompts", new JSONObject[]{new JSONObject().put("text", prompt)});
payload.put("style_preset", "photographic");
payload.put("steps", 50);
payload.put("cfg_scale", 10);
}
return payload;
}
```

View File

@@ -0,0 +1,121 @@
# Model ID Lookup Guide
This document provides quick lookup for the most commonly used model IDs in Amazon Bedrock.
## Text Generation Models
### Claude (Anthropic)
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Claude 4.5 Sonnet | `anthropic.claude-sonnet-4-5-20250929-v1:0` | Latest high-performance model | Complex reasoning, coding, creative tasks |
| Claude 4.5 Haiku | `anthropic.claude-haiku-4-5-20251001-v1:0` | Latest fast model | Real-time applications, chatbots |
| Claude 3.7 Sonnet | `anthropic.claude-3-7-sonnet-20250219-v1:0` | Most advanced reasoning | High-stakes decisions, complex analysis |
| Claude Opus 4.1 | `anthropic.claude-opus-4-1-20250805-v1:0` | Most powerful creative | Advanced creative tasks |
| Claude 3.5 Sonnet v2 | `anthropic.claude-3-5-sonnet-20241022-v2:0` | High-performance model | General use, coding |
| Claude 3.5 Haiku | `anthropic.claude-3-5-haiku-20241022-v1:0` | Fast and affordable | Real-time applications |
### Llama (Meta)
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Llama 3.3 70B | `meta.llama3-3-70b-instruct-v1:0` | Latest generation | Complex reasoning, general use |
| Llama 3.2 90B | `meta.llama3-2-90b-instruct-v1:0` | Large context | Long context tasks |
| Llama 3.2 11B | `meta.llama3-2-11b-instruct-v1:0` | Medium model | Balanced performance |
| Llama 3.2 3B | `meta.llama3-2-3b-instruct-v1:0` | Small model | Fast inference |
| Llama 3.2 1B | `meta.llama3-2-1b-instruct-v1:0` | Ultra-fast | Quick responses |
| Llama 3.1 70B | `meta.llama3-1-70b-instruct-v1:0` | Previous gen | General use |
| Llama 3.1 8B | `meta.llama3-1-8b-instruct-v1:0` | Fast small model | Lightweight applications |
### Mistral AI
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Mistral Large 2407 | `mistral.mistral-large-2407-v1:0` | Latest large model | Complex reasoning |
| Mistral Large 2402 | `mistral.mistral-large-2402-v1:0` | Previous large model | General use |
| Mistral Pixtral 2502 | `mistral.pixtral-large-2502-v1:0` | Multimodal | Text + image understanding |
| Mistral 7B | `mistral.mistral-7b-instruct-v0:2` | Small fast model | Quick responses |
### Amazon
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Titan Text Express | `amazon.titan-text-express-v1` | Fast text generation | Quick responses |
| Titan Text Lite | `amazon.titan-text-lite-v1` | Cost-effective | Budget-sensitive apps |
| Titan Embeddings | `amazon.titan-embed-text-v1` | Text embeddings | Semantic search |
### Cohere
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Command R+ | `cohere.command-r-plus-v1:0` | High performance | Complex tasks |
| Command R | `cohere.command-r-v1:0` | General purpose | Standard use cases |
## Image Generation Models
### Stability AI
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Stable Diffusion 3.5 Large | `stability.sd3-5-large-v1:0` | Latest image gen | High-quality images |
| Stable Diffusion XL | `stability.stable-diffusion-xl-v1` | Previous generation | General image generation |
### Amazon Nova
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Nova Canvas | `amazon.nova-canvas-v1:0` | Image generation | Creative images |
| Nova Reel | `amazon.nova-reel-v1:1` | Video generation | Video content |
## Embedding Models
### Amazon
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Titan Embeddings | `amazon.titan-embed-text-v1` | Text embeddings | Semantic search |
| Titan Embeddings V2 | `amazon.titan-embed-text-v2:0` | Improved embeddings | Better accuracy |
### Cohere
| Model | Model ID | Description | Use Case |
|-------|----------|-------------|----------|
| Embed English | `cohere.embed-english-v3` | English embeddings | English content |
| Embed Multilingual | `cohere.embed-multilingual-v3` | Multi-language | International use |
## Selection Guide
### By Speed
1. **Fastest**: Llama 3.2 1B, Claude 4.5 Haiku, Titan Lite
2. **Fast**: Mistral 7B, Llama 3.2 3B
3. **Medium**: Claude 3.5 Sonnet, Llama 3.2 11B
4. **Slow**: Claude 4.5 Sonnet, Llama 3.3 70B
### By Quality
1. **Highest**: Claude 4.5 Sonnet, Claude 3.7 Sonnet, Claude Opus 4.1
2. **High**: Claude 3.5 Sonnet, Llama 3.3 70B
3. **Medium**: Mistral Large, Llama 3.2 11B
4. **Basic**: Mistral 7B, Llama 3.2 3B
### By Cost
1. **Most Affordable**: Claude 4.5 Haiku, Llama 3.2 1B
2. **Affordable**: Mistral 7B, Titan Lite
3. **Medium**: Claude 3.5 Haiku, Llama 3.2 3B
4. **Expensive**: Claude 4.5 Sonnet, Llama 3.3 70B
## Common Patterns
### Default Model Selection
```java
// For most applications
String DEFAULT_MODEL = "anthropic.claude-sonnet-4-5-20250929-v1:0";
// For real-time applications
String FAST_MODEL = "anthropic.claude-haiku-4-5-20251001-v1:0";
// For budget-sensitive applications
String CHEAP_MODEL = "amazon.titan-text-lite-v1";
// For complex reasoning
String POWERFUL_MODEL = "anthropic.claude-3-7-sonnet-20250219-v1:0";
```
### Model Fallback Chain
```java
private static final String[] MODEL_CHAIN = {
"anthropic.claude-sonnet-4-5-20250929-v1:0", // Primary
"anthropic.claude-haiku-4-5-20251001-v1:0", // Fast fallback
"amazon.titan-text-lite-v1" // Cheap fallback
};
```

View File

@@ -0,0 +1,365 @@
# Testing Strategies
## Unit Testing
### Mocking Bedrock Clients
```java
@ExtendWith(MockitoExtension.class)
class BedrockServiceTest {
@Mock
private BedrockRuntimeClient bedrockRuntimeClient;
@InjectMocks
private BedrockAIService aiService;
@Test
void shouldGenerateTextWithClaude() {
// Arrange
String modelId = "anthropic.claude-3-sonnet-20240229-v1:0";
String prompt = "Hello, world!";
String expectedResponse = "Hello! How can I help you today?";
InvokeModelResponse mockResponse = InvokeModelResponse.builder()
.body(SdkBytes.fromUtf8String(
"{\"content\":[{\"text\":\"" + expectedResponse + "\"}]}"))
.build();
when(bedrockRuntimeClient.invokeModel(any(InvokeModelRequest.class)))
.thenReturn(mockResponse);
// Act
String result = aiService.generateText(prompt, modelId);
// Assert
assertThat(result).isEqualTo(expectedResponse);
verify(bedrockRuntimeClient).invokeModel(argThat(request ->
request.modelId().equals(modelId)));
}
@Test
void shouldHandleThrottling() {
// Arrange
when(bedrockRuntimeClient.invokeModel(any(InvokeModelRequest.class)))
.thenThrow(ThrottlingException.builder()
.message("Rate limit exceeded")
.build());
// Act & Assert
assertThatThrownBy(() -> aiService.generateText("test"))
.isInstanceOf(RuntimeException.class)
.hasMessageContaining("Rate limit exceeded");
}
}
```
### Testing Error Conditions
```java
@Test
void shouldHandleInvalidModelId() {
String invalidModelId = "invalid.model.id";
String prompt = "test";
when(bedrockRuntimeClient.invokeModel(any(InvokeModelRequest.class)))
.thenThrow(ValidationException.builder()
.message("Invalid model identifier")
.build());
assertThatThrownBy(() -> aiService.generateText(prompt, invalidModelId))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Invalid model identifier");
}
```
### Testing Multiple Models
```java
@ParameterizedTest
@EnumSource(ModelProvider.class)
void shouldSupportAllModels(ModelProvider modelProvider) {
String prompt = "Hello";
String modelId = modelProvider.getModelId();
String expectedResponse = "Response";
InvokeModelResponse mockResponse = InvokeModelResponse.builder()
.body(SdkBytes.fromUtf8String(createMockResponse(modelProvider, expectedResponse)))
.build();
when(bedrockRuntimeClient.invokeModel(any(InvokeModelRequest.class)))
.thenReturn(mockResponse);
String result = aiService.generateText(prompt, modelId);
assertThat(result).isEqualTo(expectedResponse);
}
private enum ModelProvider {
CLAUDE("anthropic.claude-3-sonnet-20240229-v1:0"),
LLAMA("meta.llama3-70b-instruct-v1:0"),
TITAN("amazon.titan-text-express-v1");
private final String modelId;
ModelProvider(String modelId) {
this.modelId = modelId;
}
public String getModelId() {
return modelId;
}
}
```
## Integration Testing
### Testcontainers Integration
```java
@Testcontainers
@SpringBootTest(classes = BedrockConfiguration.class)
@ActiveProfiles("test")
class BedrockIntegrationTest {
@Container
static LocalStackContainer localStack = new LocalStackContainer(
DockerImageName.parse("localstack/localstack:latest"))
.withServices(AWSService BEDROCK_RUNTIME)
.withEnv("DEFAULT_REGION", "us-east-1");
@Autowired
private BedrockRuntimeClient bedrockRuntimeClient;
@Test
void shouldConnectToLocalStack() {
assertThat(bedrockRuntimeClient).isNotNull();
}
@Test
void shouldListFoundationModels() {
ListFoundationModelsResponse response =
bedrockRuntimeClient.listFoundationModels();
assertThat(response.modelSummaries()).isNotEmpty();
}
}
```
### LocalStack Configuration
```java
@Configuration
public class LocalStackConfig {
@Value("${localstack.enabled:true}")
private boolean localStackEnabled;
@Bean
@ConditionalOnProperty(name = "localstack.enabled", havingValue = "true")
public AwsCredentialsProvider localStackCredentialsProvider() {
return StaticCredentialsProvider.create(
new AwsBasicCredentialsAccessKey("test", "test"));
}
@Bean
@ConditionalOnProperty(name = "localstack.enabled", havingValue = "true")
public BedrockRuntimeClient localStackBedrockRuntimeClient(
AwsCredentialsProvider credentialsProvider) {
return BedrockRuntimeClient.builder()
.credentialsProvider(credentialsProvider)
.endpointOverride(localStack.getEndpoint())
.region(Region.US_EAST_1)
.build();
}
}
```
### Performance Testing
```java
@Test
void shouldPerformWithinTimeLimit() {
String prompt = "Performance test prompt";
int iterationCount = 100;
long startTime = System.currentTimeMillis();
for (int i = 0; i < iterationCount; i++) {
InvokeModelResponse response = bedrockRuntimeClient.invokeModel(
request -> request
.modelId("anthropic.claude-3-sonnet-20240229-v1:0")
.body(SdkBytes.fromUtf8String(createPayload(prompt))));
}
long duration = System.currentTimeMillis() - startTime;
double avgTimePerRequest = (double) duration / iterationCount;
assertThat(avgTimePerRequest).isLessThan(5000); // Less than 5 seconds per request
System.out.println("Average response time: " + avgTimePerRequest + "ms");
}
```
## Testing Streaming Responses
### Streaming Handler Testing
```java
@Test
void shouldStreamResponse() throws InterruptedException {
String prompt = "Stream this response";
MockStreamHandler mockHandler = new MockStreamHandler();
InvokeModelWithResponseStreamRequest streamRequest =
InvokeModelWithResponseStreamRequest.builder()
.modelId("anthropic.claude-3-sonnet-20240229-v1:0")
.body(SdkBytes.fromUtf8String(createPayload(prompt)))
.build();
bedrockRuntimeClient.invokeModelWithResponseStream(streamRequest, mockHandler);
// Wait for streaming to complete
mockHandler.awaitCompletion(10, TimeUnit.SECONDS);
assertThat(mockHandler.getStreamedContent()).isNotEmpty();
assertThat(mockHandler.getStreamedContent()).contains(" streamed");
}
private static class MockStreamHandler extends
InvokeModelWithResponseStreamResponseHandler.Visitor {
private final StringBuilder contentBuilder = new StringBuilder();
private final CountDownLatch latch = new CountDownLatch(1);
@Override
public void visit(EventStream eventStream) {
eventStream.forEach(event -> {
if (event instanceof PayloadPart) {
PayloadPart payloadPart = (PayloadPart) event;
String chunk = payloadPart.bytes().asUtf8String();
contentBuilder.append(chunk);
}
});
latch.countDown();
}
public String getStreamedContent() {
return contentBuilder.toString();
}
public void awaitCompletion(long timeout, TimeUnit unit)
throws InterruptedException {
latch.await(timeout, unit);
}
}
```
## Testing Configuration
### Testing Different Regions
```java
@ParameterizedTest
@EnumSource(value = Region.class,
names = {"US_EAST_1", "US_WEST_2", "EU_WEST_1"})
void shouldWorkInAllRegions(Region region) {
BedrockRuntimeClient client = BedrockRuntimeClient.builder()
.region(region)
.build();
assertThat(client).isNotNull();
}
### Testing Authentication
```java
@Test
void shouldUseIamRoleForAuthentication() {
BedrockRuntimeClient client = BedrockRuntimeClient.builder()
.region(Region.US_EAST_1)
.build();
// Test that client can make basic calls
ListFoundationModelsResponse response = client.listFoundationModels();
assertThat(response).isNotNull();
}
```
## Test Data Management
### Test Response Fixtures
```java
public class BedrockTestFixtures {
public static String createClaudeResponse() {
return "{\"content\":[{\"text\":\"Hello! How can I help you today?\"}]}";
}
public static String createLlamaResponse() {
return "{\"generation\":\"Hello! How can I assist you?\"}";
}
public static String createTitanResponse() {
return "{\"results\":[{\"outputText\":\"Hello! How can I help?\"}]}";
}
public static String createPayload(String prompt) {
return new JSONObject()
.put("anthropic_version", "bedrock-2023-05-31")
.put("max_tokens", 1000)
.put("messages", new JSONObject[]{
new JSONObject()
.put("role", "user")
.put("content", prompt)
})
.toString();
}
}
```
### Integration Test Suite
```java
@Suite
@SelectClasses({
BedrockAIServiceTest.class,
BedrockConfigurationTest.class,
BedrockStreamingTest.class,
BedrockErrorHandlingTest.class
})
public class BedrockTestSuite {
// Integration test suite for all Bedrock functionality
}
```
## Testing Guidelines
### Unit Testing Best Practices
1. **Mock External Dependencies:** Always mock AWS SDK clients in unit tests
2. **Test Error Scenarios:** Include tests for throttling, validation errors, and network issues
3. **Parameterized Tests:** Test multiple models and configurations efficiently
4. **Performance Assertions:** Include basic performance benchmarks
5. **Test Data Fixtures:** Reuse test response data across tests
### Integration Testing Best Practices
1. **Use LocalStack:** Test against LocalStack for local development
2. **Test Multiple Regions:** Verify functionality across different AWS regions
3. **Test Edge Cases:** Include timeout, retry, and concurrent request scenarios
4. **Monitor Performance:** Track response times and error rates
5. **Clean Up Resources:** Ensure proper cleanup after integration tests
### Testing Configuration
```properties
# application-test.properties
localstack.enabled=true
aws.region=us-east-1
bedrock.timeout=5000
bedrock.retry.max-attempts=3
```