DevTurtle logo DevTurtle

Spring AI – Integration with vector databases

guide/ Spring AI guide

Through integration with advanced AI algorithms, vector databases are no longer simple repositories of multidimensional information, but become dynamic platforms for analysis, prediction and making intelligent data-driven decisions. In this article we will see how the Spring AI framework offers a simple and intuitive solution for integrating with vector databases.

Prerequisites

For our tutorial we will use the Qdrant vector database and OpenAI’s “text-embedding-3-small” model to generate multidimensional vectors (embeddings). We therefore invite you to read our previous articles on these topics:

You can also download the source code of our tutorial from GitHub:

git icon
Git RepositoryDownload source

Vector databases compatible with Spring AI

Although we decided to use Qdrant in this tutorial, the way integration into Spring AI with vector databases works is still the same. Below is the list of compatible DBs:

You therefore have a wide choice to find the solution that best suits your needs.

Qdrant integration tutorial with Spring AI

Database connection

We begin our tutorial on integrating Qdrant into Spring AI by importing the maven dependency relating to the module that acts as the connector:

XML
<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-qdrant-store-spring-boot-starter</artifactId>
</dependency>

To allow authentication of our application to Qdrant it is necessary to generate an API Key. To do this you need to access the Qdrant Web-UI (as explained in the previous article) and click on the key icon at the top right.

Qdrant API key button
Qdrant API key button

Subsequently, in the popup that will appear you can type a key of your choice:

Qdrant api key
Qdrant api key

Once the key has been created, we can proceed with configuring Spring AI. In this regard, it is necessary to add the following lines to the application.properties file:

Plaintext
spring.ai.vectorstore.qdrant.host=localhost
spring.ai.vectorstore.qdrant.port=6334
spring.ai.vectorstore.qdrant.api-key=ewwk1201nqndkq12u14uop
spring.ai.vectorstore.qdrant.collectionname=spring-test-collection

As you can see, apart from the connection parameters (host, port and API Key), we have also defined the name of the collection to which we want to connect.

At this point, trying to start the Spring AI application, the empty collection will automatically be created and it will be possible to view it within the Web-UI.

Save the embeddings in the DB

As we have already seen in our previous tutorial, with OpenAI it is very simple to generate vector representations starting from a string. We therefore proceed by importing the dependencies from the modules:

  • “Spring Boot – Web” required for exposing a RestEndpoint
  • “Spring AI – OpenAI” required to generate embeddings
XML
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

And we implement a RestController to generate embeddings and insert them into Qdrant:

Java
package com.devturtle.springai.vectordbdemo;

import java.util.ArrayList;
import java.util.List;

import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OpenAiEmbeddingController {
	
	@Autowired 
	private VectorStore vectorStore;
	
	
	@PostMapping("/ai/embeddings/add")
    public void add(@RequestBody List<String> docs) {
		List<Document> documents = new ArrayList<Document>();
		docs.forEach((el) -> { 
			documents.add(new Document(el)); 
		});
		vectorStore.add(documents);
    } 
	
}

Once again, the code is really very simple and intuitive:

  • we define an endpoint that receives a list of strings in POST;
  • for each string we create an object of type Document;
  • we use VectorStore to insert documents into the vector database.

In all this we have never referred to OpenAI or Qdrant but Spring AI is able to automatically understand the model and the DB to use as we have imported the dependencies previously (via dependency injection). We could then easily replace both the LLM and the database.

By executing a curl on the newly created endpoint we can verify its functioning.

Plaintext
curl --location 'http://localhost:8080/ai/embeddings/add' \
--header 'Content-Type: application/json' \
--data '[
    "We will use the Qdrant vector database", 
    "With Spring AI we will generate embeddings", 
    "We will use Qdrant to save the embeddings", 
    "We will do a similarity search using Qdrant"
]'

By opening the collection via the Qdrant Web-UI we can verify that the data is present:

Qdrant collection example
Qdrant collection example

Perform similarity searches in vector databases

Having inserted the data into the collection, we can now use it to carry out similarity searches. To do this, simply define a second endpoint that takes as input a string to use as a filter for the search:

Java
@GetMapping("ai/embeddings/search")
public List<Document> search(@RequestParam(value = "query") String query) {
	
	return  vectorStore.similaritySearch(query);
	
}

Below is an example of an invocation to the search endpoint:

http://localhost:8080/ai/embeddings/search?query=Quadrant vector database

The result will be:

JSON
[
  {
    "embedding": [
      
    ],
    "content": "We will use the Qdrant vector database",
    "id": "5b4843e6-c9e4-4af0-9e7c-79d113f1d3b9",
    "metadata": {
      "distance": 0.36218166
    }
  },
  {
    "embedding": [
      
    ],
    "content": "We will do a similarity search using Qdrant",
    "id": "1b2a4f99-2be7-4d54-acf6-bc4cceed903f",
    "metadata": {
      "distance": 0.58939946
    }
  },
  {
    "embedding": [
      
    ],
    "content": "We will use Qdrant to save the embeddings",
    "id": "2a6a692e-4b71-4738-9c1e-7d4d709a249e",
    "metadata": {
      "distance": 0.6111447
    }
  },
  {
    "embedding": [
      
    ],
    "content": "With Spring AI we will generate embeddings",
    "id": "3d39f18f-4279-4dc5-aaf2-6552dbb74e8d",
    "metadata": {
      "distance": 0.80965024
    }
  }
]

As you can see, in first place (with a lower “distance” value) we find the phrase “We will use the Qdrant vector database” which contains exactly the searched string. Next are those that contain the word “Qdrant” and finally the phrase that does not contain it.

It is possible to set additional search parameters such as a distance limit value:

Java
@GetMapping("ai/embeddings/search")
public List<Document> search(@RequestParam(value = "query") String query) {
	
	return  vectorStore.similaritySearch(
				SearchRequest.defaults()
	                .withQuery(query)
	                .withSimilarityThreshold(0.5));
	
}

By doing this the query will only return the first result that has a distance value less than 0.5.

As always, I hope that the tutorial was useful in making you understand in a simple way how the integration between Spring AI and vector databases works and I invite you to read the other articles on our blog on similar topics.