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

zbendhiba 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 e9e869f9c25 CAMEL-21719: Neo4j Embedding  Data transfomer for RAG 
results (#17072)
e9e869f9c25 is described below

commit e9e869f9c2587677b976e2fe2eff96f7cd48718b
Author: Zineb BENDHIBA <bendhiba.zi...@gmail.com>
AuthorDate: Wed Feb 5 20:09:12 2025 +0100

    CAMEL-21719: Neo4j Embedding  Data transfomer for RAG results (#17072)
---
 .../apache/camel/catalog/transformers.properties   |  1 +
 .../camel/catalog/transformers/neo4j-rag.json      | 14 ++++++
 ...angChain4jEmbeddingsComponentNeo4jTargetIT.java | 29 +++++++++++-
 .../org/apache/camel/transformer.properties        |  2 +-
 .../org/apache/camel/transformer/neo4j-rag         |  2 +
 .../org/apache/camel/transformer/neo4j-rag.json    | 14 ++++++
 .../camel-neo4j/src/main/docs/neo4j-component.adoc | 49 +++++++++++++++-----
 ...ataTypeTransformer.java => Neo4jEmbedding.java} | 41 +++++++++++------
 .../camel/component/neo4j/Neo4jProducer.java       | 52 ++++++++++++++++------
 .../Neo4jEmbeddingDataTypeTransformer.java         | 17 ++++++-
 ...Neo4jReverseEmbeddingsDataTypeTransformer.java} | 27 ++++++++---
 .../neo4j/it/Neo4jVectorEmbeddingsIT.java          | 48 ++++++++++++++++----
 12 files changed, 238 insertions(+), 58 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
index 4a3560e1fe5..b1ffb14a926 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
@@ -29,6 +29,7 @@ google-storage-application-cloudevents
 http-application-cloudevents
 milvus-embeddings
 neo4j-embeddings
+neo4j-rag
 pinecone-embeddings
 protobuf-binary
 protobuf-x-java-object
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/neo4j-rag.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/neo4j-rag.json
new file mode 100644
index 00000000000..27e84a5f080
--- /dev/null
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/neo4j-rag.json
@@ -0,0 +1,14 @@
+{
+  "transformer": {
+    "kind": "transformer",
+    "name": "neo4j:rag",
+    "title": "Neo4j (Rag)",
+    "description": "Prepares the similarity search LangChain4j embeddings to 
become a List of String for LangChain4j RAG",
+    "deprecated": false,
+    "javaType": 
"org.apache.camel.component.neo4j.transformer.Neo4jReverseEmbeddingsDataTypeTransformer",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-neo4j",
+    "version": "4.10.0-SNAPSHOT"
+  }
+}
+
diff --git 
a/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentNeo4jTargetIT.java
 
b/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentNeo4jTargetIT.java
index 46fd8a65aa0..b6d29f463d5 100644
--- 
a/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentNeo4jTargetIT.java
+++ 
b/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentNeo4jTargetIT.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.langchain4j.embeddings;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -28,6 +29,7 @@ import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.neo4j.Neo4Operation;
 import org.apache.camel.component.neo4j.Neo4jComponent;
 import org.apache.camel.component.neo4j.Neo4jConstants;
+import org.apache.camel.spi.DataType;
 import org.apache.camel.test.infra.neo4j.services.Neo4jService;
 import org.apache.camel.test.infra.neo4j.services.Neo4jServiceFactory;
 import org.apache.camel.test.junit5.CamelTestSupport;
@@ -47,7 +49,7 @@ import static org.junit.Assert.assertTrue;
 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 public class LangChain4jEmbeddingsComponentNeo4jTargetIT extends 
CamelTestSupport {
 
-    public static final String NEO4J_URI = "neo4j:neo4j";
+    public static final String NEO4J_URI = 
"neo4j:neo4j?vectorIndexName=myIndex&label=Test";
     @RegisterExtension
     static Neo4jService NEO4J = Neo4jServiceFactory.createSingletonService();
 
@@ -138,6 +140,20 @@ public class LangChain4jEmbeddingsComponentNeo4jTargetIT 
extends CamelTestSuppor
 
     }
 
+    @Test
+    @Order(3)
+    public void rag_similarity_search() {
+        Exchange result = fluentTemplate.to("direct:search")
+                .withBody("hi")
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+
+        
assertThat(result.getIn().getBody()).isInstanceOfSatisfying(Collection.class, c 
-> assertThat(c).hasSize(1));
+        assertTrue(result.getIn().getBody(List.class).contains("hi"));
+    }
+
     @Override
     protected RoutesBuilder createRouteBuilder() {
         return new RouteBuilder() {
@@ -149,6 +165,17 @@ public class LangChain4jEmbeddingsComponentNeo4jTargetIT 
extends CamelTestSuppor
                         
.setHeader(Neo4jConstants.Headers.LABEL).constant("Test")
                         .transform(new 
org.apache.camel.spi.DataType("neo4j:embeddings"))
                         .to(NEO4J_URI);
+
+                from("direct:search")
+                        .to("langchain4j-embeddings:test")
+                        // transform prompt into embeddings for search
+                        .transform(
+                                new DataType("neo4j:embeddings"))
+                        .setHeader(Neo4jConstants.Headers.OPERATION, 
constant(Neo4Operation.VECTOR_SIMILARITY_SEARCH))
+                        .to(NEO4J_URI)
+                        // decode retrieved embeddings for RAG
+                        .transform(
+                                new DataType("neo4j:rag"));
             }
         };
     }
diff --git 
a/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
 
b/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
index 90fcac63c4f..10c4e1d06a4 100644
--- 
a/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
+++ 
b/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
@@ -1,5 +1,5 @@
 # Generated by camel build tools - do NOT edit this file!
-transformers=neo4j:embeddings
+transformers=neo4j:embeddings neo4j:rag
 groupId=org.apache.camel
 artifactId=camel-neo4j
 version=4.10.0-SNAPSHOT
diff --git 
a/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer/neo4j-rag
 
b/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer/neo4j-rag
new file mode 100644
index 00000000000..179c57958a6
--- /dev/null
+++ 
b/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer/neo4j-rag
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.neo4j.transformer.Neo4jReverseEmbeddingsDataTypeTransformer
diff --git 
a/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer/neo4j-rag.json
 
b/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer/neo4j-rag.json
new file mode 100644
index 00000000000..27e84a5f080
--- /dev/null
+++ 
b/components/camel-ai/camel-neo4j/src/generated/resources/META-INF/services/org/apache/camel/transformer/neo4j-rag.json
@@ -0,0 +1,14 @@
+{
+  "transformer": {
+    "kind": "transformer",
+    "name": "neo4j:rag",
+    "title": "Neo4j (Rag)",
+    "description": "Prepares the similarity search LangChain4j embeddings to 
become a List of String for LangChain4j RAG",
+    "deprecated": false,
+    "javaType": 
"org.apache.camel.component.neo4j.transformer.Neo4jReverseEmbeddingsDataTypeTransformer",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-neo4j",
+    "version": "4.10.0-SNAPSHOT"
+  }
+}
+
diff --git a/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc 
b/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc
index 5fc4b0a8960..ea552b2faa2 100644
--- a/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc
+++ b/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc
@@ -223,16 +223,20 @@ The URI endpoint should contain also specify the vector 
index name.
 === Create a vector
 To create a vector in a database named `test`, use the operation 
`CREATE_VECTOR`.
 The URI endpoint should also specify the label, the alias and the vector index 
name.
+Put the vector array in the `CamelLangChain4jEmbeddingsVector` header, and the 
corresponding text in the body.
+The `id` can be generated by Camel Neo4j.
+
+Camel Neo4j will create the node and store the vector as an `embedding` 
property, the text as `text` property and the `id`as `id` property.
 
-Camel Neo4j will create the node and store the vector as an `embedding` 
property.
 
 .Example:
 [source,java]
 ----
-         Exchange result = 
fluentTemplate.to("neo4j:test?vectorIndexName=movieIdx&label=Movie&alias=m")
-                .withHeader(Neo4j.Headers.OPERATION, 
Neo4Operation.CREATE_VECTOR)
-                .withHeader(Neo4j.Headers.VECTOR_ID, testData.getId())
-                .withBody(List.of(0.8f, 0.6f))
+            Exchange result = 
fluentTemplate.to("neo4j:test?vectorIndexName=myIndex&label=Test&alias=t")
+                .withHeader(Neo4jConstants.Headers.OPERATION, 
Neo4Operation.CREATE_VECTOR)
+                .withHeader(Neo4jConstants.Headers.VECTOR_ID, "1")
+                .withHeader("CamelLangChain4jEmbeddingsVector", new float[] { 
10.8f, 10.6f })
+                .withBody("Hello World!")
                 .request(Exchange.class);
 ----
 
@@ -244,9 +248,8 @@ The URI endpoint should also specify the label, the alias 
and the vector index n
 .Example:
 [source,java]
 ----
-         Exchange result = 
fluentTemplate.to("neo4j:test?vectorIndexName=movieIdx&label=Movie&alias=m")
-                .withHeader(Neo4j.Headers.OPERATION, 
Neo4Operation.CREATE_VECTOR)
-                .withHeader(Neo4j.Headers.VECTOR_ID, testData.getId())
+         Exchange result = 
fluentTemplate.to("neo4j:test?vectorIndexName=myIndex&label=Test&alias=t")
+                .withHeader(Neo4jConstants.Headers.OPERATION, 
Neo4Operation.VECTOR_SIMILARITY_SEARCH)
                 .withBody(List.of(0.75f, 0.65f))
                 .request(Exchange.class);
 ----
@@ -254,7 +257,7 @@ The URI endpoint should also specify the label, the alias 
and the vector index n
 == Generate Embeddings with Langchain4j-embeddings
 You can generate embeddings with an Embedding Models using the camel 
Lancghain4j Embeddings components. Camel Neo4j introduces a DataType 
`neo4j:embeddings` that automates the transformations of the Lancghain4j 
embeddings to Neo4j vectors.
 
-.Example of a camel Route that create embeddings with Camel Langchain4j 
Embeddings
+.Example of a camel Route that create embeddings with Camel Langchain4j 
Embeddings, and ingest them into Neo4j database.
 [source,java]
 ----
          from("direct:in")
@@ -262,5 +265,31 @@ You can generate embeddings with an Embedding Models using 
the camel Lancghain4j
             
.setHeader(Neo4j.Headers.OPERATION).constant(Neo4Operation.CREATE_VECTOR)
             .setHeader(Neo4j.Headers.LABEL).constant("Test")
             .transform(new DataType("neo4j:embeddings"))
-            .to("neo4j:test");
+            .to("neo4j:neo4j?vectorIndexName=myIndex&label=Test");
 ----
+
+== Similarity Search for LangChain4j RAG
+You can enhance the Camel LangChain4j chat RAG experience by integrating Neo4j 
similarity search with Camel Neo4j DataTypes.
+
+To achieve this, use the `neo4j:embeddings` DataType to generate embeddings 
from the prompt. These embeddings will then be utilized for the similarity 
search operation.
+
+Next, use the `neo4j:rag` DataType to convert the retrieved embeddings into a 
List<String> for RAG. This list can be directly used with the 
`LangChain4jRagAggregatorStrategy` from the LangChain4j chat component.
+
+NOTE: The retrieved embeddings must be ingested in Neo4j as LangChain4j 
embeddings.
+
+.Example of a camel Route that performs a similarity search in the Vector 
index, using a string and returning a list of strings
+[source,java]
+----
+         from("direct:search")
+                        .to("langchain4j-embeddings:test")
+                        // transform prompt into embeddings for search
+                        .transform(
+                                new DataType("neo4j:embeddings"))
+                        .setHeader(Neo4jConstants.Headers.OPERATION, 
constant(Neo4Operation.VECTOR_SIMILARITY_SEARCH))
+                        .to("neo4j:neo4j?vectorIndexName=myIndex&label=Test")
+                        // decode retrieved embeddings for RAG
+                        .transform(
+                                new DataType("neo4j:rag"));
+----
+
+
diff --git 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jEmbedding.java
similarity index 50%
copy from 
components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
copy to 
components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jEmbedding.java
index 78544256206..02d06718ecc 100644
--- 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
+++ 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jEmbedding.java
@@ -14,21 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.neo4j.transformer;
+package org.apache.camel.component.neo4j;
 
-import dev.langchain4j.data.embedding.Embedding;
-import org.apache.camel.Message;
-import org.apache.camel.ai.CamelLangchain4jAttributes;
-import org.apache.camel.spi.DataType;
-import org.apache.camel.spi.DataTypeTransformer;
-import org.apache.camel.spi.Transformer;
+/**
+ * Class that represents the embedding to persist when using LangChain4j - The 
names of the properties correspond to the
+ * ones in LangChain4j project for compatibility.
+ */
+public class Neo4jEmbedding {
+    private String id;
+
+    private String text;
+
+    private float[] vectors;
+
+    public Neo4jEmbedding(String id, String text, float[] vectors) {
+        this.id = id;
+        this.text = text;
+        this.vectors = vectors;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getText() {
+        return text;
+    }
 
-@DataTypeTransformer(name = "neo4j:embeddings",
-                     description = "Prepares the message to become an object 
writable by Neo4j component")
-public class Neo4jEmbeddingDataTypeTransformer extends Transformer {
-    @Override
-    public void transform(Message message, DataType fromType, DataType toType) 
{
-        Embedding embedding = 
message.getHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR,
 Embedding.class);
-        message.setBody(embedding.vector());
+    public float[] getVectors() {
+        return vectors;
     }
 }
diff --git 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jProducer.java
 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jProducer.java
index 6dfa6bc8838..c1ac6cb0a87 100644
--- 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jProducer.java
+++ 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/Neo4jProducer.java
@@ -25,6 +25,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.NoSuchHeaderException;
+import org.apache.camel.ai.CamelLangchain4jAttributes;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
 import org.neo4j.driver.Driver;
@@ -242,37 +243,60 @@ public class Neo4jProducer extends DefaultProducer {
 
     private void createVector(Exchange exchange) {
         final String alias
-                = getEndpoint().getConfiguration().getAlias() != null ? 
getEndpoint().getConfiguration().getAlias() : "x";
+                = getEndpoint().getConfiguration().getAlias() != null ? 
getEndpoint().getConfiguration().getAlias() : "e";
 
-        final String label = 
exchange.getMessage().getHeader(Neo4jConstants.Headers.LABEL,
-                () -> getEndpoint().getConfiguration().getLabel(), 
String.class);
-        ObjectHelper.notNull(label, "label");
-
-        final String id
-                = 
exchange.getMessage().getHeader(Neo4jConstants.Headers.VECTOR_ID, () -> 
UUID.randomUUID(), String.class);
+        final String label
+                = getEndpoint().getConfiguration().getLabel() != null
+                        ? getEndpoint().getConfiguration().getLabel() : 
"Embedding";
 
-        final float[] body = exchange.getMessage().getBody(float[].class);
+        String id;
+        String text;
+        float[] vectors;
 
         final String databaseName = getEndpoint().getName();
 
+        Object body = exchange.getMessage().getBody();
+
+        if (body instanceof Neo4jEmbedding) {
+            id = ((Neo4jEmbedding) body).getId();
+            text = ((Neo4jEmbedding) body).getText();
+            vectors = ((Neo4jEmbedding) body).getVectors();
+        } else {
+            id = 
exchange.getMessage().getHeader(Neo4jConstants.Headers.VECTOR_ID, () -> 
UUID.randomUUID(), String.class);
+            vectors = 
exchange.getMessage().getHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR,
+                    float[].class);
+            text = exchange.getMessage().getBody(String.class);
+        }
+
+        ObjectHelper.notNull(text, "text");
+        ObjectHelper.notNull(vectors, "vectors");
+
         String query = String.format("""
-                MERGE (%s:%s {id: $id})
+                MERGE (%s:%s {id: $id, text: $text})
                 WITH %s
                 CALL db.create.setNodeVectorProperty(%s, 'embedding', 
$embedding);
                 """, alias, label, alias, alias);
 
         Map<String, Object> params = Map.of(
-                "embedding", Values.value(body),
-                "id", id);
+                "embedding", Values.value(vectors),
+                "id", id,
+                "text", text);
 
         executeWriteQuery(exchange, query, params, databaseName, 
Neo4Operation.CREATE_VECTOR);
     }
 
-    public void similaritySearch(Exchange exchange) {
+    public void similaritySearch(Exchange exchange) throws 
InvalidPayloadException {
         final String vectorIndexName = 
getEndpoint().getConfiguration().getVectorIndexName();
         ObjectHelper.notNull(vectorIndexName, "vectorIndexName");
 
-        final float[] body = exchange.getMessage().getBody(float[].class);
+        float[] vectors;
+
+        Object body = exchange.getMessage().getMandatoryBody();
+        if (body instanceof Neo4jEmbedding) {
+            vectors = ((Neo4jEmbedding) body).getVectors();
+        } else {
+            vectors = exchange.getMessage().getBody(float[].class);
+        }
 
         final double minScore = getEndpoint().getConfiguration().getMinScore();
 
@@ -288,7 +312,7 @@ public class Neo4jProducer extends DefaultProducer {
                 """;
 
         Map<String, Object> params = Map.of("indexName", vectorIndexName,
-                "embeddingValue", body,
+                "embeddingValue", vectors,
                 "minScore", minScore,
                 "maxResults", maxResults);
 
diff --git 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
index 78544256206..2908a8ab057 100644
--- 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
+++ 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
@@ -16,9 +16,14 @@
  */
 package org.apache.camel.component.neo4j.transformer;
 
+import java.util.UUID;
+
 import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
 import org.apache.camel.Message;
 import org.apache.camel.ai.CamelLangchain4jAttributes;
+import org.apache.camel.component.neo4j.Neo4jConstants;
+import org.apache.camel.component.neo4j.Neo4jEmbedding;
 import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.Transformer;
@@ -28,7 +33,15 @@ import org.apache.camel.spi.Transformer;
 public class Neo4jEmbeddingDataTypeTransformer extends Transformer {
     @Override
     public void transform(Message message, DataType fromType, DataType toType) 
{
-        Embedding embedding = 
message.getHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR,
 Embedding.class);
-        message.setBody(embedding.vector());
+        final Embedding embedding
+                = 
message.getHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR,
 Embedding.class);
+
+        final TextSegment text = message.getBody(TextSegment.class);
+
+        final String id = message.getHeader(Neo4jConstants.Headers.VECTOR_ID, 
() -> UUID.randomUUID(), String.class);
+
+        Neo4jEmbedding neo4jEmbedding = new Neo4jEmbedding(id, text.text(), 
embedding.vector());
+
+        message.setBody(neo4jEmbedding);
     }
 }
diff --git 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jReverseEmbeddingsDataTypeTransformer.java
similarity index 59%
copy from 
components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
copy to 
components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jReverseEmbeddingsDataTypeTransformer.java
index 78544256206..cc711176585 100644
--- 
a/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jEmbeddingDataTypeTransformer.java
+++ 
b/components/camel-ai/camel-neo4j/src/main/java/org/apache/camel/component/neo4j/transformer/Neo4jReverseEmbeddingsDataTypeTransformer.java
@@ -14,21 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.camel.component.neo4j.transformer;
 
-import dev.langchain4j.data.embedding.Embedding;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 import org.apache.camel.Message;
-import org.apache.camel.ai.CamelLangchain4jAttributes;
 import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.Transformer;
 
-@DataTypeTransformer(name = "neo4j:embeddings",
-                     description = "Prepares the message to become an object 
writable by Neo4j component")
-public class Neo4jEmbeddingDataTypeTransformer extends Transformer {
+/**
+ * Maps a List of retrieved LangChain4j Embeddings with similarity search to a 
List of String for LangChain4j RAG
+ **/
+@DataTypeTransformer(name = "neo4j:rag",
+                     description = "Prepares the similarity search LangChain4j 
embeddings to become a List of String for LangChain4j RAG")
+public class Neo4jReverseEmbeddingsDataTypeTransformer extends Transformer {
+
     @Override
     public void transform(Message message, DataType fromType, DataType toType) 
{
-        Embedding embedding = 
message.getHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR,
 Embedding.class);
-        message.setBody(embedding.vector());
+        final List<Map<String, Object>> embeddings = 
message.getBody(List.class);
+
+        List<String> result = embeddings.stream()
+                .map(embedding -> (String) embedding.getOrDefault("text", ""))
+                .collect(Collectors.toList());
+
+        message.setBody(result);
+
     }
 }
diff --git 
a/components/camel-ai/camel-neo4j/src/test/java/org/apache/camel/component/neo4j/it/Neo4jVectorEmbeddingsIT.java
 
b/components/camel-ai/camel-neo4j/src/test/java/org/apache/camel/component/neo4j/it/Neo4jVectorEmbeddingsIT.java
index b2e04c3a2c9..ab5fce9bd7a 100644
--- 
a/components/camel-ai/camel-neo4j/src/test/java/org/apache/camel/component/neo4j/it/Neo4jVectorEmbeddingsIT.java
+++ 
b/components/camel-ai/camel-neo4j/src/test/java/org/apache/camel/component/neo4j/it/Neo4jVectorEmbeddingsIT.java
@@ -20,8 +20,10 @@ import java.util.List;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
+import org.apache.camel.ai.CamelLangchain4jAttributes;
 import org.apache.camel.component.neo4j.Neo4Operation;
 import org.apache.camel.component.neo4j.Neo4jConstants;
+import org.apache.camel.component.neo4j.Neo4jEmbedding;
 import org.apache.camel.component.neo4j.Neo4jTestSupport;
 import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Order;
@@ -62,7 +64,8 @@ public class Neo4jVectorEmbeddingsIT extends Neo4jTestSupport 
{
         Exchange result = 
fluentTemplate.to("neo4j:neo4j?vectorIndexName=movieIdx&label=Movie&alias=m")
                 .withHeader(Neo4jConstants.Headers.OPERATION, 
Neo4Operation.CREATE_VECTOR)
                 .withHeader(Neo4jConstants.Headers.VECTOR_ID, testData.getId())
-                .withBody(testData.getVectors())
+                
.withHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR, 
testData.getVectors())
+                .withBody(testData.getText())
                 .request(Exchange.class);
 
         assertNotNull(result);
@@ -77,8 +80,29 @@ public class Neo4jVectorEmbeddingsIT extends 
Neo4jTestSupport {
         assertEquals("A node creation is expected ", 1, 
in.getHeader(Neo4jConstants.Headers.QUERY_RESULT_NODES_CREATED));
     }
 
-    @Test
     @Order(2)
+    @Test
+    void addGeneratedNeo4jEmbedding() {
+        Neo4jEmbedding neo4jEmbedding = new Neo4jEmbedding("15", "Hello 
World", new float[] { 10.8f, 10.6f });
+        Exchange result = 
fluentTemplate.to("neo4j:neo4j?vectorIndexName=movieIdx&label=Movie&alias=m")
+                .withHeader(Neo4jConstants.Headers.OPERATION, 
Neo4Operation.CREATE_VECTOR)
+                .withBody(neo4jEmbedding)
+                .request(Exchange.class);
+
+        assertNotNull(result);
+
+        Message in = result.getMessage();
+        assertNotNull(in);
+
+        assertEquals(Neo4Operation.CREATE_VECTOR, 
in.getHeader(Neo4jConstants.Headers.OPERATION));
+        assertTrue("The executed request should contain the procedure of 
setting vector embedding",
+                in.getHeader(Neo4jConstants.Headers.QUERY_RESULT, String.class)
+                        .contains("CALL db.create.setNodeVectorProperty"));
+        assertEquals("A node creation is expected ", 1, 
in.getHeader(Neo4jConstants.Headers.QUERY_RESULT_NODES_CREATED));
+    }
+
+    @Test
+    @Order(3)
     public void similaritySeach() {
         Exchange result = 
fluentTemplate.to("neo4j:neo4j?vectorIndexName=movieIdx&label=Movie&alias=m")
                 .withHeader(Neo4jConstants.Headers.OPERATION, 
Neo4Operation.VECTOR_SIMILARITY_SEARCH)
@@ -98,7 +122,7 @@ public class Neo4jVectorEmbeddingsIT extends 
Neo4jTestSupport {
     }
 
     @Test
-    @Order(3)
+    @Order(4)
     void dropVectorIndex() {
         Exchange result = 
fluentTemplate.to("neo4j:neo4j?vectorIndexName=movieIdx")
                 .withHeader(Neo4jConstants.Headers.OPERATION, 
Neo4Operation.DROP_VECTOR_INDEX)
@@ -116,17 +140,19 @@ public class Neo4jVectorEmbeddingsIT extends 
Neo4jTestSupport {
 
     // Enum to provide test data
     public enum TestData {
-        VECTOR_1(9, List.of(0.8f, 0.6f)),
-        VECTOR_2(10, List.of(0.1f, 0.9f)),
-        VECTOR_3(11, List.of(0.7f, 0.7f)),
-        VECTOR_4(12, List.of(-0.3f, -0.9f)),
-        VECTOR_5(13, List.of(1.2f, 0.8f));
+        VECTOR_1(9, "VECTOR_1", List.of(0.8f, 0.6f)),
+        VECTOR_2(10, "VECTOR_2", List.of(0.1f, 0.9f)),
+        VECTOR_3(11, "VECTOR_3", List.of(0.7f, 0.7f)),
+        VECTOR_4(12, "VECTOR_4", List.of(-0.3f, -0.9f)),
+        VECTOR_5(13, "VECTOR_5", List.of(1.2f, 0.8f));
 
         private final int id;
+        private final String text;
         private final List<Float> vectors;
 
-        TestData(int id, List<Float> vectors) {
+        TestData(int id, String text, List<Float> vectors) {
             this.id = id;
+            this.text = text;
             this.vectors = vectors;
         }
 
@@ -137,5 +163,9 @@ public class Neo4jVectorEmbeddingsIT extends 
Neo4jTestSupport {
         public List<Float> getVectors() {
             return vectors;
         }
+
+        public String getText() {
+            return text;
+        }
     }
 }

Reply via email to