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
commit 0b98fed69e8a4506399772d733756a6564bc3662 Author: Andrea Cosentino <anco...@gmail.com> AuthorDate: Mon Apr 29 12:53:13 2024 +0200 CAMEL-20702 - Add a Pinecone component Signed-off-by: Andrea Cosentino <anco...@gmail.com> --- catalog/camel-allcomponents/pom.xml | 5 + components/camel-pinecone/pom.xml | 84 +++++++++ .../PineconeVectorDbComponentConfigurer.java | 70 +++++++ .../PineconeVectorDbConfigurationConfigurer.java | 51 +++++ .../PineconeVectorDbEndpointConfigurer.java | 54 ++++++ .../PineconeVectorDbEndpointUriFactory.java | 74 ++++++++ .../apache/camel/component/pinecone/pinecone.json | 53 ++++++ .../services/org/apache/camel/component.properties | 7 + .../services/org/apache/camel/component/pinecone | 2 + ...omponent.pinecone.PineconeVectorDbConfiguration | 2 + .../org/apache/camel/configurer/pinecone-component | 2 + .../org/apache/camel/configurer/pinecone-endpoint | 2 + .../org/apache/camel/urifactory/pinecone-endpoint | 2 + .../src/main/docs/pinecone-component.adoc | 43 +++++ .../camel/component/pinecone/PineconeVectorDb.java | 74 ++++++++ .../component/pinecone/PineconeVectorDbAction.java | 27 +++ .../pinecone/PineconeVectorDbComponent.java | 71 +++++++ .../pinecone/PineconeVectorDbConfiguration.java | 72 +++++++ .../pinecone/PineconeVectorDbEndpoint.java | 125 ++++++++++++ .../pinecone/PineconeVectorDbProducer.java | 209 +++++++++++++++++++++ .../component/pinecone/it/PineconeComponentIT.java | 113 +++++++++++ .../src/test/resources/log4j2.properties | 35 ++++ parent/pom.xml | 5 + 23 files changed, 1182 insertions(+) diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml index fd69d0aeae4..edec48dad3e 100644 --- a/catalog/camel-allcomponents/pom.xml +++ b/catalog/camel-allcomponents/pom.xml @@ -1362,6 +1362,11 @@ <artifactId>camel-pgevent</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-pinecone</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-platform-http</artifactId> diff --git a/components/camel-pinecone/pom.xml b/components/camel-pinecone/pom.xml new file mode 100644 index 00000000000..132aa4ebdb2 --- /dev/null +++ b/components/camel-pinecone/pom.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>components</artifactId> + <version>4.6.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-pinecone</artifactId> + <packaging>jar</packaging> + <name>Camel :: Pinecone</name> + <description>Camel Pinecone support</description> + + <properties> + <camel.surefire.parallel>true</camel.surefire.parallel> + <camel.surefire.parallel.factor>4</camel.surefire.parallel.factor> + + <!-- Milvus is not available on these platforms --> + <skipITs.ppc64le>true</skipITs.ppc64le> + <skipITs.s390x>true</skipITs.s390x> + <skipTests.ppc64le>true</skipTests.ppc64le> + <skipTests.s390x>true</skipTests.s390x> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-support</artifactId> + </dependency> + + <dependency> + <groupId>dev.langchain4j</groupId> + <artifactId>langchain4j-core</artifactId> + <version>${langchain4j.version}</version> + </dependency> + + <dependency> + <groupId>io.pinecone</groupId> + <artifactId>pinecone-client</artifactId> + <version>1.0.0</version> + </dependency> + + <!-- test dependencies --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>${assertj-version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> diff --git a/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbComponentConfigurer.java b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbComponentConfigurer.java new file mode 100644 index 00000000000..dd6535b3461 --- /dev/null +++ b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbComponentConfigurer.java @@ -0,0 +1,70 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.pinecone; + +import javax.annotation.processing.Generated; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.ExtendedPropertyConfigurerGetter; +import org.apache.camel.spi.PropertyConfigurerGetter; +import org.apache.camel.spi.ConfigurerStrategy; +import org.apache.camel.spi.GeneratedPropertyConfigurer; +import org.apache.camel.util.CaseInsensitiveMap; +import org.apache.camel.support.component.PropertyConfigurerSupport; + +/** + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo") +@SuppressWarnings("unchecked") +public class PineconeVectorDbComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + private org.apache.camel.component.pinecone.PineconeVectorDbConfiguration getOrCreateConfiguration(PineconeVectorDbComponent target) { + if (target.getConfiguration() == null) { + target.setConfiguration(new org.apache.camel.component.pinecone.PineconeVectorDbConfiguration()); + } + return target.getConfiguration(); + } + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + PineconeVectorDbComponent target = (PineconeVectorDbComponent) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true; + case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.pinecone.PineconeVectorDbConfiguration.class, value)); return true; + case "lazystartproducer": + case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + case "token": getOrCreateConfiguration(target).setToken(property(camelContext, java.lang.String.class, value)); return true; + default: return false; + } + } + + @Override + public Class<?> getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": return boolean.class; + case "configuration": return org.apache.camel.component.pinecone.PineconeVectorDbConfiguration.class; + case "lazystartproducer": + case "lazyStartProducer": return boolean.class; + case "token": return java.lang.String.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + PineconeVectorDbComponent target = (PineconeVectorDbComponent) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "autowiredenabled": + case "autowiredEnabled": return target.isAutowiredEnabled(); + case "configuration": return target.getConfiguration(); + case "lazystartproducer": + case "lazyStartProducer": return target.isLazyStartProducer(); + case "token": return getOrCreateConfiguration(target).getToken(); + default: return null; + } + } +} + diff --git a/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbConfigurationConfigurer.java b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbConfigurationConfigurer.java new file mode 100644 index 00000000000..befae42d11c --- /dev/null +++ b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbConfigurationConfigurer.java @@ -0,0 +1,51 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.pinecone; + +import javax.annotation.processing.Generated; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.ExtendedPropertyConfigurerGetter; +import org.apache.camel.spi.PropertyConfigurerGetter; +import org.apache.camel.spi.ConfigurerStrategy; +import org.apache.camel.spi.GeneratedPropertyConfigurer; +import org.apache.camel.util.CaseInsensitiveMap; +import org.apache.camel.component.pinecone.PineconeVectorDbConfiguration; + +/** + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.GenerateConfigurerMojo") +@SuppressWarnings("unchecked") +public class PineconeVectorDbConfigurationConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + org.apache.camel.component.pinecone.PineconeVectorDbConfiguration target = (org.apache.camel.component.pinecone.PineconeVectorDbConfiguration) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "client": target.setClient(property(camelContext, io.pinecone.clients.Pinecone.class, value)); return true; + case "token": target.setToken(property(camelContext, java.lang.String.class, value)); return true; + default: return false; + } + } + + @Override + public Class<?> getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "client": return io.pinecone.clients.Pinecone.class; + case "token": return java.lang.String.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + org.apache.camel.component.pinecone.PineconeVectorDbConfiguration target = (org.apache.camel.component.pinecone.PineconeVectorDbConfiguration) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "client": return target.getClient(); + case "token": return target.getToken(); + default: return null; + } + } +} + diff --git a/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpointConfigurer.java b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpointConfigurer.java new file mode 100644 index 00000000000..5a6b067416e --- /dev/null +++ b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpointConfigurer.java @@ -0,0 +1,54 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.pinecone; + +import javax.annotation.processing.Generated; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.ExtendedPropertyConfigurerGetter; +import org.apache.camel.spi.PropertyConfigurerGetter; +import org.apache.camel.spi.ConfigurerStrategy; +import org.apache.camel.spi.GeneratedPropertyConfigurer; +import org.apache.camel.util.CaseInsensitiveMap; +import org.apache.camel.support.component.PropertyConfigurerSupport; + +/** + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo") +@SuppressWarnings("unchecked") +public class PineconeVectorDbEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + PineconeVectorDbEndpoint target = (PineconeVectorDbEndpoint) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "lazystartproducer": + case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + case "token": target.getConfiguration().setToken(property(camelContext, java.lang.String.class, value)); return true; + default: return false; + } + } + + @Override + public Class<?> getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "lazystartproducer": + case "lazyStartProducer": return boolean.class; + case "token": return java.lang.String.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + PineconeVectorDbEndpoint target = (PineconeVectorDbEndpoint) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "lazystartproducer": + case "lazyStartProducer": return target.isLazyStartProducer(); + case "token": return target.getConfiguration().getToken(); + default: return null; + } + } +} + diff --git a/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpointUriFactory.java b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpointUriFactory.java new file mode 100644 index 00000000000..c0a692cfb59 --- /dev/null +++ b/components/camel-pinecone/src/generated/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpointUriFactory.java @@ -0,0 +1,74 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.component.pinecone; + +import javax.annotation.processing.Generated; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.camel.spi.EndpointUriFactory; + +/** + * Generated by camel build tools - do NOT edit this file! + */ +@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo") +public class PineconeVectorDbEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory { + + private static final String BASE = ":collection"; + + private static final Set<String> PROPERTY_NAMES; + private static final Set<String> SECRET_PROPERTY_NAMES; + private static final Set<String> MULTI_VALUE_PREFIXES; + static { + Set<String> props = new HashSet<>(3); + props.add("collection"); + props.add("lazyStartProducer"); + props.add("token"); + PROPERTY_NAMES = Collections.unmodifiableSet(props); + Set<String> secretProps = new HashSet<>(1); + secretProps.add("token"); + SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps); + MULTI_VALUE_PREFIXES = Collections.emptySet(); + } + + @Override + public boolean isEnabled(String scheme) { + return "pinecone".equals(scheme); + } + + @Override + public String buildUri(String scheme, Map<String, Object> properties, boolean encode) throws URISyntaxException { + String syntax = scheme + BASE; + String uri = syntax; + + Map<String, Object> copy = new HashMap<>(properties); + + uri = buildPathParameter(syntax, uri, "collection", null, true, copy); + uri = buildQueryParameters(uri, copy, encode); + return uri; + } + + @Override + public Set<String> propertyNames() { + return PROPERTY_NAMES; + } + + @Override + public Set<String> secretPropertyNames() { + return SECRET_PROPERTY_NAMES; + } + + @Override + public Set<String> multiValuePrefixes() { + return MULTI_VALUE_PREFIXES; + } + + @Override + public boolean isLenientProperties() { + return false; + } +} + diff --git a/components/camel-pinecone/src/generated/resources/META-INF/org/apache/camel/component/pinecone/pinecone.json b/components/camel-pinecone/src/generated/resources/META-INF/org/apache/camel/component/pinecone/pinecone.json new file mode 100644 index 00000000000..532bdd80669 --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/org/apache/camel/component/pinecone/pinecone.json @@ -0,0 +1,53 @@ +{ + "component": { + "kind": "component", + "name": "pinecone", + "title": "Pinecone", + "description": "Perform operations on the Pinecone Vector Database.", + "deprecated": false, + "firstVersion": "4.6.0", + "label": "database,ai", + "javaType": "org.apache.camel.component.pinecone.PineconeVectorDbComponent", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-pinecone", + "version": "4.6.0-SNAPSHOT", + "scheme": "pinecone", + "extendsScheme": "", + "syntax": "pinecone:collection", + "async": false, + "api": false, + "consumerOnly": false, + "producerOnly": true, + "lenientProperties": false, + "remote": true + }, + "componentProperties": { + "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.pinecone.PineconeVectorDbConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "The 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 [...] + "token": { "index": 2, "kind": "property", "displayName": "Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.pinecone.PineconeVectorDbConfiguration", "configurationField": "configuration", "description": "Sets the API key to use for authentication" }, + "autowiredEnabled": { "index": 3, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] + }, + "headers": { + "CamelPineconeAction": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "enum": [ "CREATE_COLLECTION", "CREATE_INDEX", "UPSERT", "INSERT", "SEARCH", "DELETE" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The action to be performed.", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#ACTION" }, + "CamelPineconeOperationStatus": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation Status.", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#OPERATION_STATUS" }, + "CamelPineconeOperationStatusValue": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation Status Value.", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#OPERATION_STATUS_VALUE" }, + "CamelPineconeTextFieldName": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Text Field Name for Insert\/Upsert operation", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#TEXT_FIELD_NAME" }, + "CamelPineconeVectorFieldName": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Vector Field Name for Insert\/Upsert operation", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#VECTOR_FIELD_NAME" }, + "CamelPineconeIndexName": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Index Name", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#INDEX_NAME" }, + "CamelPineconeIndexPodType": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Index Pod Type", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#INDEX_POD_TYPE" }, + "CamelPineconeIndexPodEnvironment": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Index Pod Environment", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#INDEX_POD_ENVIRONMENT" }, + "CamelPineconeCollectionName": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Collection Name for Insert\/Upsert operation", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#COLLECTION_NAME" }, + "CamelPineconeCollectionSimilarityMetric": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Collection Similarity Metric", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#COLLECTION_SIMILARITY_METRIC" }, + "CamelPineconeCollectionDimension": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Collection Dimension", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#COLLECTION_DIMENSION" }, + "CamelPineconeCollectionCloud": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Collection Cloud Vendor", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#COLLECTION_CLOUD" }, + "CamelPineconeCollectionCloudRegion": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Collection Cloud Vendor Region", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#COLLECTION_CLOUD_REGION" }, + "CamelPineconeIndexId": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Index Upsert Id", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#INDEX_ID" }, + "CamelPineconeQueryTopK": { "index": 14, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Query Top K", "constantName": "org.apache.camel.component.pinecone.PineconeVectorDb$Headers#QUERY_TOP_K" } + }, + "properties": { + "collection": { "index": 0, "kind": "path", "displayName": "Collection", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collection Name" }, + "token": { "index": 1, "kind": "parameter", "displayName": "Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.pinecone.PineconeVectorDbConfiguration", "configurationField": "configuration", "description": "Sets the API key to use for authentication" }, + "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "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 produc [...] + } +} diff --git a/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/component.properties new file mode 100644 index 00000000000..c17bfe427ab --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/component.properties @@ -0,0 +1,7 @@ +# Generated by camel build tools - do NOT edit this file! +components=pinecone +groupId=org.apache.camel +artifactId=camel-pinecone +version=4.6.0-SNAPSHOT +projectName=Camel :: Pinecone +projectDescription=Camel Pinecone support diff --git a/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/component/pinecone b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/component/pinecone new file mode 100644 index 00000000000..9f322cba016 --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/component/pinecone @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.pinecone.PineconeVectorDbComponent diff --git a/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.pinecone.PineconeVectorDbConfiguration b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.pinecone.PineconeVectorDbConfiguration new file mode 100644 index 00000000000..cb8b5c326fa --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.pinecone.PineconeVectorDbConfiguration @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.pinecone.PineconeVectorDbConfigurationConfigurer diff --git a/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/pinecone-component b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/pinecone-component new file mode 100644 index 00000000000..0fc48953926 --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/pinecone-component @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.pinecone.PineconeVectorDbComponentConfigurer diff --git a/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/pinecone-endpoint b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/pinecone-endpoint new file mode 100644 index 00000000000..321d0603ae2 --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/configurer/pinecone-endpoint @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.pinecone.PineconeVectorDbEndpointConfigurer diff --git a/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/urifactory/pinecone-endpoint b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/urifactory/pinecone-endpoint new file mode 100644 index 00000000000..3ba2f8db14d --- /dev/null +++ b/components/camel-pinecone/src/generated/resources/META-INF/services/org/apache/camel/urifactory/pinecone-endpoint @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.pinecone.PineconeVectorDbEndpointUriFactory diff --git a/components/camel-pinecone/src/main/docs/pinecone-component.adoc b/components/camel-pinecone/src/main/docs/pinecone-component.adoc new file mode 100644 index 00000000000..633f6444f80 --- /dev/null +++ b/components/camel-pinecone/src/main/docs/pinecone-component.adoc @@ -0,0 +1,43 @@ += Pinecone Component +:doctitle: Pinecone +:shortname: pinecone +:artifactid: camel-pinecone +:description: Perform operations on the Pinecone Vector Database. +:since: 4.6 +:supportlevel: Preview +:tabs-sync-option: +:component-header: Only producer is supported +//Manually maintained attributes +:camel-spring-boot-name: pinecone + +*Since Camel {since}* + +*{component-header}* + +The Pionecone Component provides support for interacting with the https://pinecone.io/[Milvus Vector Database]. + +== URI format + +[source] +---- +pinecone:collection[?options] +---- + +Where *collection* represents a named set of points (vectors with a payload) defined in your database. + + +// component-configure options: START + +// component-configure options: END + +// component options: START +include::partial$component-configure-options.adoc[] +include::partial$component-endpoint-options.adoc[] +// component options: END + +// endpoint options: START + +// endpoint options: END + + +include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDb.java b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDb.java new file mode 100644 index 00000000000..ecfcbbc2c11 --- /dev/null +++ b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDb.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone; + +import org.apache.camel.spi.Metadata; + +public class PineconeVectorDb { + public static final String SCHEME = "pinecone"; + + private PineconeVectorDb() { + } + + public static class Headers { + @Metadata(description = "The action to be performed.", javaType = "String", + enums = "CREATE_COLLECTION,CREATE_INDEX,UPSERT,INSERT,SEARCH,DELETE") + public static final String ACTION = "CamelPineconeAction"; + + @Metadata(description = "Operation Status.", javaType = "String") + public static final String OPERATION_STATUS = "CamelPineconeOperationStatus"; + + @Metadata(description = "Operation Status Value.", javaType = "int") + public static final String OPERATION_STATUS_VALUE = "CamelPineconeOperationStatusValue"; + + @Metadata(description = "Text Field Name for Insert/Upsert operation", javaType = "String") + public static final String TEXT_FIELD_NAME = "CamelPineconeTextFieldName"; + + @Metadata(description = "Vector Field Name for Insert/Upsert operation", javaType = "String") + public static final String VECTOR_FIELD_NAME = "CamelPineconeVectorFieldName"; + + @Metadata(description = "Index Name", javaType = "String") + public static final String INDEX_NAME = "CamelPineconeIndexName"; + + @Metadata(description = "Index Pod Type", javaType = "String") + public static final String INDEX_POD_TYPE = "CamelPineconeIndexPodType"; + + @Metadata(description = "Index Pod Environment", javaType = "String") + public static final String INDEX_POD_ENVIRONMENT = "CamelPineconeIndexPodEnvironment"; + + @Metadata(description = "Collection Name for Insert/Upsert operation", javaType = "String") + public static final String COLLECTION_NAME = "CamelPineconeCollectionName"; + + @Metadata(description = "Collection Similarity Metric", javaType = "String") + public static final String COLLECTION_SIMILARITY_METRIC = "CamelPineconeCollectionSimilarityMetric"; + + @Metadata(description = "Collection Dimension", javaType = "int") + public static final String COLLECTION_DIMENSION = "CamelPineconeCollectionDimension"; + + @Metadata(description = "Collection Cloud Vendor", javaType = "String") + public static final String COLLECTION_CLOUD = "CamelPineconeCollectionCloud"; + + @Metadata(description = "Collection Cloud Vendor Region", javaType = "String") + public static final String COLLECTION_CLOUD_REGION = "CamelPineconeCollectionCloudRegion"; + + @Metadata(description = "Index Upsert Id", javaType = "String") + public static final String INDEX_ID = "CamelPineconeIndexId"; + + @Metadata(description = "Query Top K", javaType = "Integer") + public static final String QUERY_TOP_K = "CamelPineconeQueryTopK"; + } +} diff --git a/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbAction.java b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbAction.java new file mode 100644 index 00000000000..779a5b8d93f --- /dev/null +++ b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbAction.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone; + +public enum PineconeVectorDbAction { + CREATE_COLLECTION, + CREATE_SERVERLESS_INDEX, + CREATE_POD_INDEX, + UPSERT, + DELETE_INDEX, + DELETE_COLLECTION, + QUERY +} diff --git a/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbComponent.java b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbComponent.java new file mode 100644 index 00000000000..ea2e6c1e1a1 --- /dev/null +++ b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbComponent.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.annotations.Component; +import org.apache.camel.support.DefaultComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component(PineconeVectorDb.SCHEME) +public class PineconeVectorDbComponent extends DefaultComponent { + private static final Logger LOGGER = LoggerFactory.getLogger(PineconeVectorDbComponent.class); + + @Metadata + private PineconeVectorDbConfiguration configuration; + + public PineconeVectorDbComponent() { + this(null); + } + + public PineconeVectorDbComponent(CamelContext context) { + super(context); + + this.configuration = new PineconeVectorDbConfiguration(); + } + + public PineconeVectorDbConfiguration getConfiguration() { + return configuration; + } + + /** + * The configuration; + */ + public void setConfiguration(PineconeVectorDbConfiguration configuration) { + this.configuration = configuration; + } + + @Override + protected Endpoint createEndpoint( + String uri, + String remaining, + Map<String, Object> parameters) + throws Exception { + + PineconeVectorDbConfiguration configuration = this.configuration.copy(); + + PineconeVectorDbEndpoint endpoint = new PineconeVectorDbEndpoint(uri, this, remaining, configuration); + setProperties(endpoint, parameters); + + return endpoint; + } +} diff --git a/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbConfiguration.java b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbConfiguration.java new file mode 100644 index 00000000000..0e960ee214a --- /dev/null +++ b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbConfiguration.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone; + +import io.pinecone.clients.Pinecone; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.Configurer; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriParams; + +@Configurer +@UriParams +public class PineconeVectorDbConfiguration implements Cloneable { + + @Metadata(secret = true) + @UriParam + private String token; + + @Metadata(autowired = true) + private io.pinecone.clients.Pinecone client; + + public String getToken() { + return token; + } + + /** + * Sets the API key to use for authentication + */ + public void setToken(String token) { + this.token = token; + } + + public Pinecone getClient() { + return client; + } + + /** + * Reference to a `io.pinecone.clients.Pinecone`. + */ + public void setClient(Pinecone client) { + this.client = client; + } + + // ************************ + // + // Clone + // + // ************************ + + public PineconeVectorDbConfiguration copy() { + try { + return (PineconeVectorDbConfiguration) super.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeCamelException(e); + } + } +} diff --git a/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpoint.java b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpoint.java new file mode 100644 index 00000000000..0dc108fddfa --- /dev/null +++ b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbEndpoint.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone; + +import io.pinecone.clients.Pinecone; +import org.apache.camel.Category; +import org.apache.camel.Component; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriPath; +import org.apache.camel.support.DefaultEndpoint; + +/** + * Perform operations on the Pinecone Vector Database. + */ +@UriEndpoint( + firstVersion = "4.6.0", + scheme = PineconeVectorDb.SCHEME, + title = "Pinecone", + syntax = "pinecone:collection", + producerOnly = true, + category = { + Category.DATABASE, + Category.AI + }, + headersClass = PineconeVectorDb.Headers.class) +public class PineconeVectorDbEndpoint extends DefaultEndpoint { + + @Metadata(required = true) + @UriPath(description = "The collection Name") + private final String collection; + + @UriParam + private PineconeVectorDbConfiguration configuration; + + private final Object lock; + + private volatile boolean closeClient; + private volatile io.pinecone.clients.Pinecone client; + + public PineconeVectorDbEndpoint( + String endpointUri, + Component component, + String collection, + PineconeVectorDbConfiguration configuration) { + + super(endpointUri, component); + + this.collection = collection; + this.configuration = configuration; + + this.lock = new Object(); + } + + public PineconeVectorDbConfiguration getConfiguration() { + return configuration; + } + + public String getCollection() { + return collection; + } + + public synchronized Pinecone getClient() { + if (this.client == null) { + synchronized (this.lock) { + if (this.client == null) { + this.client = this.configuration.getClient(); + this.closeClient = false; + + if (this.client == null) { + this.client = createClient(); + this.closeClient = true; + } + } + } + } + + return this.client; + } + + @Override + public Producer createProducer() throws Exception { + return new PineconeVectorDbProducer(this); + } + + @Override + public Consumer createConsumer(Processor processor) throws Exception { + throw new UnsupportedOperationException("Consumer is not implemented for this component"); + } + + @Override + public void doStart() throws Exception { + super.doStart(); + } + + @Override + public void doStop() throws Exception { + super.doStop(); + } + + private Pinecone createClient() { + + io.pinecone.clients.Pinecone pinecone = new io.pinecone.clients.Pinecone.Builder(configuration.getToken()).build(); + + return pinecone; + } +} diff --git a/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbProducer.java b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbProducer.java new file mode 100644 index 00000000000..c4268ad6bc6 --- /dev/null +++ b/components/camel-pinecone/src/main/java/org/apache/camel/component/pinecone/PineconeVectorDbProducer.java @@ -0,0 +1,209 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone; + +import java.util.List; +import java.util.concurrent.ExecutorService; + +import io.pinecone.clients.Index; +import io.pinecone.clients.Pinecone; +import io.pinecone.proto.UpsertResponse; +import io.pinecone.unsigned_indices_model.QueryResponseWithUnsignedIndices; +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.NoSuchHeaderException; +import org.apache.camel.support.DefaultProducer; +import org.openapitools.client.model.CollectionModel; +import org.openapitools.client.model.IndexModel; + +public class PineconeVectorDbProducer extends DefaultProducer { + private Pinecone client; + private ExecutorService executor; + + public PineconeVectorDbProducer(PineconeVectorDbEndpoint endpoint) { + super(endpoint); + } + + @Override + public PineconeVectorDbEndpoint getEndpoint() { + return (PineconeVectorDbEndpoint) super.getEndpoint(); + } + + @Override + public void doStart() throws Exception { + super.doStart(); + + this.client = getEndpoint().getClient(); + } + + @Override + public void process(Exchange exchange) { + final Message in = exchange.getMessage(); + final PineconeVectorDbAction action = in.getHeader(PineconeVectorDb.Headers.ACTION, PineconeVectorDbAction.class); + + try { + if (action == null) { + throw new NoSuchHeaderException("The action is a required header", exchange, PineconeVectorDb.Headers.ACTION); + } + + switch (action) { + case CREATE_COLLECTION: + createCollection(exchange); + break; + case CREATE_SERVERLESS_INDEX: + createServerlessIndex(exchange); + break; + case CREATE_POD_INDEX: + createPodIndex(exchange); + break; + case UPSERT: + upsert(exchange); + break; + case DELETE_INDEX: + deleteIndex(exchange); + break; + case DELETE_COLLECTION: + deleteCollection(exchange); + break; + case QUERY: + query(exchange); + break; + default: + throw new UnsupportedOperationException("Unsupported action: " + action.name()); + } + } catch (Exception e) { + exchange.setException(e); + } + } + + // *************************************** + // + // Actions + // + // *************************************** + + private void createCollection(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + String collectionName = in.getHeader(PineconeVectorDb.Headers.COLLECTION_NAME, String.class); + String indexName = in.getHeader(PineconeVectorDb.Headers.INDEX_NAME, String.class); + + CollectionModel result = this.client.createCollection(collectionName, indexName); + + populateCollectionResponse(result, exchange); + + } + + private void createServerlessIndex(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + String indexName = in.getHeader(PineconeVectorDb.Headers.INDEX_NAME, String.class); + String collectionSimilarityMetricName + = in.getHeader(PineconeVectorDb.Headers.COLLECTION_SIMILARITY_METRIC, String.class); + int collectionDimension = in.getHeader(PineconeVectorDb.Headers.COLLECTION_DIMENSION, Integer.class); + String collectionCloudName = in.getHeader(PineconeVectorDb.Headers.COLLECTION_CLOUD, String.class); + String collectionCloudRegionName = in.getHeader(PineconeVectorDb.Headers.COLLECTION_CLOUD_REGION, String.class); + + IndexModel result = this.client.createServerlessIndex(indexName, collectionSimilarityMetricName, collectionDimension, + collectionCloudName, collectionCloudRegionName); + + populateIndexResponse(result, exchange); + + } + + private void createPodIndex(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + String indexName = in.getHeader(PineconeVectorDb.Headers.INDEX_NAME, String.class); + String collectionSimilarityMetricName + = in.getHeader(PineconeVectorDb.Headers.COLLECTION_SIMILARITY_METRIC, String.class); + int collectionDimension = in.getHeader(PineconeVectorDb.Headers.COLLECTION_DIMENSION, Integer.class); + String indexPodType = in.getHeader(PineconeVectorDb.Headers.INDEX_POD_TYPE, String.class); + String indexPodEnv = in.getHeader(PineconeVectorDb.Headers.INDEX_POD_ENVIRONMENT, String.class); + + IndexModel result = this.client.createPodsIndex(indexName, collectionDimension, + indexPodEnv, indexPodType, collectionSimilarityMetricName); + + populateIndexResponse(result, exchange); + + } + + private void upsert(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + List elements = in.getMandatoryBody(List.class); + String indexName = in.getHeader(PineconeVectorDb.Headers.INDEX_NAME, String.class); + String indexId = in.getHeader(PineconeVectorDb.Headers.INDEX_ID, String.class); + Index index = this.client.getIndexConnection(indexName); + + UpsertResponse result = index.upsert(indexId, elements); + + populateUpsertResponse(result, exchange); + + } + + private void deleteIndex(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + String indexName = in.getHeader(PineconeVectorDb.Headers.INDEX_NAME, String.class); + this.client.deleteIndex(indexName); + } + + private void deleteCollection(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + String collectionName = in.getHeader(PineconeVectorDb.Headers.COLLECTION_NAME, String.class); + this.client.deleteCollection(collectionName); + } + + private void query(Exchange exchange) throws Exception { + final Message in = exchange.getMessage(); + List elements = in.getMandatoryBody(List.class); + String indexName = in.getHeader(PineconeVectorDb.Headers.INDEX_NAME, String.class); + int topK = in.getHeader(PineconeVectorDb.Headers.QUERY_TOP_K, Integer.class); + Index index = this.client.getIndexConnection(indexName); + + QueryResponseWithUnsignedIndices result = index.queryByVector(topK, elements); + + populateQueryResponse(result, exchange); + } + + // *************************************** + // + // Helpers + // + // *************************************** + + private CamelContext getCamelContext() { + return getEndpoint().getCamelContext(); + } + + private void populateCollectionResponse(CollectionModel r, Exchange exchange) { + Message out = exchange.getMessage(); + out.setBody(r); + } + + private void populateIndexResponse(IndexModel r, Exchange exchange) { + Message out = exchange.getMessage(); + out.setBody(r); + } + + private void populateUpsertResponse(UpsertResponse r, Exchange exchange) { + Message out = exchange.getMessage(); + out.setBody(r); + } + + private void populateQueryResponse(QueryResponseWithUnsignedIndices r, Exchange exchange) { + Message out = exchange.getMessage(); + out.setBody(r); + } +} diff --git a/components/camel-pinecone/src/test/java/org/apache/camel/component/pinecone/it/PineconeComponentIT.java b/components/camel-pinecone/src/test/java/org/apache/camel/component/pinecone/it/PineconeComponentIT.java new file mode 100644 index 00000000000..7765a45eb8b --- /dev/null +++ b/components/camel-pinecone/src/test/java/org/apache/camel/component/pinecone/it/PineconeComponentIT.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.pinecone.it; + +import java.util.Arrays; +import java.util.List; + +import io.pinecone.unsigned_indices_model.QueryResponseWithUnsignedIndices; +import org.apache.camel.Exchange; +import org.apache.camel.component.pinecone.PineconeVectorDb; +import org.apache.camel.component.pinecone.PineconeVectorDbAction; +import org.apache.camel.test.junit5.CamelTestSupport; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.condition.EnabledIfSystemProperties; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; + +import static org.assertj.core.api.Assertions.assertThat; + +// Must be manually tested. Provide your own accessKey and secretKey using -Dpinecone.token +@EnabledIfSystemProperties({ + @EnabledIfSystemProperty(named = "pinecone.token", matches = ".*", disabledReason = "Pinecone token not provided"), +}) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class PineconeComponentIT extends CamelTestSupport { + + @Test + @Order(1) + public void createServerlessIndex() { + + Exchange result = fluentTemplate.to("pinecone:test-collection?token={{pinecone.token}}") + .withHeader(PineconeVectorDb.Headers.ACTION, PineconeVectorDbAction.CREATE_SERVERLESS_INDEX) + .withBody( + "hello") + .withHeader(PineconeVectorDb.Headers.INDEX_NAME, "test-serverless-index") + .withHeader(PineconeVectorDb.Headers.COLLECTION_SIMILARITY_METRIC, "cosine") + .withHeader(PineconeVectorDb.Headers.COLLECTION_DIMENSION, 3) + .withHeader(PineconeVectorDb.Headers.COLLECTION_CLOUD, "aws") + .withHeader(PineconeVectorDb.Headers.COLLECTION_CLOUD_REGION, "us-east-1") + .request(Exchange.class); + + assertThat(result).isNotNull(); + assertThat(result.getException()).isNull(); + } + + @Test + @Order(2) + public void upsert() { + + List<Float> elements = Arrays.asList(1.0f, 2.0f, 3.0f); + + Exchange result = fluentTemplate.to("pinecone:test-collection?token={{pinecone.token}}") + .withHeader(PineconeVectorDb.Headers.ACTION, PineconeVectorDbAction.UPSERT) + .withBody( + elements) + .withHeader(PineconeVectorDb.Headers.INDEX_NAME, "test-serverless-index") + .withHeader(PineconeVectorDb.Headers.INDEX_ID, "elements") + .request(Exchange.class); + + assertThat(result).isNotNull(); + assertThat(result.getException()).isNull(); + } + + @Test + @Order(3) + public void queryByVector() { + + List<Float> elements = Arrays.asList(1.0f, 2.0f, 3.0f); + + Exchange result = fluentTemplate.to("pinecone:test-collection?token={{pinecone.token}}") + .withHeader(PineconeVectorDb.Headers.ACTION, PineconeVectorDbAction.QUERY) + .withBody( + elements) + .withHeader(PineconeVectorDb.Headers.INDEX_NAME, "test-serverless-index") + .withHeader(PineconeVectorDb.Headers.QUERY_TOP_K, 3) + .request(Exchange.class); + + assertThat(result).isNotNull(); + assertThat(result.getException()).isNull(); + assertThat(((QueryResponseWithUnsignedIndices) result.getMessage().getBody()).getMatchesList()).isNotEmpty(); + assertThat( + ((QueryResponseWithUnsignedIndices) result.getMessage().getBody()).getMatches(0).getScore() > 0.9f); + } + + @Test + @Order(4) + public void deleteIndex() { + + Exchange result = fluentTemplate.to("pinecone:test-collection?token={{pinecone.token}}") + .withHeader(PineconeVectorDb.Headers.ACTION, PineconeVectorDbAction.DELETE_INDEX) + .withBody( + "test") + .withHeader(PineconeVectorDb.Headers.INDEX_NAME, "test-serverless-index") + .request(Exchange.class); + + assertThat(result).isNotNull(); + assertThat(result.getException()).isNull(); + } + +} diff --git a/components/camel-pinecone/src/test/resources/log4j2.properties b/components/camel-pinecone/src/test/resources/log4j2.properties new file mode 100644 index 00000000000..706b275083b --- /dev/null +++ b/components/camel-pinecone/src/test/resources/log4j2.properties @@ -0,0 +1,35 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- + +appender.file.type = File +appender.file.name = file +appender.file.fileName = target/camel-pinecone-test.log +appender.file.layout.type = PatternLayout +appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n + +appender.out.type = Console +appender.out.name = out +appender.out.layout.type = PatternLayout +appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n + +rootLogger.level = INFO +rootLogger.appenderRef.file.ref = file +# To log to stdout +#rootLogger.appenderRef.out.ref = out + +logger.camel-pinecone.name = org.apache.camel.component.pinecone +logger.camel-pinecone.level = DEBUG diff --git a/parent/pom.xml b/parent/pom.xml index af4f80109be..fea6738cc1b 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -1977,6 +1977,11 @@ <artifactId>camel-pgevent</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-pinecone</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-platform-http</artifactId>