深入理解Spring AI中的向量嵌入:原理与实战
在人工智能的领域中,向量嵌入技术在文本处理和信息检索等方面发挥着关键作用。本文主要围绕Spring AI的EmbeddingModel
展开,详细介绍向量嵌入的概念、在语义搜索中的应用,以及如何使用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-002
、text-embedding-3-large
、text-embedding-3-small
等模型。 - Azure OpenAI:实现类为
AzureOpenAiEmbeddingModel
,支持text-embedding-ada-002
模型。 - Ollama:
OllamaEmbeddingModel
是其实现类,支持mistral
模型。 - PostgresML:对应的实现类是
PostgresMlEmbeddingModel
,支持distilbert-base-uncased
模型 。 - Mistral AI:实现类
MistralAiEmbeddingModel
,支持mistral-embed
模型。 - MiniMax:
MiniMaxEmbeddingModel
为实现类,支持embo-01
模型。 - QianFan:
QianFanEmbeddingModel
是其实现类,支持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的向量嵌入有更深入的理解,在实际项目中能够灵活运用这一技术。如果在学习过程中有任何问题,欢迎一起交流探讨!