Spring AI Embeddings Tutorial

Introduction

Embeddings transform text into numerical arrays or vectors, enabling AI models to process and interpret language data. This transformation from text to numbers and back is crucial for how AI interacts with and understands human language. As a Java developer exploring AI, it’s not necessary to comprehend the intricate mathematical theories or the specific implementations behind these vector representations. A basic understanding of their role and function within AI systems suffices, particularly when you’re integrating AI functionalities into your applications.

Embeddings are particularly relevant in practical applications like the Retrieval Augmented Generation (RAG) pattern. They represent data as points in a semantic space, where the proximity of points reflects the similarity in meaning. This aids in tasks like text classification, semantic search, and product recommendations, as it allows the AI to discern and group related concepts based on their 'location' in this expanded semantic landscape.

What are Spring AI Embeddings?

Embedding APIs can convert words, sentences, documents, or images into embeddings. An embedding is a vector representation of these elements. For example:

  • A word "Apple" might be represented as a vector [0.1, 0.2, 0.3, 0.4, 0.5].
  • A sentence "I love Apple" might be represented as a vector [0.1, 10.3, -10.2, 90.3, 2.4, -0.5].

Spring AI provides an EmbeddingClient interface to convert text or documents into embeddings. You can use any of the supported EmbeddingClient implementations like OpenAiEmbeddingClient, OllamaEmbeddingClient, AzureOpenAiEmbeddingClient, VertexAiEmbeddingClient, etc.

How to Use Spring AI Embeddings

Step 1: Setting Up the Project

Use Spring Initializr to create a new Spring Boot project. Include dependencies for Spring Web and Spring AI.

Using Spring Initializr:

  • Go to start.spring.io
  • Select:
    • Project: Maven Project
    • Language: Java
    • Spring Boot: 3.0.0 (or latest)
    • Dependencies: Spring Web
  • Generate the project and unzip it.

Step 2: Add Dependencies

In your project's pom.xml, add the necessary dependencies for Spring AI.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

Step 3: Configure API Key

Add your OpenAI API key to application.properties or application.yml.

For application.properties:

openai.api.key=your_openai_api_key

For application.yml:

openai:
  api:
    key: your_openai_api_key

Step 4: Configure Spring Beans

Create a configuration class to set up the necessary Spring beans, including the OpenAiClient.

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.openai.OpenAiClient;
import org.springframework.ai.openai.OpenAiEmbeddingClient;
import org.springframework.ai.embeddings.EmbeddingClient;

@Configuration
public class AppConfig {

    @Bean
    public OpenAiClient openAiClient() {
        return new OpenAiClient();
    }

    @Bean
    public EmbeddingClient embeddingClient(OpenAiClient openAiClient) {
        return new OpenAiEmbeddingClient(openAiClient);
    }
}

Step 5: Create a Service for Embeddings

Create a service to generate embeddings for given text inputs.

package com.example.demo.service;

import org.springframework.ai.embeddings.EmbeddingClient;
import org.springframework.ai.embeddings.EmbeddingRequest;
import org.springframework.ai.embeddings.EmbeddingResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmbeddingService {

    private final EmbeddingClient embeddingClient;

    @Autowired
    public EmbeddingService(EmbeddingClient embeddingClient) {
        this.embeddingClient = embeddingClient;
    }

    public List<Double> generateEmbedding(String text) {
        EmbeddingRequest request = new EmbeddingRequest();
        request.setInput(text);

        EmbeddingResponse response = embeddingClient.createEmbedding(request);
        return response.getData().get(0).getEmbedding();
    }
}

Step 6: Create a Controller to Expose the Service

Create a controller to expose an endpoint for generating embeddings.

package com.example.demo.controller;

import com.example.demo.service.EmbeddingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class EmbeddingController {

    private final EmbeddingService embeddingService;

    @Autowired
    public EmbeddingController(EmbeddingService embeddingService) {
        this.embeddingService = embeddingService;
    }

    @GetMapping("/generateEmbedding")
    public List<Double> generateEmbedding(@RequestParam String text) {
        return embeddingService.generateEmbedding(text);
    }
}

Step 7: Using ChatClient with Embeddings

To use embeddings within a chat interaction, you can integrate the ChatClient as follows:

package com.example.demo.service;

import org.springframework.ai.embeddings.EmbeddingClient;
import org.springframework.ai.embeddings.EmbeddingRequest;
import org.springframework.ai.embeddings.EmbeddingResponse;
import org.springframework.ai.openai.ChatClient;
import org.springframework.ai.openai.model.ChatMessage;
import org.springframework.ai.openai.model.ChatRequest;
import org.springframework.ai.openai.model.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ChatEmbeddingService {

    private final EmbeddingClient embeddingClient;
    private final ChatClient chatClient;

    @Autowired
    public ChatEmbeddingService(EmbeddingClient embeddingClient, ChatClient chatClient) {
        this.embeddingClient = embeddingClient;
        this.chatClient = chatClient;
    }

    public String chatWithEmbedding(String text) {
        EmbeddingRequest request = new EmbeddingRequest();
        request.setInput(text);

        EmbeddingResponse embeddingResponse = embeddingClient.createEmbedding(request);
        List<Double> embedding = embeddingResponse.getData().get(0).getEmbedding();

        ChatMessage userMessage = new ChatMessage("user", text);
        ChatMessage embeddingMessage = new ChatMessage("system", "Embedding: " + embedding.toString());

        ChatRequest chatRequest = new ChatRequest();
        chatRequest.setMessages(List.of(userMessage, embeddingMessage));

        ChatResponse chatResponse = chatClient.sendMessage(chatRequest);
        return chatResponse.getReply();
    }
}

4. Testing the Integration

Step 1: Run the Application

Run your Spring Boot application. Ensure the application starts without errors.

Step 2: Access the Embedding Endpoint

Use Postman, curl, or your browser to test the endpoint. For example:

http://localhost:8080/generateEmbedding?text=Artificial Intelligence is transforming the world.

Step 3: Access the Chat with Embedding Endpoint

Test the chat interaction with embedding.

http://localhost:8080/chatWithEmbedding?text=Explain the concept of embeddings.

You should receive responses with the numerical array (vector) representing the embedding of the provided text and the AI's response to the chat request.

Conclusion

This tutorial demonstrated how to set up and use embeddings in a Spring Boot application with Spring AI. You learned how to configure Spring AI, generate embeddings for text inputs, and expose endpoints to interact with the AI model. Integrating embeddings with chat interactions further enhances the capabilities of your AI applications. Explore further customization and enhancements to leverage the full potential of embeddings in your Spring Boot projects.

Comments