Spring AI 学习篇(五)| 嵌入模型与向量表示的本质
2026/6/23 12:37:08 网站建设 项目流程

Spring AI 学习篇(五)| 嵌入模型与向量表示的本质

  • 一、本章核心学习目标
  • 二、前置知识准备
  • 三、为什么我们需要嵌入模型?
    • 嵌入的本质:把文本变成机器可理解的数字向量
  • 四、向量相似度计算原理
    • 1. 余弦相似度(最常用)
    • 2. 点积相似度
    • 3. 欧氏距离
  • 五、Spring AI EmbeddingClient统一API详解
    • 1. 基础依赖配置
      • (1) 对接DeepSeek商业嵌入API
      • (2) 对接本地Ollama嵌入模型
    • 2. 基础配置
      • (1) DeepSeek商业API配置
      • (2) Ollama本地模型配置
    • 3. 基础调用示例
    • 4. 计算两个文本的相似度
  • 六、2026年主流嵌入模型对比与选型
    • 1. 嵌入模型核心参数说明
    • 2. 主流嵌入模型横向对比
    • 3. 嵌入模型选型决策树
    • 4. 本地Ollama部署BGE-M4
  • 七、嵌入模型的常见误区
    • 1. ❌ 误区一:用聊天模型做嵌入
    • 2. ❌ 误区二:混用不同嵌入模型的向量
    • 3. ❌ 误区三:向量维度越高越好
    • 4. ❌ 误区四:嵌入模型越新越好
  • 八、企业级性能优化技巧
    • 1. 批量生成嵌入向量
    • 2. 缓存嵌入向量
    • 3. 限制文本长度
    • 4. 选择合适的批量大小
  • 九、常见坑与解决方案
    • 1. ❌ 向量维度不匹配
    • 2. ❌ 中文效果差
    • 3. ❌ 批量调用报错
    • 4. ❌ 本地模型速度慢
  • 十、本章总结与下章预告
    • 本章总结
    • 下章预告
  • 十一、课后练习

一、本章核心学习目标

学完本章,你将能够:

  1. 深刻理解嵌入(Embedding)的本质和核心原理
  2. 掌握向量相似度计算的三种常用方法
  3. 熟练使用Spring AIEmbeddingClient统一API
  4. 独立完成主流嵌入模型的对比与选型
  5. 实现本地Ollama嵌入模型与商业API的无缝切换
  6. 避开嵌入模型使用中的常见误区
  7. 掌握嵌入模型的企业级性能优化技巧

二、前置知识准备

  • 已经完成前4篇的学习,熟练掌握ChatClient和提示词工程
  • 了解大模型的知识截止和幻觉问题
  • 熟悉Spring Boot的配置和依赖注入

三、为什么我们需要嵌入模型?

在前面的学习中,我们已经能够让大模型回答问题,但大模型有三个无法通过提示词工程解决的原生缺陷:

  1. 知识截止限制:所有大模型都有训练数据截止日期,无法回答训练之后发生的事情
  2. 幻觉问题:大模型会编造不存在的事实和数据
  3. 私有数据不可用:企业内部文档、客户数据等不能上传给大模型训练

嵌入模型就是解决这三个问题的核心钥匙,它是RAG(检索增强生成)技术的基础。

嵌入的本质:把文本变成机器可理解的数字向量

通俗地说,嵌入就是把人类语言的文本转换成一串固定长度的数字向量。它的神奇之处在于:语义相似的文本,生成的向量在空间中距离也会很近

举个直观的例子:

  • “我喜欢吃苹果” 和 “我爱吃苹果” → 向量距离非常近
  • “我喜欢吃苹果” 和 “我喜欢吃香蕉” → 向量距离较近(都是水果)
  • “我喜欢吃苹果” 和 “今天天气很好” → 向量距离非常远

这样一来,机器就可以通过计算向量之间的距离,来判断两段文本的语义相似度。

预告式提及:下一章我们会学习向量数据库,它就是专门用来存储这些向量并快速计算相似度的数据库。

四、向量相似度计算原理

向量相似度计算是检索的核心,常用的有三种方法:

1. 余弦相似度(最常用)

计算两个向量之间的夹角余弦值,取值范围是[-1, 1]。值越接近1,相似度越高;越接近-1,相似度越低;0表示完全无关。

特点:不受向量长度的影响,只关心向量的方向,是文本相似度计算的首选方法。

2. 点积相似度

计算两个向量对应位置元素的乘积之和。取值范围没有限制,值越大相似度越高。

特点:同时考虑向量的方向和长度,适合需要考虑文本重要性的场景。

3. 欧氏距离

计算两个向量在空间中的直线距离。取值范围是[0, +∞),值越小相似度越高。

特点:适合比较向量的绝对差异,在文本相似度计算中使用较少。

企业级最佳实践:中文RAG场景首选余弦相似度。

五、Spring AI EmbeddingClient统一API详解

ChatClient一样,Spring AI为所有嵌入模型提供了统一的EmbeddingClient接口。无论你使用的是商业API还是本地模型,代码完全相同。

1. 基础依赖配置

(1) 对接DeepSeek商业嵌入API

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-deepseek</artifactId></dependency>

(2) 对接本地Ollama嵌入模型

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-ollama</artifactId></dependency>

2. 基础配置

(1) DeepSeek商业API配置

spring:ai:deepseek:api-key:你的DeepSeek API Keyembedding:options:model:deepseek-embedding

(2) Ollama本地模型配置

spring:ai:ollama:base-url:http://localhost:11434embedding:options:model:bge-m4

重要说明:只需要添加对应的依赖和配置,Spring AI会自动为你创建EmbeddingClient实例,不需要编写任何额外代码。

3. 基础调用示例

importorg.springframework.ai.embedding.EmbeddingClient;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;@RestControllerpublicclassEmbeddingController{privatefinalEmbeddingClientembeddingClient;publicEmbeddingController(EmbeddingClientembeddingClient){this.embeddingClient=embeddingClient;}// 生成单个文本的嵌入向量(返回 float[])@GetMapping("/embed")publicfloat[]embed(@RequestParamStringtext){returnembeddingClient.embed(text);}// 批量生成嵌入向量@GetMapping("/embed/batch")publicList<float[]>embedBatch(@RequestParamList<String>texts){returnembeddingClient.embed(texts);}// 获取嵌入向量的维度@GetMapping("/embed/dimension")publicintgetDimension(){returnembeddingClient.dimensions();}}

4. 计算两个文本的相似度

Spring AI 不提供内置的向量计算工具类,需要手动实现余弦相似度:

@GetMapping("/similarity")publicdoublecalculateSimilarity(@RequestParamStringtext1,@RequestParamStringtext2){float[]vector1=embeddingClient.embed(text1);float[]vector2=embeddingClient.embed(text2);returncosineSimilarity(vector1,vector2);}/** * 手动实现余弦相似度:cos(θ) = (A·B) / (|A| × |B|) */privatedoublecosineSimilarity(float[]a,float[]b){doubledotProduct=0,normA=0,normB=0;for(inti=0;i<a.length;i++){dotProduct+=a[i]*b[i];normA+=a[i]*a[i];normB+=b[i]*b[i];}returndotProduct/(Math.sqrt(normA)*Math.sqrt(normB));}

测试示例

  • 输入:text1=“我喜欢吃苹果”,text2=“我爱吃苹果” → 相似度≈0.95
  • 输入:text1=“我喜欢吃苹果”,text2=“今天天气很好” → 相似度≈0.1

六、2026年主流嵌入模型对比与选型

这是本章最核心的内容,也是你在实际开发中必须做出的决策。

1. 嵌入模型核心参数说明

参数含义影响
向量维度向量包含的数字个数维度越高,语义表达能力越强,但存储和计算成本也越高
最大序列长度模型一次能处理的最大token数超过这个长度的文本会被截断,导致语义丢失
中文性能模型对中文语义的理解能力直接决定RAG系统的检索准确率
商用许可证是否可以免费用于商业用途关系到企业的法律风险

2. 主流嵌入模型横向对比

模型名称厂商/机构类型向量维度最大长度100万tokens成本中文评分商用许可
BGE-M4智源研究院开源本地102481920元95Apache 2.0(免费商用)
M3E-v2阿里达摩院开源本地10245120元90Apache 2.0
Jina Embeddings v3Jina AI开源本地102481920元85Apache 2.0
DeepSeek-embedding-v2深度求索商业API153640961元85商业
智谱embedding-3智谱AI商业API102440965元88商业
OpenAI text-embedding-3-smallOpenAI商业API153681910.14元80商业

3. 嵌入模型选型决策树

嵌入模型选型决策树: ├── 数据敏感,绝对不能上传到第三方服务器 → 必须选择开源本地模型 │ ├── 有GPU(4GB以上显存) → BGE-M4(首选,中文性能天花板) │ └── 只有CPU → M3E-v2(推理速度快,CPU友好) └── 数据不敏感,可以上传 → 商业API ├── 预算有限 → DeepSeek-embedding-v2(性价比之王) ├── 已经在使用智谱生态 → 智谱embedding-3 └── 多语言需求 → OpenAI text-embedding-3-small

重要纠正:之前有说法"DeepSeek没有向量模型",这是完全错误的。DeepSeek不仅有官方的嵌入API,而且价格极低,是商业API的首选。

2026年最新进展:BGE-M4已经内置了稀疏向量支持,不需要再单独部署Splade等稀疏向量模型,可以直接实现混合检索。我们会在第8篇详细讲解混合检索技术。

4. 本地Ollama部署BGE-M4

如果你选择本地部署BGE-M4,只需要一行命令:

ollama pull bge-m4

然后修改application.yml配置为Ollama模式,不需要修改任何Java代码。

七、嵌入模型的常见误区

1. ❌ 误区一:用聊天模型做嵌入

很多新手会误以为"同一个模型既可以聊天也可以做嵌入",这是完全错误的。

聊天模型和嵌入模型的训练目标完全不同:

  • 聊天模型的训练目标是生成下一个token
  • 嵌入模型的训练目标是让语义相似的文本生成相似的向量

用聊天模型生成的向量,相似度计算结果会非常不准确。

2. ❌ 误区二:混用不同嵌入模型的向量

每个嵌入模型生成的向量空间是完全不同的。你不能把BGE-M4生成的向量和DeepSeek生成的向量放在同一个向量数据库中进行比较,结果会完全没有意义。

企业级最佳实践:一个RAG系统只能使用一个嵌入模型,所有向量都必须由同一个模型生成。

3. ❌ 误区三:向量维度越高越好

虽然维度越高语义表达能力越强,但1024维已经足够应对绝大多数中文场景。更高的维度(如1536维)只会增加存储和计算成本,带来的性能提升非常有限。

4. ❌ 误区四:嵌入模型越新越好

不要盲目追求最新的嵌入模型。BGE-M4已经经过了大量企业的验证,稳定性和效果都有保障。新模型可能存在各种问题,不建议直接用于生产环境。

八、企业级性能优化技巧

1. 批量生成嵌入向量

不要每次只生成一个文本的向量,尽量批量生成,这样可以大幅提升效率。

importjava.util.Arrays;importjava.util.List;// 推荐:批量生成List<String>texts=Arrays.asList("文本1","文本2","文本3");List<float[]>embeddings=embeddingClient.embed(texts);// 不推荐:逐个生成for(Stringtext:texts){float[]embedding=embeddingClient.embed(text);}

2. 缓存嵌入向量

对于不会变化的文本(如知识库文档),生成一次向量后就缓存起来,不要重复生成。可以使用Redis作为缓存。

3. 限制文本长度

不要把过长的文本直接传给嵌入模型,应该先进行切分。我们会在第7篇详细讲解文本切分策略。

4. 选择合适的批量大小

商业API一般都有批量大小限制,比如DeepSeek的最大批量大小是2048。超过这个限制会导致调用失败。

九、常见坑与解决方案

1. ❌ 向量维度不匹配

问题:嵌入模型生成的向量维度和向量数据库要求的维度不一致
解决方案:确保嵌入模型和向量数据库使用相同的维度。BGE-M4是1024维,DeepSeek是1536维。

2. ❌ 中文效果差

问题:使用OpenAI等国外模型,中文检索准确率低
解决方案:中文场景优先使用BGE-M4、M3E-v2等国产模型,它们的中文性能远超国外模型。

3. ❌ 批量调用报错

问题:批量调用时提示"请求过大"
解决方案:减小批量大小,一般每次处理10-100个文本比较合适。

4. ❌ 本地模型速度慢

问题:使用CPU运行BGE-M4,生成速度很慢
解决方案:如果有NVIDIA显卡,Ollama会自动启用GPU加速,推理速度大幅提升。

十、本章总结与下章预告

本章总结

  1. 嵌入模型的本质是将文本转换为数字向量,语义相似的文本向量距离更近
  2. 余弦相似度是文本相似度计算的首选方法
  3. Spring AI提供了统一的EmbeddingClient接口,支持商业API和本地模型
  4. 中文RAG场景首选BGE-M4开源本地模型,商业API首选DeepSeek-embedding-v2
  5. 不要用聊天模型做嵌入,不要混用不同模型的向量
  6. 批量生成和缓存可以大幅提升嵌入模型的性能

预告式提及:我们现在已经学会了如何生成向量,但如何高效地存储和检索这些向量呢?下一章我们将学习向量数据库,它是RAG系统的核心存储组件。

下章预告

下一章我们将深入学习向量数据库的选择与Spring AI集成。你将学会:

  • 什么是向量数据库?为什么不用MySQL存向量?
  • 主流向量数据库对比:Milvus vs Qdrant vs Chroma
  • Spring AI向量数据库统一API详解
  • 本地向量数据库Chroma的快速上手
  • 向量的增删改查与批量导入导出

十一、课后练习

  1. 分别使用DeepSeek商业API和本地Ollama BGE-M4生成"Java是最好的编程语言"的向量,观察它们的维度差异
  2. 计算三对文本的相似度:“Java开发"和"Java编程”、“Java开发"和"Python开发”、“Java开发"和"打篮球”
  3. 实现一个批量生成嵌入向量的接口,支持一次处理最多50个文本
  4. 尝试修改Ollama配置,使用M3E-v2模型,对比它和BGE-M4的生成速度和相似度计算结果
  5. 思考一下:为什么嵌入模型能够捕捉到文本的语义信息?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询