CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-ai--spring-ai-openai

OpenAI models support for Spring AI, providing comprehensive integration for chat completion, embeddings, image generation, audio transcription, text-to-speech, and content moderation capabilities within Spring Boot applications.

Overview
Eval results
Files

embedding-models.mddocs/reference/

Embedding Models

Generate vector embeddings for text using OpenAI's embedding models for semantic search, clustering, recommendation systems, and similarity calculations.

Capabilities

OpenAiEmbeddingModel

Generates dense vector representations of text that capture semantic meaning, enabling similarity comparisons and vector-based operations.

/**
 * OpenAI embedding model implementation
 */
public class OpenAiEmbeddingModel extends AbstractEmbeddingModel {
    /**
     * Generate embedding vector for a single document
     * @param document Document to embed
     * @return float array representing the embedding vector
     */
    public float[] embed(Document document);

    /**
     * Generate embeddings for multiple inputs
     * @param request Embedding request with one or more inputs
     * @return EmbeddingResponse containing embeddings and metadata
     */
    public EmbeddingResponse call(EmbeddingRequest request);

    /**
     * Set custom observation convention for observability
     * @param observationConvention Custom observation convention
     */
    public void setObservationConvention(EmbeddingModelObservationConvention observationConvention);
}

Constructors:

// Basic constructor
public OpenAiEmbeddingModel(OpenAiApi openAiApi);

// With metadata mode
public OpenAiEmbeddingModel(
    OpenAiApi openAiApi,
    MetadataMode metadataMode
);

// With options
public OpenAiEmbeddingModel(
    OpenAiApi openAiApi,
    MetadataMode metadataMode,
    OpenAiEmbeddingOptions options
);

// With retry support
public OpenAiEmbeddingModel(
    OpenAiApi openAiApi,
    MetadataMode metadataMode,
    OpenAiEmbeddingOptions options,
    RetryTemplate retryTemplate
);

// Full constructor with observability
public OpenAiEmbeddingModel(
    OpenAiApi openAiApi,
    MetadataMode metadataMode,
    OpenAiEmbeddingOptions options,
    RetryTemplate retryTemplate,
    ObservationRegistry observationRegistry
);

Note: OpenAiEmbeddingModel uses constructor-based initialization only. Unlike OpenAiChatModel, it does not provide a builder pattern. Use the appropriate constructor based on your configuration needs.

Usage Example:

import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.OpenAiEmbeddingOptions;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingRequest;

// Create API client
var openAiApi = OpenAiApi.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .build();

// Create embedding model
var embeddingModel = new OpenAiEmbeddingModel(
    openAiApi,
    MetadataMode.EMBED,
    OpenAiEmbeddingOptions.builder()
        .model(OpenAiApi.EmbeddingModel.TEXT_EMBEDDING_3_SMALL.getValue())
        .build()
);

// Generate single embedding
var document = new Document("The quick brown fox jumps over the lazy dog");
float[] embedding = embeddingModel.embed(document);
System.out.println("Embedding dimensions: " + embedding.length);

// Generate multiple embeddings
var request = new EmbeddingRequest(
    List.of("First text", "Second text", "Third text"),
    OpenAiEmbeddingOptions.builder()
        .model(OpenAiApi.EmbeddingModel.TEXT_EMBEDDING_3_LARGE.getValue())
        .dimensions(1024)  // Reduce dimensions for efficiency
        .build()
);
var response = embeddingModel.call(request);
response.getData().forEach(emb -> {
    System.out.println("Embedding: " + Arrays.toString(emb.getEmbedding()));
});

Calculating Similarity:

// Cosine similarity between two embeddings
public static double cosineSimilarity(float[] a, float[] b) {
    double dotProduct = 0.0;
    double normA = 0.0;
    double normB = 0.0;
    for (int i = 0; i < a.length; i++) {
        dotProduct += a[i] * b[i];
        normA += a[i] * a[i];
        normB += b[i] * b[i];
    }
    return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}

// Compare documents
var doc1Embedding = embeddingModel.embed(new Document("Machine learning is fascinating"));
var doc2Embedding = embeddingModel.embed(new Document("AI and ML are interesting topics"));
var doc3Embedding = embeddingModel.embed(new Document("I love pizza"));

double similarity12 = cosineSimilarity(doc1Embedding, doc2Embedding);
double similarity13 = cosineSimilarity(doc1Embedding, doc3Embedding);

System.out.println("ML vs AI similarity: " + similarity12);  // High similarity
System.out.println("ML vs Pizza similarity: " + similarity13);  // Low similarity

OpenAiEmbeddingOptions

Configuration options for embedding generation requests.

/**
 * Configuration options for OpenAI embedding requests
 */
public class OpenAiEmbeddingOptions implements EmbeddingOptions {
    /**
     * Create a new builder for embedding options
     * @return Builder instance
     */
    public static Builder builder();

    /**
     * Get the embedding model identifier
     * @return Model name
     */
    public String getModel();
    public void setModel(String model);

    /**
     * Get the encoding format for embeddings
     * @return "float" or "base64"
     */
    public String getEncodingFormat();
    public void setEncodingFormat(String encodingFormat);

    /**
     * Get the number of dimensions for the embedding (v3 models only)
     * @return Dimension count or null for default
     */
    public Integer getDimensions();
    public void setDimensions(Integer dimensions);

    /**
     * Get the user identifier for tracking/abuse prevention
     * @return User ID
     */
    public String getUser();
    public void setUser(String user);
}

Builder Pattern:

public static class Builder {
    public Builder model(String model);
    public Builder encodingFormat(String encodingFormat);
    public Builder dimensions(Integer dimensions);
    public Builder user(String user);
    public OpenAiEmbeddingOptions build();
}

Usage Example:

// text-embedding-ada-002 (legacy model, 1536 dimensions, fixed)
var adaOptions = OpenAiEmbeddingOptions.builder()
    .model(OpenAiApi.EmbeddingModel.TEXT_EMBEDDING_ADA_002.getValue())
    .build();

// text-embedding-3-small (default 1536 dimensions, adjustable)
var small3Options = OpenAiEmbeddingOptions.builder()
    .model(OpenAiApi.EmbeddingModel.TEXT_EMBEDDING_3_SMALL.getValue())
    .dimensions(512)  // Reduce for efficiency, range: 1-1536
    .build();

// text-embedding-3-large (default 3072 dimensions, adjustable)
var large3Options = OpenAiEmbeddingOptions.builder()
    .model(OpenAiApi.EmbeddingModel.TEXT_EMBEDDING_3_LARGE.getValue())
    .dimensions(1024)  // Reduce for efficiency, range: 1-3072
    .encodingFormat("float")  // or "base64"
    .user("user-123")
    .build();

Configuration Parameters Reference

Model (String)

Embedding model identifier:

  • text-embedding-ada-002: Legacy model, 1536 dimensions (fixed), lower cost
  • text-embedding-3-small: New model, up to 1536 dimensions (adjustable), better performance than ada-002
  • text-embedding-3-large: Most capable model, up to 3072 dimensions (adjustable), highest performance

Dimensions (Integer)

Number of dimensions in the output embedding vector (v3 models only):

  • Allows trading off embedding size vs performance
  • Smaller dimensions = lower storage costs and faster similarity calculations
  • Larger dimensions = more semantic information captured
  • text-embedding-3-small: Range 1-1536, default 1536
  • text-embedding-3-large: Range 1-3072, default 3072
  • Not applicable to text-embedding-ada-002 (always 1536)

Encoding Format (String)

Format for the embedding vector:

  • "float": Array of floats (default, recommended for most use cases)
  • "base64": Base64-encoded string representation (more compact over network)

User (String)

Unique identifier for end-user for tracking and abuse monitoring


Types

Request Types

// High-level embedding request (from spring-ai-core)
public class EmbeddingRequest {
    public EmbeddingRequest(List<String> inputs, EmbeddingOptions options);
    public List<String> getInstructions();
    public EmbeddingOptions getOptions();
}

// Low-level embedding request
public record EmbeddingRequest<T>(
    T input,                             // String or List<String>
    String model,                        // Model identifier
    String encodingFormat,               // "float" or "base64"
    Integer dimensions,                  // Output dimensions (v3 models)
    String user                          // User identifier
) {}

Response Types

// High-level embedding response (from spring-ai-core)
public interface EmbeddingResponse {
    List<Embedding> getData();
    EmbeddingResponseMetadata getMetadata();
}

public class Embedding {
    public float[] getEmbedding();
    public Integer getIndex();
    public Object getObject();
}

// Low-level embedding response
public record EmbeddingList<T>(
    String object,                       // "list"
    List<Embedding> data,                // Embedding results
    String model,                        // Model used
    Usage usage                          // Token usage
) {}

public record Embedding(
    Integer index,                       // Result index
    float[] embedding,                   // Embedding vector
    String object                        // "embedding"
) {}

Metadata Types

public class EmbeddingResponseMetadata {
    public String getModel();
    public Usage getUsage();
}

public record Usage(
    Integer promptTokens,                // Input token count
    Integer totalTokens                  // Total token count
) {}

Model Enums

public enum OpenAiApi.EmbeddingModel {
    TEXT_EMBEDDING_ADA_002("text-embedding-ada-002"),
    TEXT_EMBEDDING_3_SMALL("text-embedding-3-small"),
    TEXT_EMBEDDING_3_LARGE("text-embedding-3-large");

    public String getValue();
}

Metadata Mode

// From spring-ai-core, controls document metadata inclusion
public enum MetadataMode {
    ALL,      // Include all metadata in embedding
    EMBED,    // Include only embedding-relevant metadata
    NONE      // Exclude all metadata
}

Common Use Cases

Semantic Search

// Index documents
List<Document> documents = loadDocuments();
Map<Document, float[]> index = new HashMap<>();

for (Document doc : documents) {
    float[] embedding = embeddingModel.embed(doc);
    index.put(doc, embedding);
}

// Search query
String query = "How do I reset my password?";
float[] queryEmbedding = embeddingModel.embed(new Document(query));

// Find most similar documents
List<Map.Entry<Document, Double>> results = index.entrySet().stream()
    .map(entry -> Map.entry(
        entry.getKey(),
        cosineSimilarity(queryEmbedding, entry.getValue())
    ))
    .sorted(Map.Entry.<Document, Double>comparingByValue().reversed())
    .limit(5)
    .toList();

Document Clustering

// Generate embeddings for all documents
List<float[]> embeddings = documents.stream()
    .map(embeddingModel::embed)
    .toList();

// Use clustering algorithm (e.g., K-means) on embeddings
// to group semantically similar documents

Recommendation System

// Embed user preferences
float[] userProfile = embeddingModel.embed(
    new Document(String.join(" ", userLikedItems))
);

// Find similar items
List<Item> recommendations = allItems.stream()
    .map(item -> {
        float[] itemEmbedding = embeddingModel.embed(new Document(item.getDescription()));
        double similarity = cosineSimilarity(userProfile, itemEmbedding);
        return new ScoredItem(item, similarity);
    })
    .sorted(Comparator.comparing(ScoredItem::score).reversed())
    .limit(10)
    .map(ScoredItem::item)
    .toList();

Duplicate Detection

// Find near-duplicate documents
double threshold = 0.95;  // Very high similarity

for (int i = 0; i < documents.size(); i++) {
    for (int j = i + 1; j < documents.size(); j++) {
        float[] emb1 = embeddingModel.embed(documents.get(i));
        float[] emb2 = embeddingModel.embed(documents.get(j));
        double similarity = cosineSimilarity(emb1, emb2);

        if (similarity > threshold) {
            System.out.println("Potential duplicate: " + i + " and " + j);
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-ai--spring-ai-openai

docs

index.md

tile.json