Skip to content

Commit

Permalink
Fixes #4091: Update RAG docs with vector db examples (#4116)
Browse files Browse the repository at this point in the history
  • Loading branch information
vga91 authored Jun 28, 2024
1 parent a386e67 commit c6d1cc4
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

== ChromaDB

Here is a list of all available ChromaDB procedures,
Expand Down Expand Up @@ -221,6 +220,16 @@ For example, by executing a `CALL apoc.vectordb.chroma.query(...) YIELD metadata
so that we do not return the other values that we do not need.
====

It is possible to execute vector db procedures together with the xref::ml/rag.adoc[apoc.ml.rag] as follow:

[source,cypher]
----
CALL apoc.vectordb.chroma.getAndUpdate($host, $collection, [<id1>, <id2>], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, $question, $confPrompt) YIELD value
RETURN value
----

.Delete vectors (it leverages https://docs.trychroma.com/usage-guide#deleting-data-from-a-collection[this API])
[source,cypher]
----
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

== Milvus

Here is a list of all available Milvus procedures:
Expand Down Expand Up @@ -223,6 +222,15 @@ For example, by executing a `CALL apoc.vectordb.milvus.query(...) YIELD metadata
so that we do not return the other values that we do not need.
====

It is possible to execute vector db procedures together with the xref::ml/rag.adoc[apoc.ml.rag] as follow:

[source,cypher]
----
CALL apoc.vectordb.milvus.getAndUpdate($host, $collection, [<id1>, <id2>], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, $question, $confPrompt) YIELD value
RETURN value
----


.Delete vectors (it leverages https://milvus.io/api-reference/restful/v2.4.x/v2/Vector%20(v2)/Delete.md[this API])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

== Pinecone

Here is a list of all available Pinecone procedures:
Expand Down Expand Up @@ -237,7 +236,15 @@ For example, by executing a `CALL apoc.vectordb.pinecone.query(...) YIELD metada
so that we do not return the other values that we do not need.
====

It is possible to execute vector db procedures together with the xref::ml/rag.adoc[apoc.ml.rag] as follow:

[source,cypher]
----
CALL apoc.vectordb.pinecone.getAndUpdate($host, $collection, [<id1>, <id2>], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, $question, $confPrompt) YIELD value
RETURN value
----

.Delete vectors (it leverages https://docs.pinecone.io/reference/api/data-plane/delete[this API])
[source,cypher]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

== Qdrant

Here is a list of all available Qdrant procedures,
Expand Down Expand Up @@ -224,7 +223,15 @@ For example, by executing a `CALL apoc.vectordb.qdrant.query(...) YIELD metadata
so that we do not return the other values that we do not need.
====

It is possible to execute vector db procedures together with the xref::ml/rag.adoc[apoc.ml.rag] as follow:

[source,cypher]
----
CALL apoc.vectordb.qdrant.getAndUpdate($host, $collection, [<id1>, <id2>], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, $question, $confPrompt) YIELD value
RETURN value
----

.Delete vectors (it leverages https://qdrant.github.io/qdrant/redoc/index.html#tag/points/operation/delete_vectors[this API])
[source,cypher]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

== Weaviate

Here is a list of all available Weaviate procedures,
Expand Down Expand Up @@ -240,7 +239,15 @@ For example, by executing a `CALL apoc.vectordb.weaviate.query(...) YIELD metada
so that we do not return the other values that we do not need.
====

It is possible to execute vector db procedures together with the xref::ml/rag.adoc[apoc.ml.rag] as follow:

[source,cypher]
----
CALL apoc.vectordb.weaviate.getAndUpdate($host, $collection, [<id1>, <id2>], $conf) YIELD score, node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, $question, $confPrompt) YIELD value
RETURN value
----

.Delete vectors (it leverages https://weaviate.io/developers/weaviate/api/rest#tag/objects/delete/objects/\{className\}/\{id\}[this API])
[source,cypher]
Expand Down
47 changes: 43 additions & 4 deletions extended-it/src/test/java/apoc/vectordb/ChromaDbTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package apoc.vectordb;

import apoc.ml.Prompt;
import apoc.util.TestUtil;
import org.junit.AfterClass;
import org.junit.Before;
Expand All @@ -16,30 +17,39 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import static apoc.ml.Prompt.API_KEY_CONF;
import static apoc.ml.RestAPIConfig.HEADERS_KEY;
import static apoc.util.MapUtil.map;
import static apoc.util.TestUtil.testCall;
import static apoc.util.TestUtil.testResult;
import static apoc.vectordb.VectorDbHandler.Type.CHROMA;
import static apoc.vectordb.VectorDbTestUtil.EntityType.FALSE;
import static apoc.vectordb.VectorDbTestUtil.EntityType.NODE;
import static apoc.vectordb.VectorDbTestUtil.EntityType.REL;
import static apoc.vectordb.VectorDbTestUtil.assertBerlinResult;
import static apoc.vectordb.VectorDbTestUtil.assertLondonResult;
import static apoc.vectordb.VectorDbTestUtil.assertNodesCreated;
import static apoc.vectordb.VectorDbTestUtil.assertRagWithVectors;
import static apoc.vectordb.VectorDbTestUtil.assertReadOnlyProcWithMappingResults;
import static apoc.vectordb.VectorDbTestUtil.assertRelsCreated;
import static apoc.vectordb.VectorDbTestUtil.dropAndDeleteAll;
import static apoc.vectordb.VectorDbTestUtil.EntityType.*;
import static apoc.vectordb.VectorDbTestUtil.getAuthHeader;
import static apoc.vectordb.VectorDbTestUtil.ragSetup;
import static apoc.vectordb.VectorEmbeddingConfig.ALL_RESULTS_KEY;
import static apoc.vectordb.VectorEmbeddingConfig.MAPPING_KEY;
import static apoc.vectordb.VectorMappingConfig.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertTrue;
import static org.neo4j.configuration.GraphDatabaseSettings.DEFAULT_DATABASE_NAME;
import static org.neo4j.configuration.GraphDatabaseSettings.SYSTEM_DATABASE_NAME;

public class ChromaDbTest {
private static final AtomicReference<String> COLL_ID = new AtomicReference<>();
private static final ChromaDBContainer CHROMA_CONTAINER = new ChromaDBContainer("chromadb/chroma:0.4.25.dev137");
private static final String READONLY_KEY = "my_readonly_api_key";
private static final Map<String, String> READONLY_AUTHORIZATION = getAuthHeader(READONLY_KEY);

private static String HOST;

Expand All @@ -60,7 +70,7 @@ public static void setUp() throws Exception {
CHROMA_CONTAINER.start();

HOST = "localhost:" + CHROMA_CONTAINER.getMappedPort(8000);
TestUtil.registerProcedure(db, ChromaDb.class, VectorDb.class);
TestUtil.registerProcedure(db, ChromaDb.class, VectorDb.class, Prompt.class);

testCall(db, "CALL apoc.vectordb.chroma.createCollection($host, 'test_collection', 'cosine', 4)",
map("host", HOST),
Expand Down Expand Up @@ -123,7 +133,7 @@ public void getVectorsWithoutVectorResult() {
assertNull(row.get("id"));
});
}

@Test
public void deleteVector() {
testCall(db, """
Expand Down Expand Up @@ -421,4 +431,33 @@ public void queryVectorsWithSystemDbStorage() {

assertNodesCreated(db);
}

@Test
public void queryVectorsWithRag() {
String openAIKey = ragSetup(db);

Map<String, Object> conf = map(ALL_RESULTS_KEY, true,
HEADERS_KEY, READONLY_AUTHORIZATION,
MAPPING_KEY, map(NODE_LABEL, "Rag",
ENTITY_KEY, "readID",
METADATA_KEY, "foo")
);

testResult(db,
"""
CALL apoc.vectordb.chroma.getAndUpdate($host, $collection, ['1', '2'], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, "Which city has foo equals to one?", $confPrompt) YIELD value
RETURN value
"""
,
map(
"host", HOST,
"conf", conf,
"collection", COLL_ID.get(),
"confPrompt", map(API_KEY_CONF, openAIKey),
"attributes", List.of("city", "foo")
),
VectorDbTestUtil::assertRagWithVectors);
}
}
43 changes: 40 additions & 3 deletions extended-it/src/test/java/apoc/vectordb/MilvusTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package apoc.vectordb;

import apoc.ml.Prompt;
import apoc.util.TestUtil;
import apoc.util.Util;
import org.junit.AfterClass;
Expand All @@ -16,6 +17,8 @@
import java.util.List;
import java.util.Map;

import static apoc.ml.Prompt.API_KEY_CONF;
import static apoc.ml.RestAPIConfig.HEADERS_KEY;
import static apoc.util.MapUtil.map;
import static apoc.util.TestUtil.testCall;
import static apoc.util.TestUtil.testResult;
Expand All @@ -29,16 +32,18 @@
import static apoc.vectordb.VectorDbTestUtil.assertReadOnlyProcWithMappingResults;
import static apoc.vectordb.VectorDbTestUtil.assertRelsCreated;
import static apoc.vectordb.VectorDbTestUtil.dropAndDeleteAll;
import static apoc.vectordb.VectorDbTestUtil.getAuthHeader;
import static apoc.vectordb.VectorDbTestUtil.ragSetup;
import static apoc.vectordb.VectorEmbeddingConfig.ALL_RESULTS_KEY;
import static apoc.vectordb.VectorEmbeddingConfig.FIELDS_KEY;
import static apoc.vectordb.VectorEmbeddingConfig.MAPPING_KEY;
import static apoc.vectordb.VectorMappingConfig.MODE_KEY;
import static apoc.vectordb.VectorMappingConfig.EMBEDDING_KEY;
import static apoc.vectordb.VectorMappingConfig.ENTITY_KEY;
import static apoc.vectordb.VectorMappingConfig.METADATA_KEY;
import static apoc.vectordb.VectorMappingConfig.MODE_KEY;
import static apoc.vectordb.VectorMappingConfig.MappingMode;
import static apoc.vectordb.VectorMappingConfig.NODE_LABEL;
import static apoc.vectordb.VectorMappingConfig.REL_TYPE;
import static apoc.vectordb.VectorMappingConfig.MappingMode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
Expand All @@ -49,6 +54,8 @@
public class MilvusTest {
private static final List<String> FIELDS = List.of("city", "foo");
private static final MilvusContainer MILVUS_CONTAINER = new MilvusContainer("milvusdb/milvus:v2.4.0");
private static final String READONLY_KEY = "my_readonly_api_key";
private static final Map<String, String> READONLY_AUTHORIZATION = getAuthHeader(READONLY_KEY);

private static String HOST;

Expand All @@ -69,7 +76,7 @@ public static void setUp() throws Exception {
MILVUS_CONTAINER.start();

HOST = MILVUS_CONTAINER.getEndpoint();
TestUtil.registerProcedure(db, Milvus.class, VectorDb.class);
TestUtil.registerProcedure(db, Milvus.class, VectorDb.class, Prompt.class);

testCall(db, "CALL apoc.vectordb.milvus.createCollection($host, 'test_collection', 'COSINE', 4)",
map("host", HOST),
Expand Down Expand Up @@ -429,4 +436,34 @@ public void queryVectorsWithSystemDbStorage() {
assertNodesCreated(db);
}

@Test
public void queryVectorsWithRag() {
String openAIKey = ragSetup(db);

Map<String, Object> conf = map(
FIELDS_KEY, FIELDS,
ALL_RESULTS_KEY, true,
HEADERS_KEY, READONLY_AUTHORIZATION,
MAPPING_KEY, map(NODE_LABEL, "Rag",
ENTITY_KEY, "readID",
METADATA_KEY, "foo")
);

testResult(db,
"""
CALL apoc.vectordb.milvus.getAndUpdate($host, 'test_collection', [1, 2], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, "Which city has foo equals to one?", $confPrompt) YIELD value
RETURN value
"""
,
map(
"host", HOST,
"conf", conf,
"confPrompt", map(API_KEY_CONF, openAIKey),
"attributes", List.of("city", "foo")
),
VectorDbTestUtil::assertRagWithVectors);
}

}
45 changes: 42 additions & 3 deletions extended-it/src/test/java/apoc/vectordb/QdrantTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import apoc.util.TestUtil;
import apoc.util.Util;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
Expand All @@ -13,9 +14,12 @@
import org.neo4j.test.TestDatabaseManagementServiceBuilder;
import org.testcontainers.qdrant.QdrantContainer;

import java.util.List;
import java.util.Map;

import apoc.ml.Prompt;
import static apoc.ml.RestAPIConfig.HEADERS_KEY;
import static apoc.ml.Prompt.API_KEY_CONF;
import static apoc.util.MapUtil.map;
import static apoc.util.TestUtil.testCall;
import static apoc.util.TestUtil.testResult;
Expand All @@ -35,9 +39,9 @@
import static apoc.vectordb.VectorMappingConfig.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.neo4j.configuration.GraphDatabaseSettings.*;

Expand Down Expand Up @@ -72,7 +76,7 @@ public static void setUp() throws Exception {
QDRANT_CONTAINER.start();

HOST = "localhost:" + QDRANT_CONTAINER.getMappedPort(6333);
TestUtil.registerProcedure(db, Qdrant.class, VectorDb.class);
TestUtil.registerProcedure(db, Qdrant.class, VectorDb.class, Prompt.class);

testCall(db, "CALL apoc.vectordb.qdrant.createCollection($host, 'test_collection', 'Cosine', 4, $conf)",
map("host", HOST, "conf", ADMIN_HEADER_CONF),
Expand Down Expand Up @@ -177,6 +181,41 @@ public void deleteVector() {
});
}

@Test
public void queryVectorsWithRag() {
String openAIKey = System.getenv("OPENAI_KEY");;
Assume.assumeNotNull("No OPENAI_KEY environment configured", openAIKey);

db.executeTransactionally("CREATE (:Rag {readID: 'one'}), (:Rag {readID: 'two'})");

Map<String, Object> conf = map(ALL_RESULTS_KEY, true,
HEADERS_KEY, READONLY_AUTHORIZATION,
MAPPING_KEY, map(NODE_LABEL, "Rag",
ENTITY_KEY, "readID",
METADATA_KEY, "foo")
);

testResult(db,
"""
CALL apoc.vectordb.qdrant.getAndUpdate($host, 'test_collection', [1, 2], $conf) YIELD node, metadata, id, vector
WITH collect(node) as paths
CALL apoc.ml.rag(paths, $attributes, "Which city has foo equals to one?", $confPrompt) YIELD value
RETURN value
"""
,
map(
"host", HOST,
"conf", conf,
"confPrompt", map(API_KEY_CONF, openAIKey),
"attributes", List.of("city", "foo")
),
r -> {
Map<String, Object> row = r.next();
Object value = row.get("value");
assertTrue("The actual value is: " + value, value.toString().contains("Berlin"));
});
}

@Test
public void queryVectors() {
testResult(db, "CALL apoc.vectordb.qdrant.query($host, 'test_collection', [0.2, 0.1, 0.9, 0.7], {}, 5, $conf)",
Expand Down Expand Up @@ -463,5 +502,5 @@ public void queryVectorsWithSystemDbStorage() {

assertNodesCreated(db);
}

}
Loading

0 comments on commit c6d1cc4

Please sign in to comment.