AWS Bedrock integration for LangChain4j enabling Java applications to interact with various LLM providers through a unified interface
Handle common errors and implement retry strategies.
import dev.langchain4j.exception.RateLimitException;
import dev.langchain4j.exception.QuotaExceededException;
import dev.langchain4j.exception.UnauthorizedException;
import dev.langchain4j.exception.ValidationException;
import dev.langchain4j.exception.ModelNotFoundException;import dev.langchain4j.model.bedrock.BedrockChatModel;
BedrockChatModel model = BedrockChatModel.builder()
.modelId("anthropic.claude-3-5-sonnet-20241022-v2:0")
.maxRetries(3) // Retry up to 3 times on transient failures
.build();try {
ChatResponse response = model.chat(request);
} catch (RateLimitException e) {
// Handle rate limiting (429 errors)
System.err.println("Rate limited. Retry after: " + e.getRetryAfter());
// Implement exponential backoff
} catch (QuotaExceededException e) {
// Handle quota exceeded
System.err.println("Quota exceeded: " + e.getMessage());
} catch (UnauthorizedException e) {
// Handle authentication errors
System.err.println("Invalid credentials: " + e.getMessage());
} catch (ValidationException e) {
// Handle invalid request parameters
System.err.println("Invalid request: " + e.getMessage());
} catch (ModelNotFoundException e) {
// Handle model not found
System.err.println("Model not available: " + e.getMessage());
} catch (Exception e) {
// Handle other errors
System.err.println("Error: " + e.getMessage());
}public class RetryHandler {
private static final int MAX_RETRIES = 5;
private static final long INITIAL_DELAY_MS = 1000;
public ChatResponse chatWithRetry(BedrockChatModel model, ChatRequest request) {
int attempt = 0;
long delay = INITIAL_DELAY_MS;
while (attempt < MAX_RETRIES) {
try {
return model.chat(request);
} catch (RateLimitException e) {
attempt++;
if (attempt >= MAX_RETRIES) {
throw e;
}
try {
Thread.sleep(delay);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException(ie);
}
delay *= 2; // Exponential backoff
}
}
throw new RuntimeException("Max retries exceeded");
}
}import dev.langchain4j.model.output.FinishReason;
ChatResponse response = model.chat(request);
FinishReason finishReason = response.metadata().finishReason();
switch (finishReason) {
case STOP:
// Normal completion
System.out.println("Generation completed successfully");
break;
case LENGTH:
// Hit max token limit
System.out.println("Response truncated due to token limit");
System.out.println("Consider increasing maxOutputTokens");
break;
case CONTENT_FILTER:
// Blocked by content filter or guardrail
System.out.println("Response blocked by content filter");
break;
case TOOL_EXECUTION:
// Model called a tool
System.out.println("Model requested tool execution");
break;
default:
System.out.println("Unknown finish reason: " + finishReason);
}import software.amazon.awssdk.services.bedrockruntime.model.ThrottlingException;
import software.amazon.awssdk.services.bedrockruntime.model.ValidationException;
import software.amazon.awssdk.services.bedrockruntime.model.AccessDeniedException;
import software.amazon.awssdk.services.bedrockruntime.model.ResourceNotFoundException;
try {
ChatResponse response = model.chat(request);
} catch (ThrottlingException e) {
// Rate limiting
System.err.println("Throttled: " + e.getMessage());
} catch (ValidationException e) {
// Invalid request
System.err.println("Validation error: " + e.getMessage());
} catch (AccessDeniedException e) {
// Insufficient permissions
System.err.println("Access denied: " + e.getMessage());
} catch (ResourceNotFoundException e) {
// Model or resource not found
System.err.println("Resource not found: " + e.getMessage());
}import java.time.Duration;
BedrockChatModel model = BedrockChatModel.builder()
.modelId("anthropic.claude-3-5-sonnet-20241022-v2:0")
.timeout(Duration.ofSeconds(120)) // 2-minute timeout
.build();
try {
ChatResponse response = model.chat(request);
} catch (java.util.concurrent.TimeoutException e) {
System.err.println("Request timed out");
}public class BedrockErrorHandler {
private final Logger logger = LoggerFactory.getLogger(BedrockErrorHandler.class);
public ChatResponse handleChat(BedrockChatModel model, ChatRequest request) {
try {
return model.chat(request);
} catch (RateLimitException e) {
logger.warn("Rate limited, retrying after {}ms", e.getRetryAfter());
return retryWithBackoff(model, request);
} catch (QuotaExceededException e) {
logger.error("Quota exceeded", e);
throw new ServiceUnavailableException("API quota exceeded");
} catch (UnauthorizedException e) {
logger.error("Authentication failed", e);
throw new SecurityException("Invalid AWS credentials");
} catch (ValidationException e) {
logger.error("Invalid request", e);
throw new IllegalArgumentException("Request validation failed: " + e.getMessage());
} catch (ModelNotFoundException e) {
logger.error("Model not found", e);
throw new IllegalStateException("Requested model not available");
} catch (Exception e) {
logger.error("Unexpected error", e);
throw new RuntimeException("Chat request failed", e);
}
}
private ChatResponse retryWithBackoff(BedrockChatModel model, ChatRequest request) {
// Implement retry logic
return null;
}
}Related: