Spring AI Embeddings 和 Vector 入门

2024-03-22 09:12

本文主要是介绍Spring AI Embeddings 和 Vector 入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

在前面 Spring AI Chat 简单示例 中介绍了 Chat 的基本用法,本文在此基础(主要是pom.xml)上继续探索 Embedding 和 Vector。

官方文档:

  • embeddings: https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embeddings.html
  • redis: https://docs.spring.io/spring-ai/reference/api/vectordbs/redis.html

Embeddings 介绍

文本嵌入(Embeddings)将文本转换为数值数组或向量,使人工智能模型能够处理和理解语言数据。这种从文本到数字的转换以及反向转换,是人工智能如何与人类语言互动和理解它的关键要素。对于探索人工智能的 Java 开发者来说,没有必要理解这些向量表示背后复杂的技术原理或是具体实现细节。只要基本了解它们在人工智能系统中的作用和功能就足够了,尤其是在将人工智能功能集成到应用程序中的时候。

文本嵌入在诸如检索增强生成 (RAG) 模式等实际应用中尤为重要。它们可以让数据在语义空间中表示为点,类似于欧几里得几何中的二维空间,只不过维度更高。这意味着就像欧几里得几何平面上的点可以根据其坐标相近或较远一样,在语义空间中,点的相近程度反映了含义的相似性。相似主题的句子在这个多维空间中会更靠近,就像图表上彼此靠近的点一样。这种相近性有助于文本分类、语义搜索甚至产品推荐等任务,因为它允许人工智能根据这些概念在扩展语义空间中的“位置”来识别和分组相关概念。

您可以将语义空间理解为一个具有多个维度的向量。每个维度代表一个语义特征,例如词性、主题、情感等。在语义空间中,每个词或句子都表示为一个向量。向量的各个分量代表该词或句子在各个语义特征上的得分。例如,一个表示“猫”的向量可能在“动物”维度上得分很高,而在“颜色”维度上得分较低。

Vector Databases 介绍

向量数据库(Vector Databases)是一种在人工智能应用中扮演着重要角色的特殊数据库类型。

与传统的关系型数据库不同,向量数据库中的查询不是进行精确匹配,而是执行相似性搜索。当使用向量作为查询时,向量数据库会返回与查询向量“相似”的向量。有关如何计算相似度的高级细节可以在 “向量相似性” 中找到。

向量数据库用于将您的数据与人工智能模型集成。使用它们的第一步是将您的数据加载到向量数据库中。然后,当用户查询需要发送到人工智能模型时,首先会检索一组相似的文档。然后,这些文档连同用户的查询一起作为用户问题的上下文发送到人工智能模型。这种技术称为检索增强生成 (Retrieval Augmented Generation, RAG)。

准备工作

在前一批 pom.xml 基础上增加依赖:

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-redis</artifactId>
</dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.1.0</version>
</dependency>

Spring AI 支持下面几种向量数据库:

  • Azure Vector Search - The Azure vector store.
  • ChromaVectorStore - The Chroma vector store.
  • MilvusVectorStore - The Milvus vector store.
  • Neo4jVectorStore - The Neo4j vector store.
  • PgVectorStore - The PostgreSQL/PGVector vector store.
  • PineconeVectorStore - PineCone vector store.
  • QdrantVectorStore - Qdrant vector store.
  • RedisVectorStore - The Redis vector store.
  • WeaviateVectorStore - The Weaviate vector store.
  • SimpleVectorStore - A simple implementation of persistent vector storage, good for educational purposes.

在本文示例中我们使用 RedisVectorStoreSimpleVectorStore,RedisVectorStore 可以通过 Docker compose 快速启动一个测试环境:

version: '3'
services:redis:image: redis/redis-stackports:- "6379:6379"volumes:- redis_data:/datavolumes:redis_data:

如果你不方便使用 Docker,SimpleVectorStore 就是就简单的选择,一个纯内存实现,不需要任何中间件。

EmbeddingClient 示例

代码如下:

// HTTPS 代理
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "7890");
// 和前面创建方式一样
var openAiApi = new OpenAiApi(System.getenv("OPENAI_API_KEY"));
// 在Api基础上创建 Embedding 客户端
var embeddingClient = new OpenAiEmbeddingClient(openAiApi,MetadataMode.EMBED,OpenAiEmbeddingOptions.builder().withModel("text-embedding-ada-002").withUser("user-1").build(),RetryUtils.DEFAULT_RETRY_TEMPLATE);

可以看到这里仍然复用了 openAiApi,通过组合可以很方便的复用公共类,公共类基于接口使得实现可以被替换,组合后的类可以扩展出更多职责单一的方法。

下面是 EmbeddingClient 常用的几个方法示例:

//单个文档
List<Double> list = embeddingClient.embed("MyBatis 分页插件 PageHelper");
//多个文档
List<List<Double>> lists = embeddingClient.embed(List.of("MyBatis 分页插件 PageHelper", "MyBatis 通用Mapper", "MyBatis 最新的 mybatis-mapper"));
//指定额外参数
EmbeddingResponse embeddingResponse = embeddingClient.call(new EmbeddingRequest(List.of("Hello World", "World is big and salvation is near"),OpenAiEmbeddingOptions.builder().withModel("Different-Embedding-Model-Deployment-Name").build()));
List<Embedding> embeddings = embeddingResponse.getResults();
for (Embedding embedding : embeddings) {List<Double> output = embedding.getOutput();// Do something with the output.
}

上面的方法返回了一个 Double 集合,需要将这个结果存入到向量数据库中,需要在数据库中记录向量数据还有原始内容,通过向量查询匹配后还需要取出原始内容。Spring AI 中定义了 Document:

public class Document {public static final ContentFormatter DEFAULT_CONTENT_FORMATTER = DefaultContentFormatter.defaultConfig();private final String id;private Map<String, Object> metadata;private String content;@JsonProperty(index = 100)private List<Double> embedding;@JsonIgnoreprivate ContentFormatter contentFormatter;//省略其他
}

VectorStore 示例

配合Spring AI 的 VectorStore 使用的时候,我们不需要手动通过 EmbeddingClient 获取 Embedding,这里分别提供基于 RedisVectorStoreSimpleVectorStore 的实现:

private static VectorStore redisVectorStore(EmbeddingClient embeddingClient) {RedisVectorStore.RedisVectorStoreConfigconfig = RedisVectorStore.RedisVectorStoreConfig.builder().withURI("redis://localhost:6379").withMetadataFields(RedisVectorStore.MetadataField.numeric("year")).build();RedisVectorStore vectorStore = new RedisVectorStore(config, embeddingClient);//手动创建时必须执行下面方法,这会初始化 spring-ai-index 索引vectorStore.afterPropertiesSet();return vectorStore;
}private static VectorStore simpleVectorStore(EmbeddingClient embeddingClient) {return new SimpleVectorStore(embeddingClient);
}

在前面创建完成 var embeddingClient 后,我们可以创建 VectorStore 来存储文档的向量数据:

VectorStore vectorStore = redisVectorStore(embeddingClient);List<Document> documents = List.of(new Document("MyBatis 分页插件 PageHelper", Map.of("year", 2014)),new Document("MyBatis 通用Mapper", Map.of("year", 2014)),new Document("MyBatis 最新的 mybatis-mapper", Map.of("year", 2019)));vectorStore.add(documents);

在调用 vectorStore.add 方法的内部会根据 documents 循环调用 embeddingClient.embed(document) 获取向量数据并存储向量存储中。在使用 redisVectorStore 实现时需要注意,由于 Redis 持久化,反复执行会存入多次数据,因此如果已经添加过文档,后续执行当前代码时可以考虑注释 vectorStore.add 行代码,如果使用的 SimpleVectorStore,内存会在每次启动时初始化,需要反复计算向量数据才能使用。

有了数据之后就可以通过向量数据库进行查询:

List<Document> results = vectorStore.similaritySearch(SearchRequest.query("插件").withTopK(5));
results.forEach(d -> System.out.println(d.getContent()));

输出结果:

MyBatis 分页插件 PageHelper
MyBatis 通用Mapper
MyBatis 最新的 mybatis-mapper

使用 redis 时的数据:

127.0.0.1:6379> keys *
1) "embedding:e9f7cea2-b296-4674-abba-d2611360afac"
2) "embedding:3d8c0f61-2192-452c-a8db-884277dcbf7d"
3) "embedding:8e1b0cb8-c125-40e2-9cdb-5ab9a6f4705d"
127.0.0.1:6379> ft._list
1) spring-ai-index

上面的查询在使用 SimpleVectorStore 的时候也可以正常运行,但是 SimpleVectorStore 不支持下面针对元数据的表达式查询(定义时也没有元数据相关的选项):

results = vectorStore.similaritySearch(SearchRequest.query("MyBatis").withFilterExpression("year == 2014"));

有了向量数据和向量查询后,后续可以结合 Chat 在使用过程中将自己的数据放到上下文中使用,本文后续会继续介绍 Spring AI 相关的内容。

这篇关于Spring AI Embeddings 和 Vector 入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/835007

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory