Java SpringAI

Spring AI Vector Stores and Embeddings — Store and Search Semantic Vectors

Spring AI Vector Stores and Embeddings — Store and Search Semantic Vectors

Embeddings are the foundation of semantic search and RAG. An embedding model converts text into a dense float array (a vector) where semantically similar sentences produce vectors that are close together in high-dimensional space. Spring AI provides a uniform VectorStore API that works across multiple backends — PGVector, ChromaDB, Pinecone, Redis, and an in-memory store for development.

What is an Embedding?

"Java is a programming language"   → [0.023, -0.417, 0.891, ... ] (1536 numbers)
"Java programming tutorial"        → [0.019, -0.401, 0.887, ... ] (very similar vector)
"How to make pizza"                → [0.741, 0.233, -0.102, ... ] (very different vector)

Cosine similarity:
  "Java is a language" vs "Java programming tutorial" → 0.95 (very similar)
  "Java is a language" vs "How to make pizza"         → 0.12 (unrelated)

Dependencies — SimpleVectorStore (No External DB)

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
# application.properties
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.embedding.options.model=text-embedding-3-small

EmbeddingModel — Convert Text to Vectors

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.EmbeddingResponse;

@Service
public class EmbeddingService {

    private final EmbeddingModel embeddingModel;

    public EmbeddingService(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    public float[] embed(String text) {
        EmbeddingResponse response = embeddingModel.embedForResponse(List.of(text));
        return response.getResult().getOutput();
    }

    public void showEmbeddingInfo(String text) {
        float[] vector = embed(text);
        System.out.println("Text      : " + text);
        System.out.println("Dimensions: " + vector.length);
        System.out.printf("First 5   : [%.4f, %.4f, %.4f, %.4f, %.4f]%n",
                vector[0], vector[1], vector[2], vector[3], vector[4]);
    }
}

Output

Text      : Spring Boot makes Java development easy
Dimensions: 1536
First 5   : [0.0123, -0.4178, 0.8912, 0.0234, -0.2341]

SimpleVectorStore — In-Memory (Development)

import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.document.Document;

@Configuration
public class VectorStoreConfig {

    @Bean
    public VectorStore vectorStore(EmbeddingModel embeddingModel) {
        return new SimpleVectorStore(embeddingModel);
    }
}

@Service
public class KnowledgeBaseService {

    private final VectorStore vectorStore;

    public KnowledgeBaseService(VectorStore vectorStore) {
        this.vectorStore = vectorStore;
    }

    public void addDocuments(List<String> texts) {
        List<Document> documents = texts.stream()
                .map(Document::new)
                .toList();
        vectorStore.add(documents);
        System.out.println("Added " + documents.size() + " documents");
    }

    public List<Document> search(String query, int topK) {
        return vectorStore.similaritySearch(
                SearchRequest.query(query)
                        .withTopK(topK)
                        .withSimilarityThreshold(0.7)   // only results above 70% similarity
        );
    }
}

Full Add and Search Example

@SpringBootApplication
public class VectorStoreDemo implements CommandLineRunner {

    @Autowired KnowledgeBaseService kb;

    @Override
    public void run(String... args) {
        // 1. Index documents
        kb.addDocuments(List.of(
            "Spring Boot auto-configures your application based on classpath dependencies",
            "Spring Data JPA provides CRUD repositories for database access",
            "Spring Security handles authentication and authorization in web applications",
            "Spring Cloud enables microservices patterns like service discovery and circuit breakers",
            "Hibernate is the default JPA implementation in Spring Boot"
        ));

        // 2. Semantic search
        List<Document> results = kb.search("How do I connect to a database?", 3);

        System.out.println("Top 3 results:");
        results.forEach(doc -> System.out.println("  - " + doc.getContent()));
    }
}

Output

Added 5 documents

Top 3 results:
  - Spring Data JPA provides CRUD repositories for database access
  - Hibernate is the default JPA implementation in Spring Boot
  - Spring Boot auto-configures your application based on classpath dependencies

Document Metadata — Filter Search Results

// Add documents with metadata
List<Document> docs = List.of(
    new Document("Spring Boot REST API tutorial",
            Map.of("category", "spring-boot", "difficulty", "beginner")),
    new Document("Spring AI RAG implementation guide",
            Map.of("category", "spring-ai", "difficulty", "advanced")),
    new Document("Java Stream API examples",
            Map.of("category", "java", "difficulty", "intermediate"))
);
vectorStore.add(docs);

// Filter: only return Spring AI documents
List<Document> results = vectorStore.similaritySearch(
        SearchRequest.query("AI retrieval")
                .withTopK(3)
                .withFilterExpression("category == 'spring-ai'")
);

Save and Load SimpleVectorStore to Disk

// Save
SimpleVectorStore store = (SimpleVectorStore) vectorStore;
store.save(new File("knowledge-base.json"));

// Load
store.load(new File("knowledge-base.json"));
System.out.println("Loaded vector store from disk");

Key Points

  • Use text-embedding-3-small (1536 dimensions) for a good balance of cost and quality; text-embedding-3-large for maximum accuracy
  • SimpleVectorStore is in-memory only — data is lost on restart; use PGVector or ChromaDB for production
  • withSimilarityThreshold(0.7) filters out low-relevance results — tune this for your use case
  • Always use the same embedding model for indexing and querying — mixing models produces wrong similarity scores
  • Document metadata enables filtered search — store category, date, source, or access level as metadata
Topics: Java SpringAI
← Newer Post Older Post →