人工智能的领域中,向量嵌入技术在文本处理和信息检索等方面发挥着关键作用。本文主要围绕Spring AIEmbeddingModel展开,详细介绍向量嵌入的概念、在语义搜索中的应用,以及如何使用OpenAI模型生成向量嵌入,同时会结合具体代码示例,帮助大家更好地理解和掌握这一技术。

一、向量嵌入是什么?

在大语言模型(LLMs)的世界里,向量(也叫嵌入向量)是一组用来表示某个对象的数字数组。这里的对象可以是一个单词、一个句子、一段音频或视频,甚至像产品描述这样的结构化数据。向量主要通过计算两个向量之间的距离,来判断对象之间的相关性。简单来说,向量间距离小,就表示两个对象相关性高;距离大,则相关性低。

在向量(也就是数字数组)中,每个数字都被称作一个分量,它对应着高维空间中的一个维度。每个维度都代表了数据的一个独特特征或属性。

比如说“happiness”这个单词,它的向量嵌入可能是[2.5, 1.3, 0.8] 。向量中的每个分量都代表了这个单词在语言层面的一个特征:

  • 第一个分量2.5,可以理解为对单词情感积极性的量化。
  • 第二个分量1.3,体现了情感强度。
  • 第三个分量0.8,表示这个单词使用的语境。

要知道,向量里的这些数字单独拿出来看,并没有什么特别的意义,真正重要的是它们之间的相对大小和相互关系,这些才蕴含了语义信息。借助这样的向量,大语言模型就能更好地理解和处理“happiness”这个单词了。而且,同一个单词在不同的语境中,向量嵌入可能是不一样的。当然,使用的模型类型对向量嵌入结果的质量起着关键作用。

二、语义搜索(相似性搜索)

向量最主要的用途就是进行相似性搜索,也就是在嵌入空间里找出向量之间的相近程度。语义搜索可不依赖于单词的精确匹配,它能够理解查询的上下文和语义,所以往往能给出更好的搜索结果。

相似性搜索在很多应用场景中都有广泛的应用,比如检索增强生成(RAG)、搜索引擎、推荐引擎、文档管理系统等。就拿谷歌搜索来说,语义搜索让它能够执行智能搜索,直接给出答案,或者把我们带到网页上能找到答案的地方,而且有时候搜索结果和我们输入的查询词表面上看可能没什么关系,但实际上是符合语义的。

三、EmbeddingModel接口详解

Spring AI中,EmbeddingModel接口是所有向量嵌入功能的核心。它的主要职责就是把文本转化为数值向量(也就是向量嵌入)。这个接口提供了多个方法,其中embed()方法比较常用,它可以接受不同类型的输入(比如文本、文档等),调用配置好的后端嵌入模型,然后返回生成的向量。EmbeddingModel接口的定义如下:

public interface EmbeddingModel extends Model<EmbeddingRequest, EmbeddingResponse> { List<Double> embed(String text); List<Double> embed(Document document); EmbeddingResponse embedForResponse(List<String> texts); EmbeddingResponse call(EmbeddingRequest request); //... } 

embedForResponse()方法会返回更全面的输出,除了向量,还包含关于向量嵌入的一些额外信息。

假设有了EmbeddingModel的Bean,调用它的方法就很简单,示例代码如下:

String text = "..."; List<Double> embeddings = embeddingModel.embed(text); 

如果想要通过编程的方式覆盖默认值,可以像下面这样提供参数:

String text = "..."; List<Double> embeddings = embeddingModel.call( new EmbeddingRequest(List.of(text), OpenAiEmbeddingOptions.builder() .withModel("text-embedding-3-small") .withUser("jon.snow") .build())) .getResult().getOutput(); 

四、EmbeddingModel的实现类

Spring AI支持多种嵌入模型,针对每个模型,都有对应的EmbeddingModel接口实现类。如果想获取完整且最新的支持供应商和模型列表,可以参考官方指南。下面列举一些常见的供应商、实现类和支持的模型:

  • OpenAI:实现类是OpenAiEmbeddingModel,支持text-embedding-ada-002text-embedding-3-largetext-embedding-3-small等模型。
  • Azure OpenAI:实现类为AzureOpenAiEmbeddingModel,支持text-embedding-ada-002模型。
  • OllamaOllamaEmbeddingModel是其实现类,支持mistral模型。
  • PostgresML:对应的实现类是PostgresMlEmbeddingModel,支持distilbert-base-uncased模型 。
  • Mistral AI:实现类MistralAiEmbeddingModel,支持mistral-embed模型。
  • MiniMaxMiniMaxEmbeddingModel为实现类,支持embo-01模型。
  • QianFanQianFanEmbeddingModel是其实现类,支持bge_large_zh模型。
  • Amazon Bedrock Titan:实现类是BedrockTitanEmbeddingModel,支持amazon.titan-embed-image-v1模型。
  • Amazon Bedrock Cohere:对应的实现类为BedrockCohereEmbeddingModel,支持cohere.embed-multilingual-v3模型。

五、实战演示:用OpenAI生成向量嵌入

接下来通过一个示例,看看如何使用OpenAiEmbeddingModel类,借助OpenAI的text-embedding-ada-002模型来生成向量嵌入。其实,使用其他供应商和模型的步骤也大致相同。

(一)添加Maven依赖

首先,在项目的pom.xml文件里添加spring-ai-openai-spring-boot-starter依赖,添加这个依赖后,Spring Boot会自动为OpenAI嵌入模型进行配置。如果是从零开始搭建项目,可以参考Spring AI的入门指南获取完整信息。添加的依赖代码如下:

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

别忘了在属性文件里添加OpenAI的API密钥,配置如下:

spring.ai.openai.api-key=${OPENAI_API_KEY} 

(二)配置OpenAiEmbeddingModel Bean

添加完spring-ai-openai-spring-boot-starter依赖后,Spring Boot的自动配置功能会创建一个带有默认配置的OpenAiEmbeddingModel Bean。我们可以把这个Bean注入到Spring管理的类中,然后就能使用它了。示例代码如下:

import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.web.bind.annotation.RestController; // 定义一个RestController @RestController class EmbeddingController { // 注入EmbeddingModel实例 private final EmbeddingModel embeddingModel; // 通过构造函数注入EmbeddingModel EmbeddingController(EmbeddingModel embeddingModel) { this.embeddingModel = embeddingModel; } // 其他代码... } 

如果想要修改默认配置,可以在application.properties文件里指定相应的属性。比如:

spring.ai.openai.embedding.options.model=text-embedding-3 spring.ai.openai.embedding.options.encodingFormat=base64 # 也可以是float spring.ai.openai.embedding.options.user=howtodoinjava # 用于监测和防止滥用,代表终端用户 spring.ai.openai.embedding.options.dimensions=3000 # 仅在text-embedding-3及后续模型中支持 

如果想查看完整的属性列表和默认值,可以参考相关的属性说明部分。

(三)生成嵌入向量

OpenAiEmbeddingModel Bean初始化完成后,就可以使用它的embed()方法,从输入的文本或文档生成向量了。通常,这些向量会存储在向量数据库中。默认情况下,text-embedding-3-small模型生成的嵌入向量长度是1536,text-embedding-3-large模型生成的向量长度是3072。示例代码如下:

import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; // 定义一个RestController @RestController class EmbeddingController { // 自动注入EmbeddingModel实例 @Autowired EmbeddingModel embeddingModel; // 处理POST请求,路径为/embed @PostMapping("/embed") Response embed(@RequestBody String message) { // 调用embed方法生成向量 var embeddings = embeddingModel.embed(message); // 返回包含向量维度和向量数据的Response对象 return new Response(embeddings.size(), embeddings); } } // 定义Response记录类,包含向量维度和向量数据 record Response(int dimension, List<Double> vector){} 

最后,可以用任何REST测试工具调用这个API,验证返回的结果。比如在工具里发送请求:

POST http:/localhost:8080/embed 请求体: { "message":"The quality of the item is poor and unreliable." } 

得到的响应可能类似这样:

{ "dimension":1536, "vector":[ -0.017181374, 0.009984727, -0.028008185, 0.004044133, -0.0038955295, 0.019658094, -0.012595899, -0.011555676 ] } 

六、总结

本文详细介绍了Spring AI中的向量嵌入相关知识:

  • 向量嵌入是一组数字数组,用于表示单词、句子、音视频片段等对象。
  • 语义搜索就是在多维嵌入空间中寻找向量的相近程度。
  • 讲解了EmbeddingModel接口及其方法的基本原理。
  • 介绍了常见的嵌入模型,以及访问这些模型的实现类。
  • 说明了EmbeddingModel Bean如何通过默认配置初始化,以及如何在属性文件中修改配置。
  • 最后通过示例,展示了如何使用OpenAI的text-embedding-3-small模型和OpenAiEmbeddingModel Bean生成向量嵌入。

希望通过本文的介绍,大家对Spring AI的向量嵌入有更深入的理解,在实际项目中能够灵活运用这一技术。如果在学习过程中有任何问题,欢迎一起交流探讨!