From 5a63cd840cfff691eb3ddca9f0705dc44381afb7 Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Fri, 15 Sep 2023 22:39:01 +0200 Subject: [PATCH] Add PGVector VectorStore implementation * Enable PGVector indexing support * Add same document ID vector update support * Add documentation for VectorStores --- .gitignore | 3 +- README.md | 4 +- pom.xml | 11 +- spring-ai-core/pom.xml | 17 +- .../springframework/ai/document/Document.java | 110 ++++---- .../modules/ROOT/images/lawofcosines.png | Bin 0 -> 51819 bytes .../ROOT/images/pythagorean-triangle.png | Bin 0 -> 4961 bytes .../ROOT/images/vector_2d_coordinates.png | Bin 0 -> 12479 bytes .../modules/ROOT/images/vector_similarity.png | Bin 0 -> 90020 bytes .../modules/ROOT/pages/api/vectordbs.adoc | 203 +++++++++++++- .../{AcmeIntegrationTest.java => AcmeIT.java} | 6 +- ...entIntegrationTests.java => ClientIT.java} | 4 +- ...gIntegrationTest.java => EmbeddingIT.java} | 2 +- ...ctIntegrationTest.java => AbstractIT.java} | 4 +- .../spring-ai-pgvector-store/README.md | 16 ++ .../spring-ai-pgvector-store/pom.xml | 94 +++++++ .../ai/vectorstore/PgVectorStore.java | 261 ++++++++++++++++++ .../ai/vectorstore/PgVectorStoreIT.java | 173 ++++++++++++ 18 files changed, 829 insertions(+), 79 deletions(-) create mode 100644 spring-ai-docs/src/main/antora/modules/ROOT/images/lawofcosines.png create mode 100644 spring-ai-docs/src/main/antora/modules/ROOT/images/pythagorean-triangle.png create mode 100644 spring-ai-docs/src/main/antora/modules/ROOT/images/vector_2d_coordinates.png create mode 100644 spring-ai-docs/src/main/antora/modules/ROOT/images/vector_similarity.png rename spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/{AcmeIntegrationTest.java => AcmeIT.java} (95%) rename spring-ai-openai/src/test/java/org/springframework/ai/openai/client/{ClientIntegrationTests.java => ClientIT.java} (96%) rename spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/{EmbeddingIntegrationTest.java => EmbeddingIT.java} (97%) rename spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/{AbstractIntegrationTest.java => AbstractIT.java} (97%) create mode 100644 vector-stores/spring-ai-pgvector-store/README.md create mode 100644 vector-stores/spring-ai-pgvector-store/pom.xml create mode 100644 vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java create mode 100644 vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java diff --git a/.gitignore b/.gitignore index 476f773c8..ca5d03678 100644 --- a/.gitignore +++ b/.gitignore @@ -26,10 +26,11 @@ out /.gradletasknamecache **/*.flattened-pom.xml -vscode +vscode settings.json node node_modules package-lock.json package.json +.vscode \ No newline at end of file diff --git a/README.md b/README.md index dce550567..6913f0b0c 100644 --- a/README.md +++ b/README.md @@ -149,10 +149,10 @@ To build with only unit tests ``` To build including integration tests. -Set API key environment variables for OpenAI and Azure OpenAI before running. +Set API key environment variables for OpenAI and Azure OpenAI before running. ```shell -./mvnw clean package -Pintegration-tests +./mvnw clean verify -Pintegration-tests ``` To build the docs diff --git a/pom.xml b/pom.xml index 8f05ace92..9675749f9 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,7 @@ spring-ai-spring-boot-starters/spring-ai-starter-openai spring-ai-spring-boot-starters/spring-ai-starter-azure-openai spring-ai-docs + vector-stores/spring-ai-pgvector-store @@ -61,7 +62,7 @@ 17 - + 3.1.2 4.0.2 0.12.0 @@ -127,9 +128,6 @@ ${maven-surefire-plugin.version} ${surefireArgLine} - - **/*IntegrationTests.java - @@ -247,11 +245,6 @@ org.apache.maven.plugins maven-failsafe-plugin ${maven-failsafe-plugin.version} - - - **/*IntegrationTests.java - - diff --git a/spring-ai-core/pom.xml b/spring-ai-core/pom.xml index cb15c5f3e..b2c74e939 100644 --- a/spring-ai-core/pom.xml +++ b/spring-ai-core/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 org.springframework.experimental.ai @@ -18,6 +19,10 @@ git@github.com:spring-projects-experimental/spring-ai.git + + 4.31.1 + + @@ -46,21 +51,15 @@ com.github.victools jsonschema-generator - 4.31.1 + ${jsonschema.version} com.github.victools jsonschema-module-jackson - 4.31.1 + ${jsonschema.version} - - - - - - org.springframework.boot diff --git a/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java b/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java index ae6b6745d..ce1e89f3c 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java @@ -6,14 +6,10 @@ import java.util.*; public class Document { - private static String DEFAULT_TEXT_TEMPLATE = "{metadata_string}\n\n{text}"; - - private static String DEFAULT_METADATA_TEMPLATE = "{key}: {value}"; - /** * Unique ID */ - private String id = UUID.randomUUID().toString(); + private final String id; private List embedding = new ArrayList<>(); @@ -25,28 +21,24 @@ public class Document { // Type; introduce when support images, now only text. + // TODO: Rename to `content` instead. private String text; - private MetadataMode metadataMode = MetadataMode.NONE; - - private List excludedMetadataKeysForEmbedding; - - private List excludedMetadataKeysForLlm; - - private List relatedIds; - - private String textTemplate = DEFAULT_TEXT_TEMPLATE; - - private String metadataTemplate = DEFAULT_METADATA_TEMPLATE; - - private String metadataSeparator = "\n"; - public Document(String text) { + this(UUID.randomUUID().toString(), text); + } + + public Document(String id, String text) { + this.id = id; this.text = text; - this.metadata = metadata; } public Document(String text, Map metadata) { + this(UUID.randomUUID().toString(), text, metadata); + } + + public Document(String id, String text, Map metadata) { + this.id = id; this.text = text; this.metadata = metadata; } @@ -59,6 +51,43 @@ public class Document { return this.text; } + public Map getMetadata() { + return metadata; + } + + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } + + @Override + public String toString() { + return "Document{" + "id='" + id + '\'' + ", metadata=" + metadata + ", text='" + text + '\'' + '}'; + } + + // TODO: Consider moving the following methods & fields in a seprarate + // dedicated class. (e.g. DocumentService, DocumentUtil or alike)¬ + + // private List excludedMetadataKeysForEmbedding; + // private List relatedIds; + + private static String DEFAULT_TEXT_TEMPLATE = "{metadata_string}\n\n{text}"; + + private static String DEFAULT_METADATA_TEMPLATE = "{key}: {value}"; + + private final String textTemplate = DEFAULT_TEXT_TEMPLATE; + + private final String metadataTemplate = DEFAULT_METADATA_TEMPLATE; + + private final String metadataSeparator = "\n"; + + private MetadataMode metadataMode = MetadataMode.NONE; + + private List excludedMetadataKeysForLlm; + public String getContent() { return getContent(MetadataMode.ALL); } @@ -103,45 +132,28 @@ public class Document { return String.join(getMetadataSeparator(), metadataStringList); } - public String getTextTemplate() { + private String getTextTemplate() { return textTemplate; } - public String getMetadataTemplate() { + private String getMetadataTemplate() { return metadataTemplate; } - public String getMetadataSeparator() { + private String getMetadataSeparator() { return metadataSeparator; } - public Map getMetadata() { - return metadata; - } + // public void setTextTemplate(String textTemplate) { + // this.textTemplate = textTemplate; + // } - public List getEmbedding() { - return embedding; - } + // public void setMetadataTemplate(String metadataTemplate) { + // this.metadataTemplate = metadataTemplate; + // } - public void setEmbedding(List embedding) { - this.embedding = embedding; - } - - @Override - public String toString() { - return "Document{" + "id='" + id + '\'' + ", metadata=" + metadata + ", text='" + text + '\'' + '}'; - } - - public void setTextTemplate(String textTemplate) { - this.textTemplate = textTemplate; - } - - public void setMetadataTemplate(String metadataTemplate) { - this.metadataTemplate = metadataTemplate; - } - - public void setMetadataSeparator(String metadataSeparator) { - this.metadataSeparator = metadataSeparator; - } + // public void setMetadataSeparator(String metadataSeparator) { + // this.metadataSeparator = metadataSeparator; + // } } diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/images/lawofcosines.png b/spring-ai-docs/src/main/antora/modules/ROOT/images/lawofcosines.png new file mode 100644 index 0000000000000000000000000000000000000000..46ceadd920597d4c1697d901107fbae63602ddfa GIT binary patch literal 51819 zcmeFY^;eW#)HjZ|dK(}qEg;<>FrhC9a!(#pJ;uSoc>SI&0DQvqQAG?e|oJ_kh7#e zp*vj(0__dq%+0?Ul$07bcwS!|{|&OYdP#0DiL^*`&Zcj++S%E1jE%Lm zNznDNc9BkqG<~GrU7Y`LVa%%#>?}lirUtwydA<@K9{y;irsZ;OH&mJ)10fp2!P#5V zH#=;~OUTn$??(!dkdQ<~M3D0sQBYIcRU7mL7=cv`btwFVv0F9FNe10qvC;);aFGQp zWFe8~*SkSdFJCsyeg@gFr&OGqP9{CNd3=Z+qLXqldboHQSZ^fhbFea2q?>&C3tT8O z{42JKu+77GLomO)yL%|(rEbyKvu=8ZnHuccTJ$qfem=fMG>-*d1W2jhZ;6l6*U~r9 zJb4KkIvk0rQrAZ-z406f)I^)4-^tc+j@$#q3~<#(ijSEXnOub!{UkwAQJ=MbWSX$k zNqbt@^!74DGFg%H(7QQ(Ry7lt(OycVj)r~8@Xm^-t_S~Mny$rf7 z)8pbfZ3SB_uFT0;z&ZAFf4O@oUDRTxCLacW5Pd^qG?9^!A>n)U=j^O5)%|av%pdxy zD6$)tj3WhXByX<{JsSo@TR3ya0>Gc9rClyX@bZ{8HyV8gWnypizF2{Ft!K`#NZ{33 zI03_C&b=A0m7v%T=4=k4J z9$&APMQRvTRM+_-w!5o~tIzjOO=97aSBVZaHMM4%t%S(*-&(;NCR&o(mZ5?jMQPFn z9I0okdE3etRj@Yi7FCaeUkq<;6{kMCF~X+=yMTOXu0ld&Q9K6EkPNt(EVqF7MaePc z73&nq#n5J?r*~vN!@>D6a-XkYEOkACoHz5OSE(MCq+^<1qQv<|QCX=`{Xt|jA-K}{ zLt7P)a6?kJSKu-+4K)hepY(Z>!HWGf7G;mr{eGx&l3( zTa&{>*1@2v7RzwGr)h)Z7F*}A=e~~3~h?kWpBE|R)hBq-6bTkeXIx;-C~ zI{W=8E-tQB?sueLa{~LEIB+#kpPC)oT9pKw@!rNfWEB#c4qnM4{=L6` zX|{E8&qMG^eDVj#fA7}f+!Obfo!?FYgYO)y{!-Ulu2`P+89q0j%f;rwsE{a?88{|nlZkw!P{Z&6Jr`D0!S`?rm(A%v$**R6C-Un#{&k4$fGxLc)e67P#X zk!cztl{6-FzAox*_1gM2sgv_UFg+&{99%*zmB?+XbI_ z+%q3SlXst@)-GjTaTd})MFl=yA(G^~cX;?A{a=KJZzfg*|4I6T2dZIPDt$i1dn0G) zq;kSz0~t^uZj857uuaY}W?Iuby zUV24GNAq_D6B7JsFub!f0mW%$$~y{JIK9>>5(MQPJR~F}q@-Hv>L%@lLJ0F=*8E71 z&GGHIhSMnF`N=w$oYKwo!v?YTG4dg)hht?XTwFKUpc`yQN3g@pMupz}G{TPnYD{

Q!YDCSbs6` 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 ShXU@**o+O#^h@;YBL531_1oM4 literal 0 HcmV?d00001 diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/images/vector_2d_coordinates.png b/spring-ai-docs/src/main/antora/modules/ROOT/images/vector_2d_coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..9bc5018670004876c50e6a17f15e877cb4736242 GIT binary patch literal 12479 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 literal 0 HcmV?d00001 diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/images/vector_similarity.png b/spring-ai-docs/src/main/antora/modules/ROOT/images/vector_similarity.png new file mode 100644 index 0000000000000000000000000000000000000000..9b8a01bb84307ba6501549f500568507603cc8a4 GIT binary patch literal 90020 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ȉnoW&vO{o~_-AR|F*uR&l;j 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

{Y@>BZ)i4U>qUR#mF%-nG`U6 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 KPWr4>5&s2c@_xer literal 0 HcmV?d00001 diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc index b29015307..3c2a48959 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc @@ -1 +1,202 @@ -= Vector Databases \ No newline at end of file += Vector Databases + +== Introduction +Vector Databases are a specialized type of database that plays an essential role in AI applications. + +In Vector Databases, queries differ from traditional relational databases. +Instead of exact matches, they perform similarity searches. +When given a vector as a query, a Vector Database returns vectors that are "similar" to the query vector. +Further details on how this similarity is calculated at a high level in provided in a later section. + +Vector Databases are used to integrate your data with AI Models. +The first step in their usage is to load your data into a Vector Database. +Then, when a user query is to be sent to the AI model, a set of similar documents is retrieved first. +These documents then serve as the context for the user's question and are sent to the AI model along with the user's query. +This technique is known as Retrieval Augmented Generation. + +In the following sections, we will describe the Spring AI interface for using multiple Vector Database implementations and some high-level sample usage. + +The last section attempts to demystify the underlying approach of similarity search of Vector Databases. + +== Spring AI Vector Database Support + +Spring AI provides an abstract API over Vector Databases using the interface `VectorStore`. + +The API of the Vector store is shown below + +```java +public interface VectorStore { + + void add(List documents); + + Optional delete(List idList); + + List similaritySearch(String query); + + List similaritySearch(String query, int k); + + List similaritySearch(String query, int k, double threshold); +``` + +The Spring AI library uses the `Document` class to model the `String` you want to store in the Vector Database along with the vector representing that `String`. +The vector that representing the `String` is of the type `List` and is often called the string's embedding. + +The `List is computed from the `String` using an implementation of the class `EmbeddingClient`. +An Embedding Model is an example of an AI model, that transforms from `String` to a `List`. +The embeddings are used internally by other AI Model implementations, such as models that convert `text` to `text` like ChatGPT. + +`EmbeddingClient` that computes the embedding is passed as a constructor argument to `VectorStore` implementation. + + +The `VectorStore` implementations supported by Spring AI are: + +* InMemoryVectorStore +* SimplePersistentVectorStore +* PgVector - A Vector Store build on PostgreSQL. + +More are implementations are coming, with Pinecone being the next implementation. + +If you have a Vector Database that needs to be supported by Spring AI, please open an issue on GitHub or, even better, submit a Pull Request with an implementation. + +== Usage + +To compute the embeddings for a Vector Database, you need to pick an Embedding Model that matches the higher-level AI model being used. + +For example, with OpenAI's ChatGPT, we use the `OpenAiEmbeddingClient` and the model name `text-embedding-ada-002`. + +The Spring Boot Starter's autoconfiguation for OpenAI makes an implementation of `EmbeddingClient` available in the Spring Application Context for Dependency Injection. + +The general usage of loading data into a vector store is something you do as a batch-type job, first loading data into Spring AI's `Document` class and then calling the `save` method. + +Given a String `sourceFile` that represents a JSON file with data we want to load into the Vector Database, we use Spring AI's `JsonLoader` to load specific fields in the JSON file, which splits them up into small pieces and then passes those small pieces to the vector store implementation. +The `VectorStore` implementation computes the embeddings and stores the JSON and the embedding in the Vector Database. + +```java + @Autowired + VectorStore vectorStore; + + void load(String sourceFile) {} + JsonLoader jsonLoader = new JsonLoader(new FileSystemResource(sourceFile), + "price", "name", "shortDescription", "description", "tags"); + List documents = jsonLoader.load(); + this.vectorStore.add(documents); + } +``` + +Later, when a user question is to be passed into the AI Model, a similarity search is done to retrieve similar documents, which are then 'stuffed' into the prompt as context for the user's question. + +```java + + String question = + List similarDocuments = store.similaritySearch(question); +``` + +There are additional options to be passed into the `similaritySearch` method that defines how many documents to retrieve and a threshold of the similarity search. + +== Understanding Vectors + +Vectors have dimensionality and a direction. +For example, a picture of a two-dimensional vector stem:[\vec{a}] in the cartesian coordinate system pictured as an arrow. + +image::vector_2d_coordinates.png[] + +The head of the vector stem:[\vec{a}] is at the point stem:[(a_1, a_2)] +The *x* coordinate value is stem:[a_1] and the *y* coordinate value is stem:[a_2] and are also referred to as the components of the vector. + +== Similarity + +Several mathematical formulas can be used to determine if two vectors are similar. + +One of the most intuitive to visualize and understand is cosine similarity. + +Look at the following pictures that show three sets of graphs. + +image::vector_similarity.png[] + +The vectors stem:[\vec{A}] and stem:[\vec{B}] are considered similar, when they are pointing close to each other, as in the first diagram. +The vectors are considered unrelated when pointing perpendicular to each other and opposite when they point away from each other. + +The angle between them, stem:[\theta], is a good measure of their similarity. +How can the angle stem:[\theta] be computed? + +We are all familiar with the https://en.wikipedia.org/wiki/Pythagorean_theorem#History[Pythagorean Theorem] + +image:pythagorean-triangle.png[] + +What about when the angle between *a* and *b* is not 90 degrees? + +Enter the https://en.wikipedia.org/wiki/Law_of_cosines[Law of cosines] + + +.Law of Cosines +**** +stem:[a^2 + b^2 - 2ab\cos\theta = c^2] +**** + +Showing this as a vector diagram + +image:lawofcosines.png[] + + +The magnitude of this vector is defined in terms of its components as: + +.Magnitude +**** +stem:[\vec{A} * \vec{A} = ||\vec{A}||^2 = A_1^2 + A_2^2 ] +**** + +and the dot product between two vectors stem:[\vec{A}] and stem:[\vec{B}] is defined in terms of its components as: + + +.Dot Product +**** +stem:[\vec{A} * \vec{B} = A_1B_1 + A_2B_2] +**** + +Rewriting the Law of Cosines with vector magnitudes and dot products gives: + +.Law of Cosines in Vector form +**** +stem:[||\vec{A}||^2 + ||\vec{B}||^2 - 2||\vec{A}||||\vec{B}||\cos\theta = ||\vec{C}||^2] +**** + + +Replacing stem:[||\vec{C}||^2] with stem:[||\vec{B} - \vec{A}||^2] gives: + +.Law of Cosines in Vector form only in terms of stem:[\vec{A}] and stem:[\vec{B}] + +**** +stem:[||\vec{A}||^2 + ||\vec{B}||^2 - 2||\vec{A}||||\vec{B}||\cos\theta = ||\vec{B} - \vec{A}||^2] +**** + + +https://towardsdatascience.com/cosine-similarity-how-does-it-measure-the-similarity-maths-behind-and-usage-in-python-50ad30aad7db[Expanding this out] gives us the formula for https://en.wikipedia.org/wiki/Cosine_similarity[Cosine Similarity]. + +.Cosine Similarity +**** +stem:[similarity(vec{A},vec{B}) = \cos(\theta) = \frac{\vec{A}\cdot\vec{B}}{||\vec{A}\||\cdot||\vec{B}||] +**** + +This formula works for dimensions higher than 2 or 3, though it is hard to visualize, https://projector.tensorflow.org/[but can be done to some extent]. +It is common for vectors in AI/ML applications to have hundreds or a thousand dimensions. + +The similarity function in higher dimensions using the components of the vector is shown below. +It expands the two-dimensional definitions of Magnitude and Dot Product given previously to *N* dimensions using the https://en.wikipedia.org/wiki/Summation[Summation mathematical syntax]. + +.Cosine Similarity with vector components +**** +stem:[similarity(vec{A},vec{B}) = \cos(\theta) = \frac{ \sum_{i=1}^{n} {A_i B_i} }{ \sqrt{\sum_{i=1}^{n}{A_i^2} \cdot \sum_{i=1}^{n}{B_i^2}}] +**** + +This is the key formula used in the simple implementation of a Vector Store and can be found in the `InMemoryVectorStore` implementation. + + + + + + + + + + + diff --git a/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIntegrationTest.java b/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java similarity index 95% rename from spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIntegrationTest.java rename to spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java index 6f3e1257a..c762d9aa4 100644 --- a/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIntegrationTest.java +++ b/spring-ai-openai/src/test/java/org/springframework/ai/openai/acme/AcmeIT.java @@ -8,7 +8,7 @@ import org.springframework.ai.client.AiResponse; import org.springframework.ai.document.Document; import org.springframework.ai.loader.impl.JsonLoader; import org.springframework.ai.openai.embedding.OpenAiEmbeddingClient; -import org.springframework.ai.openai.testutils.AbstractIntegrationTest; +import org.springframework.ai.openai.testutils.AbstractIT; import org.springframework.ai.prompt.Prompt; import org.springframework.ai.prompt.SystemPromptTemplate; import org.springframework.ai.prompt.messages.Message; @@ -28,9 +28,9 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest -public class AcmeIntegrationTest extends AbstractIntegrationTest { +public class AcmeIT extends AbstractIT { - private static final Logger logger = LoggerFactory.getLogger(AcmeIntegrationTest.class); + private static final Logger logger = LoggerFactory.getLogger(AcmeIT.class); @Value("classpath:/data/acme/bikes.json") private Resource bikesResource; diff --git a/spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIntegrationTests.java b/spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIT.java similarity index 96% rename from spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIntegrationTests.java rename to spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIT.java index 5a07d2ce9..05a15cdbd 100644 --- a/spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIntegrationTests.java +++ b/spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIT.java @@ -3,7 +3,7 @@ package org.springframework.ai.openai.client; import org.junit.jupiter.api.Test; import org.springframework.ai.client.AiResponse; import org.springframework.ai.client.Generation; -import org.springframework.ai.openai.testutils.AbstractIntegrationTest; +import org.springframework.ai.openai.testutils.AbstractIT; import org.springframework.ai.parser.BeanOutputParser; import org.springframework.ai.parser.ListOutputParser; import org.springframework.ai.parser.MapOutputParser; @@ -24,7 +24,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest -class ClientIntegrationTests extends AbstractIntegrationTest { +class ClientIT extends AbstractIT { @Value("classpath:/prompts/system-message.st") private Resource systemResource; diff --git a/spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/EmbeddingIntegrationTest.java b/spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/EmbeddingIT.java similarity index 97% rename from spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/EmbeddingIntegrationTest.java rename to spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/EmbeddingIT.java index afb4165ea..5011134b3 100644 --- a/spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/EmbeddingIntegrationTest.java +++ b/spring-ai-openai/src/test/java/org/springframework/ai/openai/embedding/EmbeddingIT.java @@ -10,7 +10,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest -class EmbeddingIntegrationTest { +class EmbeddingIT { @Autowired private OpenAiEmbeddingClient embeddingClient; diff --git a/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIntegrationTest.java b/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java similarity index 97% rename from spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIntegrationTest.java rename to spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java index 0d3bd07ff..1c06eb36e 100644 --- a/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIntegrationTest.java +++ b/spring-ai-openai/src/test/java/org/springframework/ai/openai/testutils/AbstractIT.java @@ -18,9 +18,9 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -public class AbstractIntegrationTest { +public abstract class AbstractIT { - private static final Logger logger = LoggerFactory.getLogger(AbstractIntegrationTest.class); + private static final Logger logger = LoggerFactory.getLogger(AbstractIT.class); @Autowired protected OpenAiClient openAiClient; diff --git a/vector-stores/spring-ai-pgvector-store/README.md b/vector-stores/spring-ai-pgvector-store/README.md new file mode 100644 index 000000000..05bd0edfc --- /dev/null +++ b/vector-stores/spring-ai-pgvector-store/README.md @@ -0,0 +1,16 @@ + +# PGvector VectorStore + +Pgvector is an open-source extension for PostgreSQL that enables storing and searching over machine learning-generated embeddings. It provides different capabilities that let users identify both exact and approximate nearest neighbors. It is designed to work seamlessly with other PostgreSQL features, including indexing and querying. + +## Start Postgres+PGVecgor DB: + +``` +docker run -it --rm --name postgres -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres ankane/pgvector +``` + +You can connect to this server like this: + +``` +psql -U postgres -h localhost -p 5432 +``` \ No newline at end of file diff --git a/vector-stores/spring-ai-pgvector-store/pom.xml b/vector-stores/spring-ai-pgvector-store/pom.xml new file mode 100644 index 000000000..b640e5ae4 --- /dev/null +++ b/vector-stores/spring-ai-pgvector-store/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + org.springframework.experimental.ai + spring-ai + 0.2.0-SNAPSHOT + ../../pom.xml + + spring-ai-pgvector-store + jar + Spring AI Vector Store - pgvector + Spring AI PGVector Vector Store + https://github.com/spring-projects-experimental/spring-ai + + + https://github.com/spring-projects-experimental/spring-ai + git://github.com/spring-projects-experimental/spring-ai.git + git@github.com:spring-projects-experimental/spring-ai.git + + + + 0.1.3 + 42.6.0 + 0.2.0-SNAPSHOT + + 1.19.0 + 4.0.3 + + + + + org.springframework.experimental.ai + spring-ai-core + ${spring-ai.version} + + + + + com.pgvector + pgvector + ${pgvector.version} + + + + org.postgresql + postgresql + ${postgresql.version} + + + + org.springframework + spring-jdbc + + + + + org.springframework.experimental.ai + spring-ai-openai-spring-boot-starter + ${spring-ai.version} + test + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.testcontainers + testcontainers + ${testcontainers.version} + test + + + + org.testcontainers + junit-jupiter + ${testcontainers.version} + test + + + + com.zaxxer + HikariCP + ${hikari-cp.version} + test + + + + + diff --git a/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java b/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java new file mode 100644 index 000000000..e3b3a50b0 --- /dev/null +++ b/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java @@ -0,0 +1,261 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.ai.vectorstore; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.pgvector.PGvector; +import org.postgresql.util.PGobject; + +import org.springframework.ai.document.Document; +import org.springframework.ai.embedding.EmbeddingClient; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; + +/** + * @author Christian Tzolov + */ +public class PgVectorStore implements VectorStore { + + public static final int OPENAI_EMBEDDING_DIMENSION_SIZE = 1536; + + private final JdbcTemplate jdbcTemplate; + + private final EmbeddingClient embeddingClient; + + private int dimensions; + + private PgDistanceType distanceType; + + private ObjectMapper objectMapper = new ObjectMapper(); + + /** + * By default, pgvector performs exact nearest neighbor search, which provides perfect + * recall. You can add an index to use approximate nearest neighbor search, which + * trades some recall for speed. Unlike typical indexes, you will see different + * results for queries after adding an approximate index. + */ + public enum PgIndexType { + + /** + * Performs exact nearest neighbor search, which provides perfect recall. + */ + NONE, + /** + * An IVFFlat index divides vectors into lists, and then searches a subset of + * those lists that are closest to the query vector. It has faster build times and + * uses less memory than HNSW, but has lower query performance (in terms of + * speed-recall tradeoff). + */ + IVFFLAT, + /** + * An HNSW index creates a multilayer graph. It has slower build times and uses + * more memory than IVFFlat, but has better query performance (in terms of + * speed-recall tradeoff). There’s no training step like IVFFlat, so the index can + * be created without any data in the table. + */ + HNSW; + + } + + public enum PgDistanceType { + + EuclideanDistance("<->", "vector_l2_ops"), + + NegativeInnerProduct("<#>", "vector_ip_ops"), + + CosineDistance("<=>", "vector_cosine_ops"); + + public final String operator; + + public final String index; + + PgDistanceType(String operator, String index) { + this.operator = operator; + this.index = index; + } + + } + + private static class DocumentRowMapper implements RowMapper { + + private static final String COLUMN_EMBEDDING = "embedding"; + + private static final String COLUMN_METADATA = "metadata"; + + private static final String COLUMN_ID = "id"; + + private static final String COLUMN_CONTENT = "content"; + + private ObjectMapper objectMapper; + + public DocumentRowMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public Document mapRow(ResultSet rs, int rowNum) throws SQLException { + String id = rs.getString(COLUMN_ID); + String content = rs.getString(COLUMN_CONTENT); + PGobject metadata = rs.getObject(COLUMN_METADATA, PGobject.class); + PGobject embedding = rs.getObject(COLUMN_EMBEDDING, PGobject.class); + + Document document = new Document(id, content, toMap(metadata)); + document.setEmbedding(toDoubleList(embedding)); + + return document; + } + + private List toDoubleList(PGobject embedding) throws SQLException { + float[] floatArray = new PGvector(embedding.getValue()).toArray(); + List doubleEmbedding = IntStream.range(0, floatArray.length) + .mapToDouble(i -> floatArray[i]) + .boxed() + .collect(Collectors.toList()); + return doubleEmbedding; + + } + + private Map toMap(PGobject pgObject) { + + String source = pgObject.getValue(); + try { + return (Map) objectMapper.readValue(source, Map.class); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + } + + public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingClient embeddingClient) { + this(jdbcTemplate, embeddingClient, OPENAI_EMBEDDING_DIMENSION_SIZE, + PgVectorStore.PgDistanceType.CosineDistance, false, PgIndexType.NONE); + } + + public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingClient embeddingClient, int dimensions, + PgDistanceType distanceType, boolean removeExistingVectorStoreTable, PgIndexType createIndexMethod) { + this.jdbcTemplate = jdbcTemplate; + this.embeddingClient = embeddingClient; + this.dimensions = dimensions; + this.distanceType = distanceType; + + // Add PGVector support. + this.jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS vector"); + // Add JSONB support. + this.jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS hstore"); + // Add UUID support. + this.jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\""); + + // Remove existing VectorStoreTable + if (removeExistingVectorStoreTable) { + this.jdbcTemplate.execute("DROP TABLE IF EXISTS vector_store"); + } + + // TODO: we create id of type UUID, while the Document's id is String!!! + // TODO: remove injection! + this.jdbcTemplate + .execute("CREATE TABLE IF NOT EXISTS vector_store ( " + "id uuid DEFAULT uuid_generate_v4 () PRIMARY KEY, " + + "content text, " + "metadata json, " + "embedding vector(" + this.dimensions + "))"); + + if (createIndexMethod != PgIndexType.NONE) { + this.jdbcTemplate.execute("CREATE INDEX ON vector_store USING " + createIndexMethod.name() + " (embedding " + + distanceType.index + ")"); + } + + this.jdbcTemplate + .execute("CREATE TABLE IF NOT EXISTS vector_store ( " + "id uuid DEFAULT uuid_generate_v4 () PRIMARY KEY, " + + "content text, " + "metadata json, " + "embedding vector(" + this.dimensions + "))"); + } + + @Override + public void add(List documents) { + for (Document document : documents) { + List embedding = this.embeddingClient.embed(document); + document.setEmbedding(embedding); + + UUID id = UUID.fromString(document.getId()); + String content = document.getText(); // TODO: shall we use the text of text + + // metadata? + Map metadata = document.getMetadata(); + PGvector pgEmbedding = new PGvector(toFloatArray(embedding)); + + jdbcTemplate.update( + "INSERT INTO vector_store (id, content, metadata, embedding) VALUES (?, ?, ?::jsonb, ?) " + + "ON CONFLICT (id) DO " + "UPDATE SET content = ? , metadata = ?::jsonb , embedding = ? ", + id, content, metadata, pgEmbedding, content, metadata, pgEmbedding); + } + } + + private float[] toFloatArray(List embeddingDouble) { + float[] embeddingFloat = new float[embeddingDouble.size()]; + int i = 0; + for (Double d : embeddingDouble) { + embeddingFloat[i++] = d.floatValue(); + } + return embeddingFloat; + } + + @Override + public Optional delete(List idList) { + int updateCount = 0; + for (String id : idList) { + int count = jdbcTemplate.update("DELETE FROM vector_store WHERE id = ?", UUID.fromString(id)); + + updateCount = updateCount + count; + } + + return Optional.of(updateCount == idList.size()); + } + + @Override + public List similaritySearch(String query) { + return this.similaritySearch(query, 4); + } + + @Override + public List similaritySearch(String query, int k) { + PGvector queryEmbedding = getQueryEmbedding(query); + return this.jdbcTemplate.query( + "SELECT * FROM vector_store ORDER BY embedding " + this.distanceType.operator + " ? LIMIT ?", + new DocumentRowMapper(this.objectMapper), queryEmbedding, k); + } + + @Override + public List similaritySearch(String query, int k, double threshold) { + PGvector queryEmbedding = getQueryEmbedding(query); + return this.jdbcTemplate.query( + "SELECT * FROM vector_store ORDER BY embedding " + this.distanceType.operator + " ? < ? LIMIT ? ", + new DocumentRowMapper(this.objectMapper), queryEmbedding, threshold, k); + } + + private PGvector getQueryEmbedding(String query) { + List embedding = this.embeddingClient.embed(query); + return new PGvector(toFloatArray(embedding)); + } + +} \ No newline at end of file diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java new file mode 100644 index 000000000..03453cfc3 --- /dev/null +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java @@ -0,0 +1,173 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.ai.vectorstore; + +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import javax.sql.DataSource; + +import com.zaxxer.hikari.HikariDataSource; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; +import org.springframework.ai.document.Document; +import org.springframework.ai.embedding.EmbeddingClient; +import org.springframework.ai.vectorstore.PgVectorStore.PgIndexType; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.core.JdbcTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Christian Tzolov + */ +@Testcontainers +public class PgVectorStoreIT { + + @Container + static GenericContainer postgresContainer = new GenericContainer<>("ankane/pgvector") + .withEnv("POSTGRES_USER", "postgres") + .withEnv("POSTGRES_PASSWORD", "postgres") + .withExposedPorts(5432); + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(TestApplication.class) + .withPropertyValues("spring.datasource.type=com.zaxxer.hikari.HikariDataSource", + "spring.ai.openai.apiKey=" + System.getenv("SPRING_AI_OPENAI_API_KEY"), + + // JdbcTemplate configuration + String.format("app.datasource.url=jdbc:postgresql://localhost:%d/%s", + postgresContainer.getMappedPort(5432), "postgres"), + "app.datasource.username=postgres", "app.datasource.password=postgres", + "app.datasource.type=com.zaxxer.hikari.HikariDataSource"); + + @Test + public void vectorStoreTest() { + contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAutoConfiguration.class)).run(context -> { + + VectorStore vectorStore = context.getBean(VectorStore.class); + + List documents = List.of( + new Document( + "Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", + Collections.singletonMap("meta1", "meta1")), + new Document("Hello World Hello World Hello World Hello World Hello World Hello World Hello World"), + new Document( + "Great Depression Great Depression Great Depression Great Depression Great Depression Great Depression", + Collections.singletonMap("meta2", "meta2"))); + + vectorStore.add(documents); + + List results = vectorStore.similaritySearch("Great", 1); + + assertThat(results).hasSize(1); + Document resultDoc = results.get(0); + assertThat(resultDoc.getId()).isEqualTo(documents.get(2).getId()); + assertThat(resultDoc.getText()).isEqualTo( + "Great Depression Great Depression Great Depression Great Depression Great Depression Great Depression"); + assertThat(resultDoc.getMetadata()).isEqualTo(Collections.singletonMap("meta2", "meta2")); + + // Remove all documents from the store + vectorStore.delete(documents.stream().map(doc -> doc.getId()).collect(Collectors.toList())); + + List results2 = vectorStore.similaritySearch("Great", 1); + assertThat(results2).hasSize(0); + + }); + } + + @Test + public void documentUpdateTest() { + + contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAutoConfiguration.class)).run(context -> { + + VectorStore vectorStore = context.getBean(VectorStore.class); + + Document document = new Document(UUID.randomUUID().toString(), "Spring AI rocks!!", + Collections.singletonMap("meta1", "meta1")); + + vectorStore.add(List.of(document)); + + List results = vectorStore.similaritySearch("Spring", 5); + + assertThat(results).hasSize(1); + Document resultDoc = results.get(0); + assertThat(resultDoc.getId()).isEqualTo(document.getId()); + assertThat(resultDoc.getText()).isEqualTo("Spring AI rocks!!"); + assertThat(resultDoc.getMetadata()).isEqualTo(Collections.singletonMap("meta1", "meta1")); + + Document sameIdDocument = new Document(document.getId(), + "The World is Big and Salvation Lurks Around the Corner", + Collections.singletonMap("meta2", "meta2")); + + vectorStore.add(List.of(sameIdDocument)); + + results = vectorStore.similaritySearch("FooBar", 5); + + assertThat(results).hasSize(1); + resultDoc = results.get(0); + assertThat(resultDoc.getId()).isEqualTo(document.getId()); + assertThat(resultDoc.getText()).isEqualTo("The World is Big and Salvation Lurks Around the Corner"); + assertThat(resultDoc.getMetadata()).isEqualTo(Collections.singletonMap("meta2", "meta2")); + + }); + } + + @SpringBootConfiguration + @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) + public static class TestApplication { + + @Bean + public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingClient embeddingClient) { + return new PgVectorStore(jdbcTemplate, embeddingClient, 1536, PgVectorStore.PgDistanceType.CosineDistance, + true, PgIndexType.HNSW); + } + + @Bean + public JdbcTemplate myJdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean + @Primary + @ConfigurationProperties("app.datasource") + public DataSourceProperties dataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + public HikariDataSource dataSource(DataSourceProperties dataSourceProperties) { + return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); + } + + } + +}