From 5738cb056827ea7f91b29b06c29032bbd100777e Mon Sep 17 00:00:00 2001 From: SylvestrePinget <126336487+tenpigs267@users.noreply.github.com> Date: Wed, 5 Feb 2025 16:58:43 +0100 Subject: [PATCH] Bedrock : add example for the BedrockChatModel converseAPI implementation (#140) discussed in https://github.com/langchain4j/langchain4j/pull/2404 --- .../converse/BedrockChatModelExample.java | 106 ++++++++++++++++++ .../{ => invoke}/BedrockChatModelExample.java | 2 + .../BedrockStreamingChatModelExample.java | 2 + .../src/main/resources/test-file.pdf | Bin 0 -> 22958 bytes 4 files changed, 110 insertions(+) create mode 100644 bedrock-examples/src/main/java/converse/BedrockChatModelExample.java rename bedrock-examples/src/main/java/{ => invoke}/BedrockChatModelExample.java (98%) rename bedrock-examples/src/main/java/{ => invoke}/BedrockStreamingChatModelExample.java (99%) create mode 100644 bedrock-examples/src/main/resources/test-file.pdf diff --git a/bedrock-examples/src/main/java/converse/BedrockChatModelExample.java b/bedrock-examples/src/main/java/converse/BedrockChatModelExample.java new file mode 100644 index 00000000..06ee335d --- /dev/null +++ b/bedrock-examples/src/main/java/converse/BedrockChatModelExample.java @@ -0,0 +1,106 @@ +package converse; + +import dev.langchain4j.data.message.ImageContent; +import dev.langchain4j.data.message.PdfFileContent; +import dev.langchain4j.data.message.TextContent; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.model.bedrock.BedrockChatModel; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.request.ChatRequest; +import dev.langchain4j.model.chat.request.ChatRequestParameters; +import dev.langchain4j.model.chat.response.ChatResponse; + +import java.nio.file.Paths; + +public class BedrockChatModelExample { + + static class Simple_Prompt { + + public static void main(String[] args) { + + // For authentication, set the following environment variables: + // AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY + // More info on creating the API keys: + // https://docs.aws.amazon.com/bedrock/latest/userguide/api-setup.html + ChatLanguageModel chatModel = BedrockChatModel.builder() + .modelId("us.amazon.nova-lite-v1:0") + .build(); + + String joke = chatModel.chat("Tell me a joke about Java"); + + System.out.println(joke); + } + } + + static class Image_Inputs { + + public static void main(String[] args) { + + ChatLanguageModel chatModel = BedrockChatModel.builder() + .modelId("us.amazon.nova-lite-v1:0") + .build(); + + UserMessage userMessage = UserMessage.from( + TextContent.from("What do you see?"), + ImageContent.from("https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png") + ); + + ChatResponse chatResponse = chatModel.chat(userMessage); + + System.out.println(chatResponse.aiMessage().text()); + } + } + + static class PDF_Inputs { + + public static void main(String[] args) { + + ChatLanguageModel chatModel = BedrockChatModel.builder() + .modelId("us.amazon.nova-lite-v1:0") + .build(); + + UserMessage userMessage = UserMessage.from( + TextContent.from("Summarize attached document"), + PdfFileContent.from(Paths.get("bedrock-examples/src/main/resources/test-file.pdf").toUri()) + ); + + ChatResponse chatResponse = chatModel.chat(userMessage); + + System.out.println(chatResponse.aiMessage().text()); + } + } + + static class Setting_Common_ChatRequestParameters { + + public static void main(String[] args) { + + ChatRequestParameters defaultParameters = ChatRequestParameters.builder() + .temperature(0.7) + .maxOutputTokens(100) + // there are many more common parameters, see ChatRequestParameters for more info + .build(); + + ChatLanguageModel chatModel = BedrockChatModel.builder() + .modelId("us.amazon.nova-lite-v1:0") + .defaultRequestParameters(defaultParameters) + .logRequests(true) + .build(); + + ChatRequestParameters parameters = ChatRequestParameters.builder() + // Model choice can be overridden with request parameter + .modelName("anthropic.claude-3-haiku-20240307-v1:0") + .temperature(1.0) + .maxOutputTokens(50) + .build(); + + ChatRequest chatRequest = ChatRequest.builder() + .messages(UserMessage.from("Tell me a funny story about Java")) + .parameters(parameters) // merges with and overrides default parameters + .build(); + + ChatResponse chatResponse = chatModel.chat(chatRequest); + + System.out.println(chatResponse); + } + } +} diff --git a/bedrock-examples/src/main/java/BedrockChatModelExample.java b/bedrock-examples/src/main/java/invoke/BedrockChatModelExample.java similarity index 98% rename from bedrock-examples/src/main/java/BedrockChatModelExample.java rename to bedrock-examples/src/main/java/invoke/BedrockChatModelExample.java index 9643e865..96c3c63c 100644 --- a/bedrock-examples/src/main/java/BedrockChatModelExample.java +++ b/bedrock-examples/src/main/java/invoke/BedrockChatModelExample.java @@ -1,3 +1,5 @@ +package invoke; + import dev.langchain4j.model.bedrock.BedrockAnthropicMessageChatModel; import dev.langchain4j.model.chat.ChatLanguageModel; import software.amazon.awssdk.regions.Region; diff --git a/bedrock-examples/src/main/java/BedrockStreamingChatModelExample.java b/bedrock-examples/src/main/java/invoke/BedrockStreamingChatModelExample.java similarity index 99% rename from bedrock-examples/src/main/java/BedrockStreamingChatModelExample.java rename to bedrock-examples/src/main/java/invoke/BedrockStreamingChatModelExample.java index a2d300a2..cdd76b3c 100644 --- a/bedrock-examples/src/main/java/BedrockStreamingChatModelExample.java +++ b/bedrock-examples/src/main/java/invoke/BedrockStreamingChatModelExample.java @@ -1,3 +1,5 @@ +package invoke; + import dev.langchain4j.model.bedrock.BedrockAnthropicMessageChatModel; import dev.langchain4j.model.bedrock.BedrockAnthropicStreamingChatModel; import dev.langchain4j.model.chat.StreamingChatLanguageModel; diff --git a/bedrock-examples/src/main/resources/test-file.pdf b/bedrock-examples/src/main/resources/test-file.pdf new file mode 100644 index 0000000000000000000000000000000000000000..920f1fceed533d54e2908d0f71f25b79eda5529d GIT binary patch literal 22958 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Ν=4^A#qpYcd={I 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 X{p@`FejhUl38*-fl8;ZrP?PdspsZ8$ literal 0 HcmV?d00001