编程

Spring AI 中的嵌入模型 API 指南

16 2025-06-17 00:45:00

1. 概述

将人工智能集成到应用中通常涉及处理文本数据。该领域的一项关键技术是嵌入模型,它将文本信息转换为应用可以处理的嵌入。

在本教程中,我们将探索 Spring AI 中的嵌入模型 API。这个强大的 API 提供了一种抽象,使我们能够以最小的努力轻松采用不同的嵌入模型,并促进我们的应用程序理解文本。

2. 嵌入简介

为了训练 AI 模型学习文本和图像的语义含义,我们通常将这些数据类型转换为高维向量表示,即所谓的嵌入。

AI 模型通过计算嵌入的相似度来理解它们之间的关系。当两个嵌入的相似度得分较高时,这意味着它们所表示的文本的上下文含义相似。

3. 嵌入模型 API

Spring AI 提供了一组 API 来简化我们使用嵌入模型的工作。这些 API 是隐藏所有实现细节的接口。

3.1. 嵌入模型

嵌入模型是一种经过训练的机器学习模型,它将不同类型的对象(例如段落和图像)转换为高维向量空间。

不同的提供商提供不同的模型,例如 BERT。Spring AI 嵌入 API 提供了一个 EmbeddingModel 接口,该接口封装了采用嵌入模型的细节:

public interface EmbeddingModel extends Model<EmbeddingRequest, EmbeddingResponse> {
    EmbeddingResponse call(EmbeddingRequest request);

    // constructors & other methods
}

call() 方法只是接受包含数据源的 EmbeddingRequest 并将其发送给模型提供者,返回包含 EmbeddingEmbeddingResponse

3.2. EmbeddingRequest

EmbeddingRequest 包含有效负载,其中包含要转换为嵌入(embedding)的文本列表。除了文本之外,我们还可以添加专门针对 EmbeddingModel 的其他选项:

public class EmbeddingRequest implements ModelRequest<List<String>> {
    private final List<String> inputs;
    private final EmbeddingOptions options;

    // constructors & other methods
}

3.3. EmbeddingResponse

EmbeddingResponse 封装了来自 Embedding 模型提供者的响应。它包含一个 Embedding 列表以及其他元数据,比如 token 用量:

public class EmbeddingResponse implements ModelResponse<Embedding> {
    private final List<Embedding> embeddings;
    private final EmbeddingResponseMetadata metadata;

    // constructors & other methods
}

3.4. Embedding

Embedding 包含了在 float 数组中所表示的向量。其大小取决于我们所选择的模型,可能从几百到几千:

public class Embedding implements ModelResult<float[]> {
    private final float[] embedding;
    private final Integer index;
    private final EmbeddingResultMetadata metadata;

    // constructors & other methods
}

4. 集成 OpenAI

Spring AI 将 OpenAI 作为其支持的 embedding 模型之一集成。本节中,我们将使用 OpenAI 并创建 Spring 服务以将文本转换为 embedding。

4.1. Maven 依赖

首先,让我们将如下 Spring AI Open AI 依赖添加到 pom.xml

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

4.2. Open AI 配置

要完成 OpenAI 与 Spring AI 的集成,我们需要 OpenAI 的 API 密钥:

spring:
  ai:
    openai:
      api-key: "<YOUR-API-KEY>"

4.3.  EmbeddingModel 的自动配置

Spring AI 能够自动配置该 EmbeddingModel。让我们在 application.yml 中通过添加额外的属性来定义 embedding 模型:

spring:
  ai:
    openai:
      embedding:
        options:
          model: "text-embedding-3-small"

model 属性配置了我们要使用的 embedding 模型。目前有 OpenAI 提供的三个不同模型。

一旦我们定义完这个 embedding 模型,我们就将 EmbeddingModel 注入到 Spring Boot 服务,而不必指定任何 OpenAI 详情。一切都依赖于该 Spring AI embedding API:

@Service
public class EmbeddingService {
    private final EmbeddingModel embeddingModel;

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

    public EmbeddingResponse getEmbeddings(String... texts) {
        EmbeddingRequest request = new EmbeddingRequest(Arrays.asList(texts), null);
        return embeddingModel.call(request);
    }
}

自动配置提供给我们便利,同时无需暴露实际的 Embedding 

实现。这使得我们仅仅通过更新 application.xml 就可以切换到不同的实现。

4.4. 手动配置 EmbeddingModel

虽然自动配置很方便,但在某些情况下,它无法提供给我们足够的灵活性,比如,当应用需要使用多个 Embedding 模型或者使用不同 Embedding 模型提供者来生成 Embedding 时。

对于这种情况,我们在配置类中手动定义 Embedding 模型生产者:

@Configuration
public class EmbeddingConfig {
    @Bean
    public OpenAiApi openAiApi(@Value("${spring.ai.openai.api-key}") String apiKey) {
        return OpenAiApi.builder()
          .apiKey(apiKey)
          .build();
    }

    @Bean
    public OpenAiEmbeddingModel openAiEmbeddingModel(OpenAiApi openAiApi) {
        OpenAiEmbeddingOptions options = OpenAiEmbeddingOptions.builder()
          .model("text-embedding-3-small")
          .build();
        return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, options);
    }
}

上例中,我们首先使用注入的 API 密钥 openAiApiKey 创建了一个OpenAI 客户端 - OpenAiApi。然后,我们将使用该客户端创建 OpenAI embedding 模型。

我们稍微更新了服务,以注入 OpenAIEmbeddingModel 实现,而不是 EmbeddedModel 接口:

@Service
public class ManualEmbeddingService {
    private final OpenAiEmbeddingModel openAiEmbeddingModel;

    public ManualEmbeddingService(OpenAiEmbeddingModel openAiEmbeddingModel) {
        this.openAiEmbeddingModel = openAiEmbeddingModel;
    }

    public EmbeddingResponse getEmbeddings(String... texts) {
        EmbeddingRequest request = new EmbeddingRequest(Arrays.asList(texts), null);
        return openAiEmbeddingModel.call(request);
    }
}

5. 测试该 Embedding 服务

基于前一节中的自动配置服务实现,我们暴露了一个 REST 端点,允许我们测试该 Embedding 服务:

@RestController
public class EmbeddingController {
    private final EmbeddingService embeddingService;

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

    @PostMapping("/embeddings")
    public ResponseEntity<EmbeddingResponse> getEmbeddings(@RequestBody String text) {
        EmbeddingResponse response = embeddingService.getEmbeddings(text);
        return ResponseEntity.ok(response);
    }
}

让我们通过 curl 在 body 中使用文本发起请求:

$ curl -X POST http://localhost:8080/embeddings -H "Content-Type: text/plain" -d "Hello world"

我们获得如下响应:

{
    "metadata": {
        "model": "text-embedding-3-small",
        "usage": {
            "promptTokens": 2,
            "completionTokens": 0,
            "totalTokens": 2,
            "nativeUsage": {
                "prompt_tokens": 48,
                "total_tokens": 48
            }
        },
        "empty": true
    },
    "result": {
        "index": 0,
        "metadata": {
            "modalityType": "TEXT",
            "documentId": "",
            "mimeType": {
                "type": "text",
                "subtype": "plain",
                "parameters": {},
                "charset": null,
                "concrete": true,
                "wildcardSubtype": false,
                "subtypeSuffix": null,
                "wildcardType": false
            },
            "documentData": null
        },
        "output": [
            -0.0020785425,
            -0.049085874,
            ...
       ]
    }
}

请注意,这不是整个完整的响应。因为整个响应非常长,我们只截取其中一部分来描述 JSON 中的两个顶级节点:metadaresult

metadata 提供了 Embedding 转换期间模型和资源的使用信息。model 对应的是我们选用的 OpenAI 模型,totalTokens 则便是此次转换所消费的 tokens 数。

result 代表的是 embedding 结果。其中的 output 包含一个 float 数组,它是 Embedding 模型从我们提供的文本中转换的 Embedding。

6. 小结

Spring AI 中的 Embedding 模型 API 为模型提供者(如 OpenAI)提供了抽象层和支持,使我们可以将其与我们的 Java 应用集成使用。

本文中,我们使用了一个 Embedding 模型 OpenAI,使用自动以求便利,使用手动配置以求灵活性。该 Embeddings API 提供了将 文本转换为 Embedding 向量的能力。