提示:如果不能访问 OpenAI,请点击 AiCode API 注册账号,通过代理访问。
Spring AI 提供了对嵌入模型(Embedding Models)的支持,支持的嵌入模型包括 OpenAI、Hugging Face、Azure OpenAI 等。这些模型能够将文本转换为向量表示,常用于语义搜索、文本相似性比较等场景。
AI 嵌入模型(AI Embedding Model)是一种将非结构化数据(如文本、图像、音频、视频等)或结构化数据(如表格数据等)转换为低维、稠密的数值向量(即 “嵌入向量 / Embedding Vector”)的人工智能模型。其核心目标是让转换后的向量能 “捕捉” 原始数据的核心语义、特征或关联关系,且向量间的数学距离(如欧氏距离、余弦相似度)可直接对应原始数据的 “相似性”—— 例如,语义相近的两个句子,其嵌入向量在空间中会更接近。
核心本质:从“原始数据”到“机器可理解的向量”
计算机无法直接理解自然语言、图像等非结构化数据,而嵌入模型的核心作用就是搭建“桥梁”:
(1)对文本:将“猫喜欢吃鱼”这句话转换为 [0.21, -0.56, 0.89, ..., 0.12](假设维度为 768)的向量,且 “猫咪爱吃鱼” 的向量会与它高度相似。
(2)对图像:将一张猫的照片转换为向量后,会与其他猫的照片向量更接近,而与狗的照片向量距离更远。
(3)对用户 ID:将频繁购买母婴用品的用户 ID 转换为向量后,会与其他母婴用品消费者的向量更相似。注意,这里不是真对用户 ID 转换为向量,而是对用户 ID 对应的用户画像转换为向量,如通过一个数组统计用户喜好 [ 运动, 购物, 学习, 旅行],用户 A 的为 [8,1,4,0],用户 B 的为 [1,7,2,0],用户 C 的为 [7,2,3,1],通过数据是不是不难发现用户 A 和 用户 C 的兴趣爱好更接近。
下面示例将演示如何使用 Spring AI 调用嵌入模型,计算文本的嵌入向量。详细步骤如下:
首先,需要在 pom.xml 中添加相关依赖(以 OpenAI 为例):
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai</artifactId> </dependency>
完整的 pom.xml 请参考“Spring AI 聊天模型”。
创建 application.yml 配置文件,配置 API 密钥,如下:
spring: application: name: springai_demo1 #... # AI配置 ai: # openai相关配置 openai: # 基础地址 # 访问 https://api.xty.app/register?aff=pO2q 地址注册账号即可访问 OpenAI 了 base-url: https://api.xty.app # AI KEY # 高级接口key api-key: sk-vHTHX8D3wNZBfRya831*************** # 聊天模型配置 chat: options: model: gpt-4-turbo # gpt-3.5-turbo # 图片模型配置 image: options: # 需要高级接口 model: dall-e-3 chat: memory: # 会话历史持久化 repository: jdbc: # 启动时不自动执行初始化SQL脚本,手动创建数据表 initialize-schema: never client: # true 开启,自动注入 ChatClient,false 关闭,需要手动创建 ChatClient enabled: true # 日志配置 logging: charset: console: UTF-8 level: root: info org.springframework.ai: debug
上述配置中,包含了模型和日志配置。
下面代码使用 OpenAiEmbeddingModel 类来将文本转换为嵌入向量。
OpenAiEmbeddingModel 类是 Spring AI 框架对 OpenAI 嵌入模型的封装,用于便捷地将文本转换为嵌入向量(Embedding Vector),是实现语义检索、文本相似度计算等功能的核心组件。它整合了 OpenAI API 的调用逻辑,同时适配 Spring 生态的设计规范,简化了在 Spring 应用中使用 OpenAI 嵌入服务的流程。
代码如下:
package com.hxstrive.springai.springai_openai.example.embedding_model; import org.springframework.ai.embedding.Embedding; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.util.Arrays; import java.util.List; @SpringBootApplication public class EmbeddingExample implements CommandLineRunner { // 注入 OpenAI 嵌入客户端 @Autowired private OpenAiEmbeddingModel embeddingModel; public static void main(String[] args) { SpringApplication.run(EmbeddingExample.class, args); } @Override public void run(String... args) throws Exception { // 示例文本 List<String> texts = List.of( "The quick brown fox jumps over the lazy dog", "A fast brown fox leaps over a sleepy dog", "Java is a programming language" ); // 生成嵌入向量 List<float[]> embeddings = embeddingModel.embed(texts); // 输出结果 for (int i = 0; i < texts.size(); i++) { System.out.println("文本: " + texts.get(i)); System.out.println("嵌入向量长度: " + embeddings.get(i).length); float[] arr = new float[10]; System.arraycopy(embeddings.get(i), 0, arr, 0, arr.length); System.out.println("前5个向量值: " + Arrays.toString(arr)); System.out.println("--------------------------------------------------"); } // 计算文本相似度(使用余弦相似度) double similarity1 = cosineSimilarity(embeddings.get(0), embeddings.get(1)); double similarity2 = cosineSimilarity(embeddings.get(0), embeddings.get(2)); System.out.println("文本1和文本2的相似度: " + similarity1); System.out.println("文本1和文本3的相似度: " + similarity2); } // 计算余弦相似度 private double cosineSimilarity(float[] vec1, float[] vec2) { double dotProduct = 0.0; double norm1 = 0.0; double norm2 = 0.0; for (int i = 0; i < vec1.length && i < vec2.length; i++) { dotProduct += vec1[i] * vec2[i]; norm1 += Math.pow(vec1[i], 2); norm2 += Math.pow(vec2[i], 2); } return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); } }
直接运行上述代码,输出如下:
文本: The quick brown fox jumps over the lazy dog 嵌入向量长度: 1536 前5个向量值: [-0.0035696456, 0.00830194, -0.014215737, -0.0045437566, -0.015460085, 0.018627517, -0.020475186, -0.010218739, -0.012883404, -0.028129812] -------------------------------------------------- 文本: A fast brown fox leaps over a sleepy dog 嵌入向量长度: 1536 前5个向量值: [-0.0030607197, 0.008283801, -0.015861526, -0.00885749, -0.016554995, 0.026200516, -0.0018818225, -0.013188518, -0.0038708174, -0.025292702] -------------------------------------------------- 文本: Java is a programming language 嵌入向量长度: 1536 前5个向量值: [0.005201417, -0.0027674206, -0.008592817, -0.014226098, -0.015890043, 0.0071448036, -0.03221195, -0.023549272, 0.0025594274, -0.03650518] -------------------------------------------------- 文本1和文本2的相似度: 0.9463748400918686 文本1和文本3的相似度: 0.782855753697816
余弦相似度用于衡量两个向量(vec1 和 vec2)在方向上的相似程度。计算过程如下:
计算向量点积(dotProduct):通过遍历两个向量的对应元素并相乘后累加,得到点积结果。点积越大,说明向量在方向上越接近。
计算向量的模长(norm1、norm2):分别计算两个向量各元素的平方和,再通过开平方得到模长(向量的长度)。
计算余弦相似度:根据公式 余弦相似度 = 点积 / (向量1的模长 × 向量2的模长),得到最终结果。
结果含义:
余弦相似度的取值范围是 [-1, 1]。
越接近 1:两个向量方向越相似(如语义相近的文本嵌入向量)。
越接近 0:两个向量相关性越低。
越接近 -1:两个向量方向越相反。
注意,要使用其他嵌入模型,只需替换相应的依赖和客户端,并配置对应的 API 密钥或模型路径即可。
提示:如果不能访问 OpenAI,请点击 AiCode API 注册账号,通过代理访问。