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/04 11:37:13 UTC

(camel) branch main updated: CAMEL-20511 - Camel-AWS-Bedrock: Support Amazon Titan Embeddings G1 Model (#13375)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 1b0b17ead96 CAMEL-20511 - Camel-AWS-Bedrock: Support Amazon Titan Embeddings G1 Model (#13375)
1b0b17ead96 is described below

commit 1b0b17ead960e59f1fa20b07442887317f0f4261
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Mon Mar 4 12:37:07 2024 +0100

    CAMEL-20511 - Camel-AWS-Bedrock: Support Amazon Titan Embeddings G1 Model (#13375)
    
    * CAMEL-20511 - Camel-AWS-Bedrock: Support Amazon Titan Embeddings G1 Model
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
    
    * CAMEL-20511 - Camel-AWS-Bedrock: Support Amazon Titan Embeddings G1 Model
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
 .../camel/catalog/components/aws-bedrock.json      |  4 +-
 .../camel/component/aws2/bedrock/aws-bedrock.json  |  4 +-
 .../component/aws2/bedrock/BedrockModels.java      |  4 +-
 .../component/aws2/bedrock/BedrockOperations.java  |  4 +-
 .../component/aws2/bedrock/BedrockProducer.java    | 48 ++++++++++++++++++++++
 .../bedrock/integration/BedrockProducerIT.java     | 23 +++++++++++
 6 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
index 02b0151a67e..be5a902c16b 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
@@ -26,7 +26,7 @@
     "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" },
     "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
     "modelId": { "index": 2, "kind": "property", "displayName": "Model Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Define the model Id we are going to use" },
-    "operation": { "index": 3, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description" [...]
+    "operation": { "index": 3, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel", "invokeEmbeddingsModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "conf [...]
     "overrideEndpoint": { "index": 4, "kind": "property", "displayName": "Override Endpoint", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Set the need for overriding the endpoint. This option needs to be used in combina [...]
     "pojoRequest": { "index": 5, "kind": "property", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
     "profileCredentialsName": { "index": 6, "kind": "property", "displayName": "Profile Credentials Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter wi [...]
@@ -55,7 +55,7 @@
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Logical name" },
     "modelId": { "index": 1, "kind": "parameter", "displayName": "Model Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Define the model Id we are going to use" },
-    "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description [...]
+    "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel", "invokeEmbeddingsModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "con [...]
     "overrideEndpoint": { "index": 3, "kind": "parameter", "displayName": "Override Endpoint", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Set the need for overriding the endpoint. This option needs to be used in combin [...]
     "pojoRequest": { "index": 4, "kind": "parameter", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
     "profileCredentialsName": { "index": 5, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter w [...]
diff --git a/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/aws-bedrock.json b/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/aws-bedrock.json
index 02b0151a67e..be5a902c16b 100644
--- a/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/aws-bedrock.json
+++ b/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/aws-bedrock.json
@@ -26,7 +26,7 @@
     "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" },
     "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
     "modelId": { "index": 2, "kind": "property", "displayName": "Model Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Define the model Id we are going to use" },
-    "operation": { "index": 3, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description" [...]
+    "operation": { "index": 3, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel", "invokeEmbeddingsModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "conf [...]
     "overrideEndpoint": { "index": 4, "kind": "property", "displayName": "Override Endpoint", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Set the need for overriding the endpoint. This option needs to be used in combina [...]
     "pojoRequest": { "index": 5, "kind": "property", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
     "profileCredentialsName": { "index": 6, "kind": "property", "displayName": "Profile Credentials Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter wi [...]
@@ -55,7 +55,7 @@
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Logical name" },
     "modelId": { "index": 1, "kind": "parameter", "displayName": "Model Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Define the model Id we are going to use" },
-    "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description [...]
+    "operation": { "index": 2, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.aws2.bedrock.BedrockOperations", "enum": [ "invokeTextModel", "invokeImageModel", "invokeEmbeddingsModel" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "con [...]
     "overrideEndpoint": { "index": 3, "kind": "parameter", "displayName": "Override Endpoint", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "Set the need for overriding the endpoint. This option needs to be used in combin [...]
     "pojoRequest": { "index": 4, "kind": "parameter", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
     "profileCredentialsName": { "index": 5, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "configurationClass": "org.apache.camel.component.aws2.bedrock.BedrockConfiguration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter w [...]
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 c1cce5e044c..e4c27372a9f 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
@@ -20,7 +20,9 @@ public enum BedrockModels {
 
     TITAN_TEXT_EXPRESS_V1("amazon.titan-text-express-v1"),
     TITAN_TEXT_LITE_V1("amazon.titan-text-lite-v1"),
-    TITAN_IMAGE_GENERATOR_V1("amazon.titan-image-generator-v1");
+    TITAN_IMAGE_GENERATOR_V1("amazon.titan-image-generator-v1"),
+
+    TITAN_EMBEDDINGS_G1("amazon.titan-embed-text-v1");
 
     public final String model;
 
diff --git a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockOperations.java b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockOperations.java
index e99f0e08f9e..0c0ff54ff6a 100644
--- a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockOperations.java
+++ b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockOperations.java
@@ -20,5 +20,7 @@ public enum BedrockOperations {
 
     invokeTextModel,
 
-    invokeImageModel
+    invokeImageModel,
+
+    invokeEmbeddingsModel
 }
diff --git a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockProducer.java b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockProducer.java
index 584a2faef22..bcf73b0c804 100644
--- a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockProducer.java
+++ b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/BedrockProducer.java
@@ -56,6 +56,9 @@ public class BedrockProducer extends DefaultProducer {
             case invokeImageModel:
                 invokeImageModel(getEndpoint().getBedrockRuntimeClient(), exchange);
                 break;
+            case invokeEmbeddingsModel:
+                invokeEmbeddingsModel(getEndpoint().getBedrockRuntimeClient(), exchange);
+                break;
             default:
                 throw new IllegalArgumentException("Unsupported operation");
         }
@@ -178,6 +181,51 @@ public class BedrockProducer extends DefaultProducer {
         }
     }
 
+    private void invokeEmbeddingsModel(BedrockRuntimeClient bedrockRuntimeClient, Exchange exchange)
+            throws InvalidPayloadException {
+        if (getConfiguration().isPojoRequest()) {
+            Object payload = exchange.getMessage().getMandatoryBody();
+            if (payload instanceof InvokeModelRequest) {
+                InvokeModelResponse result;
+                try {
+                    result = bedrockRuntimeClient.invokeModel((InvokeModelRequest) payload);
+                } catch (AwsServiceException ase) {
+                    LOG.trace("Invoke Image Model command returned the error code {}", ase.awsErrorDetails().errorCode());
+                    throw ase;
+                }
+                Message message = getMessageForResponse(exchange);
+                message.setBody(result);
+            }
+        } else {
+            InvokeModelRequest.Builder builder = InvokeModelRequest.builder();
+            if (ObjectHelper.isNotEmpty(exchange.getMessage().getHeader(BedrockConstants.MODEL_CONTENT_TYPE))) {
+                String contentType = exchange.getIn().getHeader(BedrockConstants.MODEL_CONTENT_TYPE, String.class);
+                builder.contentType(contentType);
+            } else {
+                throw new IllegalArgumentException("Model Content Type must be specified");
+            }
+            if (ObjectHelper.isNotEmpty(exchange.getMessage().getHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE))) {
+                String acceptContentType = exchange.getIn().getHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, String.class);
+                builder.accept(acceptContentType);
+            } else {
+                throw new IllegalArgumentException("Model Accept Content Type must be specified");
+            }
+            InvokeModelRequest request = builder
+                    .body(SdkBytes.fromUtf8String(String.valueOf(exchange.getMessage().getBody())))
+                    .modelId(getConfiguration().getModelId())
+                    .build();
+            InvokeModelResponse result;
+            try {
+                result = bedrockRuntimeClient.invokeModel(request);
+            } catch (AwsServiceException ase) {
+                LOG.trace("Invoke Model command returned the error code {}", ase.awsErrorDetails().errorCode());
+                throw ase;
+            }
+            Message message = getMessageForResponse(exchange);
+            message.setBody(result);
+        }
+    }
+
     private static void setBase64Image(InvokeModelResponse result, Message message) throws JsonProcessingException {
         ObjectMapper mapper = new ObjectMapper();
         JsonNode jsonString = mapper.readTree(result.body().asUtf8String());
diff --git a/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/integration/BedrockProducerIT.java b/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/integration/BedrockProducerIT.java
index 05d34f2479c..8c192b239b8 100644
--- a/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/integration/BedrockProducerIT.java
+++ b/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/integration/BedrockProducerIT.java
@@ -134,6 +134,24 @@ class BedrockProducerIT extends CamelTestSupport {
         MockEndpoint.assertIsSatisfied(context);
     }
 
+    @Test
+    public void testInvokeTitanEmbeddingsModel() throws InterruptedException {
+
+        result.expectedMessageCount(1);
+        final Exchange result = template.send("direct:send_titan_embeddings", exchange -> {
+            ObjectMapper mapper = new ObjectMapper();
+            ObjectNode rootNode = mapper.createObjectNode();
+            rootNode.putIfAbsent("inputText",
+                    new TextNode("A Sci-fi camel running in the desert"));
+
+            exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode));
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json");
+            exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "*/*");
+        });
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
@@ -156,6 +174,11 @@ class BedrockProducerIT extends CamelTestSupport {
                         .unmarshal().base64()
                         .setHeader("CamelFileName", simple("image-${random(128)}.png")).to("file:target/generated_images")
                         .to(result);
+
+                from("direct:send_titan_embeddings")
+                        .to("aws-bedrock:label?accessKey=RAW({{aws.manual.access.key}})&secretKey=RAW({{aws.manual.secret.key}}&region=us-east-1&operation=invokeEmbeddingsModel&modelId="
+                            + BedrockModels.TITAN_EMBEDDINGS_G1.model)
+                        .to(result);
             }
         };
     }