You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2024/03/13 09:42:40 UTC

(camel) branch CAMEL-20560 created (now b3d453b4ed3)

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a change to branch CAMEL-20560
in repository https://gitbox.apache.org/repos/asf/camel.git


      at b3d453b4ed3 CAMEL-20560 - Camel-AWS-Bedrock: Support Anthropic models

This branch includes the following new commits:

     new b3d453b4ed3 CAMEL-20560 - Camel-AWS-Bedrock: Support Anthropic models

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(camel) 01/01: CAMEL-20560 - Camel-AWS-Bedrock: Support Anthropic models

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch CAMEL-20560
in repository https://gitbox.apache.org/repos/asf/camel.git

commit b3d453b4ed3a4d19bc5bf3195f8ccd80f63ca075
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Mar 13 10:30:23 2024 +0100

    CAMEL-20560 - Camel-AWS-Bedrock: Support Anthropic models
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
 .../component/aws2/bedrock/BedrockModels.java      |   5 +-
 .../aws2/bedrock/runtime/BedrockProducer.java      |  26 ++++
 .../runtime/integration/BedrockProducerIT.java     | 150 ++++++++++++++++++++-
 3 files changed, 174 insertions(+), 7 deletions(-)

diff --git a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockModels.java b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockModels.java
index ef994e22ff5..d8d9bf561a9 100644
--- a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockModels.java
+++ b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockModels.java
@@ -25,8 +25,9 @@ public enum BedrockModels {
     JURASSIC2_ULTRA("ai21.j2-ultra-v1"),
     JURASSIC2_MID("ai21.j2-mid-v1"),
     ANTROPHIC_CLAUDE_INSTANT_V1("anthropic.claude-instant-v1"),
-    ANTROPHIC_CLAUDE_INSTANT_V2("anthropic.claude-v2"),
-    ANTROPHIC_CLAUDE_INSTANT_V2_1("anthropic.claude-v2:1");
+    ANTROPHIC_CLAUDE_V2("anthropic.claude-v2"),
+    ANTROPHIC_CLAUDE_V2_1("anthropic.claude-v2:1"),
+    ANTROPHIC_CLAUDE_V3("anthropic.claude-3-sonnet-20240229-v1:0");
 
     public final String model;
 
diff --git a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
index e79c7138234..e553972684f 100644
--- a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
+++ b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
@@ -242,6 +242,20 @@ public class BedrockProducer extends DefaultProducer {
                     throw new RuntimeException(e);
                 }
             }
+            case "anthropic.claude-instant-v1", "anthropic.claude-v2", "anthropic.claude-v2:1" -> {
+                try {
+                    setAnthropicText(result, message);
+                } catch (JsonProcessingException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            case "anthropic.claude-3-sonnet-20240229-v1:0" -> {
+                try {
+                    setAnthropicV3Text(result, message);
+                } catch (JsonProcessingException e) {
+                    throw new RuntimeException(e);
+                }
+            }
             default -> throw new IllegalStateException("Unexpected value: " + getConfiguration().getModelId());
         }
     }
@@ -256,6 +270,18 @@ public class BedrockProducer extends DefaultProducer {
         message.setBody(jsonString.get("completions"));
     }
 
+    private void setAnthropicText(InvokeModelResponse result, Message message) throws JsonProcessingException {
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode jsonString = mapper.readTree(result.body().asUtf8String());
+        message.setBody(jsonString.get("completion"));
+    }
+
+    private void setAnthropicV3Text(InvokeModelResponse result, Message message) throws JsonProcessingException {
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode jsonString = mapper.readTree(result.body().asUtf8String());
+        message.setBody(jsonString);
+    }
+
     public static Message getMessageForResponse(final Exchange exchange) {
         return exchange.getMessage();
     }
diff --git a/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/integration/BedrockProducerIT.java b/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/integration/BedrockProducerIT.java
index aa2044461e3..bfe93173df8 100644
--- a/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/integration/BedrockProducerIT.java
+++ b/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/integration/BedrockProducerIT.java
@@ -17,10 +17,7 @@
 package org.apache.camel.component.aws2.bedrock.runtime.integration;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.IntNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.fasterxml.jackson.databind.node.TextNode;
+import com.fasterxml.jackson.databind.node.*;
 import org.apache.camel.EndpointInject;
 import org.apache.camel.Exchange;
 import org.apache.camel.ProducerTemplate;
@@ -220,6 +217,125 @@ class BedrockProducerIT extends CamelTestSupport {
         MockEndpoint.assertIsSatisfied(context);
     }
 
+    @Test
+    public void testInvokeAnthropicV1Model() throws InterruptedException {
+
+        result.expectedMessageCount(1);
+        final Exchange result = template.send("direct:send_anthropic_v1_model", exchange -> {
+            ObjectMapper mapper = new ObjectMapper();
+            ObjectNode rootNode = mapper.createObjectNode();
+            rootNode.putIfAbsent("prompt",
+                    new TextNode("Human: Can you tell the history of Mayflower? \\n\\Assistant:"));
+
+            ArrayNode stopSequences = mapper.createArrayNode();
+            stopSequences.add("Human:");
+            rootNode.putIfAbsent("max_tokens_to_sample", new IntNode(300));
+            rootNode.putIfAbsent("stop_sequences", stopSequences);
+            rootNode.putIfAbsent("temperature", new DoubleNode(0.5));
+            rootNode.putIfAbsent("top_p", new IntNode(1));
+            rootNode.putIfAbsent("top_k", new IntNode(250));
+            rootNode.putIfAbsent("anthropic_version", new TextNode("bedrock-2023-05-31"));
+
+            exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode));
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json");
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json");
+        });
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Test
+    public void testInvokeAnthropicV2Model() throws InterruptedException {
+
+        result.expectedMessageCount(1);
+        final Exchange result = template.send("direct:send_anthropic_v2_model", exchange -> {
+            ObjectMapper mapper = new ObjectMapper();
+            ObjectNode rootNode = mapper.createObjectNode();
+            rootNode.putIfAbsent("prompt",
+                    new TextNode("Human: Can you tell the history of Mayflower? \\n\\Assistant:"));
+
+            ArrayNode stopSequences = mapper.createArrayNode();
+            stopSequences.add("Human:");
+            rootNode.putIfAbsent("max_tokens_to_sample", new IntNode(300));
+            rootNode.putIfAbsent("stop_sequences", stopSequences);
+            rootNode.putIfAbsent("temperature", new DoubleNode(0.5));
+            rootNode.putIfAbsent("top_p", new IntNode(1));
+            rootNode.putIfAbsent("top_k", new IntNode(250));
+            rootNode.putIfAbsent("anthropic_version", new TextNode("bedrock-2023-05-31"));
+
+            exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode));
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json");
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json");
+        });
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Test
+    public void testInvokeAnthropicV21Model() throws InterruptedException {
+
+        result.expectedMessageCount(1);
+        final Exchange result = template.send("direct:send_anthropic_v21_model", exchange -> {
+            ObjectMapper mapper = new ObjectMapper();
+            ObjectNode rootNode = mapper.createObjectNode();
+            rootNode.putIfAbsent("prompt",
+                    new TextNode("Human: Can you tell the history of Mayflower? \\n\\Assistant:"));
+
+            ArrayNode stopSequences = mapper.createArrayNode();
+            stopSequences.add("Human:");
+            rootNode.putIfAbsent("max_tokens_to_sample", new IntNode(300));
+            rootNode.putIfAbsent("stop_sequences", stopSequences);
+            rootNode.putIfAbsent("temperature", new DoubleNode(0.5));
+            rootNode.putIfAbsent("top_p", new IntNode(1));
+            rootNode.putIfAbsent("top_k", new IntNode(250));
+            rootNode.putIfAbsent("anthropic_version", new TextNode("bedrock-2023-05-31"));
+
+            exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode));
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json");
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json");
+        });
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Test
+    public void testInvokeAnthropicV3Model() throws InterruptedException {
+
+        result.expectedMessageCount(1);
+        final Exchange result = template.send("direct:send_anthropic_v3_model", exchange -> {
+            ObjectMapper mapper = new ObjectMapper();
+            ObjectNode rootNode = mapper.createObjectNode();
+
+            ArrayNode messages = mapper.createArrayNode();
+
+            ObjectNode element = mapper.createObjectNode();
+            element.putIfAbsent("role", new TextNode("user"));
+
+            ArrayNode content = mapper.createArrayNode();
+
+            ObjectNode textContent = mapper.createObjectNode();
+
+            textContent.putIfAbsent("type", new TextNode("text"));
+            textContent.putIfAbsent("text", new TextNode("Can you tell the history of Mayflower?"));
+
+            content.add(textContent);
+
+            element.putIfAbsent("content", content);
+
+            messages.add(element);
+
+            rootNode.putIfAbsent("messages", messages);
+            rootNode.putIfAbsent("max_tokens", new IntNode(1000));
+            rootNode.putIfAbsent("anthropic_version", new TextNode("bedrock-2023-05-31"));
+
+            exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode));
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json");
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json");
+        });
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
@@ -257,12 +373,36 @@ class BedrockProducerIT extends CamelTestSupport {
                         .to(result);
 
                 from("direct:send_jurassic2_mid_model")
-                        .to("aws-bedrock:label?accessKey=RAW({{aws.manual.access.key}})&secretKey=RAW({{aws.manual.secret.key}}&region=us-east-1&operation=invokeTextModel&modelId="
+                        .to("aws-bedrock:label?useDefaultCredentialsProvider=true&region=us-east-1&operation=invokeTextModel&modelId="
                             + BedrockModels.JURASSIC2_MID.model)
                         .split(body())
                         .transform().jq(".data.text")
                         .log("Completions: ${body}")
                         .to(result);
+
+                from("direct:send_anthropic_v1_model")
+                        .to("aws-bedrock:label?accessKey=RAW({{aws.manual.access.key}})&secretKey=RAW({{aws.manual.secret.key}}&region=us-east-1&operation=invokeTextModel&modelId="
+                            + BedrockModels.ANTROPHIC_CLAUDE_INSTANT_V1.model)
+                        .log("${body}")
+                        .to(result);
+
+                from("direct:send_anthropic_v2_model")
+                        .to("aws-bedrock:label?accessKey=RAW({{aws.manual.access.key}})&secretKey=RAW({{aws.manual.secret.key}}&region=us-east-1&operation=invokeTextModel&modelId="
+                            + BedrockModels.ANTROPHIC_CLAUDE_V2.model)
+                        .log("${body}")
+                        .to(result);
+
+                from("direct:send_anthropic_v21_model")
+                        .to("aws-bedrock:label?accessKey=RAW({{aws.manual.access.key}})&secretKey=RAW({{aws.manual.secret.key}}&region=us-east-1&operation=invokeTextModel&modelId="
+                            + BedrockModels.ANTROPHIC_CLAUDE_V2_1.model)
+                        .log("${body}")
+                        .to(result);
+
+                from("direct:send_anthropic_v3_model")
+                        .to("aws-bedrock:label?accessKey=RAW({{aws.manual.access.key}})&secretKey=RAW({{aws.manual.secret.key}}&region=us-east-1&operation=invokeTextModel&modelId="
+                            + BedrockModels.ANTROPHIC_CLAUDE_V3.model)
+                        .log("Completions: ${body}")
+                        .to(result);
             }
         };
     }