【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库

张开发
2026/4/3 17:23:37 15 分钟阅读
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
第十一章 Embedding 向量化与向量数据库版本标注Spring AI:1.1.2Spring AI Alibaba:1.1.2.0章节定位EmbeddingModel与VectorStore是 RAG 的核心基础设施。学习本章时重点应放在统一抽象EmbeddingModel负责向量化VectorStore负责检索至于底层是 Redis 还是其他向量库属于实现选型问题。s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 [ s11 ] s12 s13 s14 s15 s16 s17 s18Embedding 不负责回答问题, 它负责让机器看懂相似度-- 向量化是检索、推荐和 RAG 的基础设施。一、为什么需要 Embedding1.1 计算机 vs 人类作为人类我们天然理解文字的含义猫 ──→ 毛茸茸的、会喵喵叫、养来抓老鼠... 狗 ──→ 忠诚的、会看家、是人类的好朋友...但对计算机来说猫和狗只是两个字符串它不知道它们有什么关系。1.2 Embedding 的思想Embedding向量化的核心思想是把文字转换成一串数字向量。Embedding 思想 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 猫 ──→ [0.12, -0.34, 0.56, 0.78, ...] (1536维向量) 狗 ──→ [0.15, -0.31, 0.53, 0.80, ...] (1536维向量) 汽车 ──→[0.89, 0.12, -0.34, 0.21, ...] (1536维向量) ↓ 向量距离很近相似 ↓ 向量距离很远不相似如果两个向量的距离很近说明对应的文本在语义上也相似。1.3 Embedding 的应用场景应用场景说明语义搜索搜手机也能找到智能手机相关内容相似推荐找到和当前内容最相似的其他内容分类聚类把相似的内容自动归类去重判断判断两段文字是否重复二、向量数据库2.1 传统数据库的局限传统数据库存储的是精确值SELECT * FROM products WHERE name 手机; -- 精确匹配但如果你搜手机就搜不到智能手机。2.2 向量数据库的优势向量数据库可以存储向量并支持相似度检索// 向量数据库查询 SearchRequest request SearchRequest.builder() .query(手机) // 搜索关键词 .topK(5) // 返回最相似的5个结果 .build(); vectorStore.similaritySearch(request); // 返回语义相似的结果即使搜索词不完全一样也能找到语义上相关的内容2.3 Redis Stack本章示例使用的向量数据库是Redis Stack本身就是内存数据库性能很快支持向量存储和检索安装使用简单三、项目代码详解3.1 VectorStore 配置类这一章有一个很容易忽略、但实际运行时一定会踩到的点VectorStore只是一个接口Spring 容器不会凭空帮你变出一个可注入的实现对象。也就是说如果你在控制器里直接写Resource private VectorStore vectorStore;但项目里既没有自动装配出某个向量库实现也没有自己手动声明 Bean启动时就会报A component required a bean of type org.springframework.ai.vectorstore.VectorStore that could not be found.在学习阶段最简单的做法是先手动提供一个SimpleVectorStoreBeanpackage com.atguigu.study.config; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class VectorStoreConfig { Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { return SimpleVectorStore.builder(embeddingModel).build(); } }这段配置类的意思很简单容器里已经有EmbeddingModel现在我们基于它手动创建一个SimpleVectorStore再把这个对象注册成VectorStoreBean这样后面的 Controller 才能顺利注入Resource private VectorStore vectorStore;3.2 向量化控制器package com.atguigu.study.controller; import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.embedding.EmbeddingRequest; import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; import java.util.List; /** * 向量化控制器 * 展示文本Embedding和向量检索的使用 */ RestController Slf4j public class Embed2VectorController { // 注入 Embedding 模型用于文本→向量 Resource private EmbeddingModel embeddingModel; // 注入向量存储器用于存储和检索向量 Resource private VectorStore vectorStore; /** * 文本转向量Text to Embedding * * 接口http://localhost:8011/text2embed?msg射雕英雄传 * * param msg 要转换的文本 * return EmbeddingResponse 包含向量结果 */ GetMapping(/text2embed) public EmbeddingResponse text2Embed(String msg) { // 方法1使用默认配置进行向量化 // EmbeddingResponse response embeddingModel.call( // new EmbeddingRequest(List.of(msg), null)); // 方法2显式指定使用 text-embedding-v3 模型推荐 // DashScopeEmbeddingOptions 包含阿里云特有的配置 EmbeddingResponse embeddingResponse embeddingModel.call( new EmbeddingRequest( List.of(msg), // 要向量化的文本列表可以一次批量处理多个 DashScopeEmbeddingOptions.builder() .withModel(text-embedding-v3) // 指定使用 embedding v3 模型 .build() ) ); // 打印向量结果可以看到生成了1536维的向量数组 System.out.println(Arrays.toString(embeddingResponse.getResult().getOutput())); // 返回完整的 EmbeddingResponse包含向量数据 return embeddingResponse; } /** * 向量入库将文本转为向量并存储到向量数据库 * * 接口http://localhost:8011/embed2vector/add * * 这个方法将文本转换为向量并存入 VectorStore */ GetMapping(/embed2vector/add) public void add() { // 1. 准备要存储的文档 // Document 是 Spring AI 定义的文档对象 // 包含 content内容、id、metadata额外信息 ListDocument documents List.of( new Document(i study LLM), // 英语我学习大语言模型 new Document(i love java) // 英语我喜欢Java ); // 2. 调用 VectorStore.add() 方法 // 内部会自动 // - 用 EmbeddingModel 把文本转为向量 // - 将向量和原始文本一起存入底层向量库 vectorStore.add(documents); // 3. 简单测试查看底层向量库中是否已经写入文档 } /** * 向量检索从向量数据库中查找相似内容 * * 接口http://localhost:8011/embed2vector/get?msgLLM * * param msg 搜索关键词 * return 和 msg 语义最相似的文档列表 */ GetMapping(/embed2vector/get) public ListDocument getAll(RequestParam(name msg) String msg) { // 1. 构建搜索请求 // SearchRequest 是 Spring AI 的搜索请求构建器 SearchRequest searchRequest SearchRequest.builder() .query(msg) // 搜索词会自动转为向量 .topK(2) // 返回最相似的2个结果 .build(); // 2. 执行相似度搜索 // 传入搜索请求返回匹配度最高的文档列表 ListDocument list vectorStore.similaritySearch(searchRequest); // 3. 打印结果 System.out.println(list); // 4. 返回结果 return list; } }四、核心原理详解4.1 为什么有时要写配置类有时又不用这个问题表面上看是在问“为什么有时要写Configuration”其实本质上是在问为什么EmbeddingModel往往可以直接注入而VectorStore却经常需要我自己注册成 BeanEmbeddingModel通常是框架已经帮你自动装配好的 BeanVectorStore通常是你还需要自己决定具体实现的 Bean所以两者最大的区别不在于“是不是接口”而在于这个对象到底是谁放进 Spring 容器里的。1. 为什么EmbeddingModel经常可以直接注入当你引入了 Spring AI Alibaba 的 DashScope Starter并且配置好了 API Key 之后框架通常会自动帮你创建好一个EmbeddingModelBean。所以在控制器里这样写Resource private EmbeddingModel embeddingModel;往往就能直接成功。这是因为Starter 已经知道你在使用 DashScope它也知道该创建哪种 Embedding 实现所以自动配置类会替你把这个对象注册进 Spring 容器也就是说这里的EmbeddingModel并不是“凭空出现的”而是框架提前帮你准备好的。2. 为什么VectorStore经常不能直接注入因为VectorStore虽然也是一个接口但它背后的实现选择并不唯一。比如你完全可以选择SimpleVectorStoreRedis VectorStoreMilvusPGVectorElasticsearch你自己写的实现Spring 不知道你到底想用哪一个所以它通常不会替你“猜一个”然后自动注册。这时如果你直接写Resource private VectorStore vectorStore;但项目里又没有任何一个VectorStoreBeanSpring 启动时就会报A component required a bean of type org.springframework.ai.vectorstore.VectorStore that could not be found.3. 这时为什么要写配置类因为你需要明确告诉 Spring“这个项目里我决定使用SimpleVectorStore作为VectorStore的实现。”最常见的写法就是Configuration public class VectorStoreConfig { Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { return SimpleVectorStore.builder(embeddingModel).build(); } }这段代码的意思是EmbeddingModel已经由框架自动提供现在我们基于它手动创建一个SimpleVectorStore再把这个对象注册成VectorStoreBean这样后面谁再写Resource private VectorStore vectorStore;Spring 就能顺利注入了。4. 那什么时候可以不写配置类如果某个对象只是你在当前方法里临时用一下其实完全可以自己创建VectorStore vectorStore SimpleVectorStore.builder(embeddingModel).build();这种写法没有错只是它有一个前提这个对象只在当前方法里用你不打算让它被别的 Controller / Service 复用你也不需要 Spring 去管理它一旦这个对象要在整个项目里复用或者要被注入到别的类里通常还是应该把它写成Bean。5. 最终怎么判断该不该写配置类可以用一个非常实用的判断标准框架已经自动装配好的对象通常直接注入就行例如EmbeddingModel需要你自己决定具体实现的对象通常要自己注册 Bean例如VectorStore所以一句话总结就是不是“有的类能直接注入有的类必须写配置类”而是“谁已经被框架放进 Spring 容器里了谁还需要你自己决定实现并注册进去”。4.2 Embedding 的维度// 阿里云的 text-embedding-v3 模型生成的向量维度是 1536 // 每个文本都会被转换成 1536 个数字的数组 // // 就好像把文字映射到一个1536维的空间中的一点 // 语义相似的文字在这个空间中的距离也会比较近4.3 相似度计算向量数据库通常使用以下几种相似度算法算法说明适用范围余弦相似度 (Cosine)夹角越小越相似方向敏感场景欧氏距离 (L2)直线距离数值敏感场景内积 (IP)点积运算排序优化很多向量库默认采用余弦相似度或相近策略具体行为取决于底层实现和索引配置。五、本章小结5.1 核心概念概念说明Embedding把文本转为向量的技术VectorStore向量数据库存储接口维度/Vector Dimension向量的长度如1536相似度检索根据向量距离找相似内容text-embedding-v3阿里云的向量化模型5.2 使用流程文本 → EmbeddingModel → 向量 → VectorStore.add() → 存入数据库 ↑ 搜索词 → 自动转向量 → similaritySearch() → 返回相似结果5.3 拓展RAG 的基础Embedding VectorStore RAG检索增强生成的核心技术后面章节我们会学习完整的 RAG 流程。本章重点理解 Embedding 的核心思想文字→数字掌握文本向量化的方法学会使用向量数据库进行相似度检索下章剧透s12掌握了向量化技术下一章我们将学习 RAG检索增强生成——让 AI 能够查阅知识库来回答专业问题TIP不要把 VectorStore 只理解成 Redis本章示例使用 Redis 只是因为它简单、容易上手。但在实际项目里VectorStore更重要的价值在于统一抽象抽象作用EmbeddingModel把文本转成向量VectorStore存储向量并做相似度检索SearchRequest描述一次检索请求这样你后续切换底层实现时业务代码改动会小很多。编辑者Flittly更新时间2026年4月

更多文章