赞
踩
Embedding是向量的意思,向量可以理解为平面坐标中的一个坐标点(x,y),在编程领域,一个二维向量就是一个大小为float类型的数组。也可以用三维坐标系中的向量表示一个空间中的点。在机器学习中,向量通常用于表示数据的特征。
向量分数越高,代表位置越接近,匹配的数据越相似。
而文本向量化是指,利用大模型可以吧一个字,一个词或一段话映射为一个多维向量,比如我们可以直接在LangChain4j中调用向量模型来对一句话进行向量化。
案例代码:
- public class EmbeddingDemo{
- public static void main(String[] args) {
- OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
- .baseUrl("http://langchain4j.dev/demo/openai/v1")
- .apiKey("demo")
- .build();
-
- Response<Embedding> embed = embeddingModel.embed("你好,我叫gorgor");
- System.out.println(embed.content().toString());
- System.out.println(embed.content().vector().length);
- }
- }
代码执行结果为:
- Embedding { vector = [-0.019351093, -0.02137422...] }
- 1536
从结果可以知道“你好,我叫gorgor”这句话经过大模型向量化之后,得到一个长度为1536的float数组。注意,1536是固定的,不会随着句子长度而变化。
那么我们通过这种向量模型得到一句话对应的向量有什么作用呢?非常有用,因为我们可以基于向量来判断两句话之间的相似度,进而可以实现超越elasticsearch的高级搜索。
我们可以使用余弦相似度来计算向量的相似度,余弦相似度是一种用于衡量向量之间相似度的指标,可以用于文本向量之间的相似度,在计算机中用来判断文本之间的距离。
例如:
"机器学习"表示为 [1,2,3]
"深度学习"表示为[2,3,3]
"英雄联盟"表示为[9,1,3]
示例代码(余弦相似度):
- package com.gorgor.langchain4j.embedding;
-
- import java.util.*;
-
- public class CosineSimilarity {
-
- // 计算两个向量的点积
- public static double dotProduct(double[] vectorA, double[] vectorB) {
- double dotProduct = 0;
- for (int i = 0; i < vectorA.length; i++) {
- dotProduct += vectorA[i] * vectorB[i];
- }
- return dotProduct;
- }
-
- // 计算向量的模
- public static double vectorMagnitude(double[] vector) {
- double magnitude = 0;
- for (double component : vector) {
- magnitude += Math.pow(component, 2);
- }
- return Math.sqrt(magnitude);
- }
-
- // 计算余弦相似度
- public static double cosineSimilarity(double[] vectorA, double[] vectorB) {
- double dotProduct = dotProduct(vectorA, vectorB);
- double magnitudeA = vectorMagnitude(vectorA);
- double magnitudeB = vectorMagnitude(vectorB);
-
- if (magnitudeA == 0 || magnitudeB == 0) {
- return 0; // 避免除以零
- } else {
- return dotProduct / (magnitudeA * magnitudeB);
- }
- }
-
- public static void main(String[] args) {
- // 示例向量
- //机器学习
- double[] vectorA = {1, 2, 3};
- //深度学习
- double[] vectorB = {2,3,3};
- //英雄联盟
- double[] vectorC = {9,1,3};
-
- // 计算余弦相似度
- //机器学习”与“深度学习”的距离:
- double similarityAB = cosineSimilarity(vectorA, vectorB);
- System.out.println("Cosine SimilarityAB: " + similarityAB);
- //"机器学习”与“英雄联盟“的距离":
- double similarityAC = cosineSimilarity(vectorA, vectorC);
- System.out.println("Cosine SimilarityAB: " + similarityAC);
- }
- }
代码执行结果:
- Cosine SimilarityAB: 0.9686648999069225
- Cosine SimilarityAB: 0.5603318146805258
结论:“机器学习”与“深度学习”两个文本之间的余弦相似度更高,表示它们在语义上更相似。
文本向量算法是指将文本数据转化为向量表示的具体算法,通常包括以下几个步骤:
常见的文本向量算法包括 Word2Vec、GloVe、FastText 等。这些算法通过预训练或自行训练的方式,将单词或短语映射到低维向量空间中,从而能够在计算机中方便地处理文本数据。当然这中间最关键的就是向量模型,因为向量是它生成的,向量模型也是经过大量机器学习训练之后产生的,向量模型效果越好,就表示它对于自然语言理解的程度越好,同时也就表示它生成出来的向量越准确,越能反映出语义的相似度。
文本嵌入用于测量文本字符串的相关性,通常用于:
LangChain4j支持的向量数据库:
向量数据库名称 | 保存 | 过滤 | 删除 |
---|---|---|---|
In-memory | ✅ | ✅ | ✅ |
Astra DB | ✅ | ||
Azure AI Search | ✅ | ✅ | |
Azure CosmosDB Mongo vCore | ✅ | ||
Azure CosmosDB NoSQL | ✅ | ||
Cassandra | ✅ | ||
Chroma | ✅ | ||
Elasticsearch | ✅ | ✅ | ✅ |
Infinispan | ✅ | ||
Milvus | ✅ | ✅ | ✅ |
MongoDB Atlas | ✅ | ||
Neo4j | |||
OpenSearch | ✅ | ||
PGVector | ✅ | ✅ | ✅ |
Pinecone | |||
Qdrant | ✅ | ||
Redis | ✅ | ||
Vearch | ✅ | ||
Vespa | |||
Weaviate | ✅ | ✅ |
EmbeddingStore表示向量数据库,它有20个实现类:
其中我们熟悉的有Elasticsearch、MongoDb、Pg、Redis,令人惊喜的是MySQL 9.0也开始支持面向Ai的向量数据库了。
下面案例就以redis来演示对于向量的增删改查
引入redis依赖
- <dependency>
- <groupId>dev.langchain4j</groupId>
- <artifactId>langchain4j-redis</artifactId>
- <version>${langchain4j.version}</version>
- </dependency>
然后需要注意的是,普通的Redis是不支持向量存储和查询的,需要额外的redisearch模块,我这边是直接使用docker来运行一个带有redisearch模块的redis容器的,命令为:
docker run -p 6379:6379 redis/redis-stack-server:latest
注意端口6379不要和你现有的Redis冲突了。
然后就可以使用以下代码把向量存到redis中了:
- public class EmbeddingDemo {
- public static void main(String[] args) {
- OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
- .baseUrl("http://langchain4j.dev/demo/openai/v1")
- .apiKey("demo")
- .build();
-
- RedisEmbeddingStore embeddingStore = RedisEmbeddingStore.builder()
- .host("127.0.0.1")
- .port(6379)
- .dimension(1536)
- .build();
-
- TextSegment textSegment1 = TextSegment.textSegment("机器学习");
- TextSegment textSegment2 = TextSegment.textSegment("深度学习");
- TextSegment textSegment3 = TextSegment.textSegment("英雄联盟");
- // 生成向量
- Response<Embedding> embed1 = embeddingModel.embed("机器学习");
- Response<Embedding> embed2 = embeddingModel.embed("深度学习");
- Response<Embedding> embed3 = embeddingModel.embed("英雄联盟");
-
- // 存储向量
- embeddingStore.add(embed1.content(),textSegment1);
- embeddingStore.add(embed2.content(),textSegment2);
- embeddingStore.add(embed3.content(),textSegment3);
-
- // 生成向量
- Response<Embedding> embed = embeddingModel.embed("学习");
-
- // 查询
- List<EmbeddingMatch<TextSegment>> result = embeddingStore.findRelevant(embed.content(), 5);
- for (EmbeddingMatch<TextSegment> embeddingMatch : result) {
- System.out.println(embeddingMatch.embedded().text() + ",分数为:" + embeddingMatch.score());
- }
- }
- }
代码执行结果为
- 深度学习,分数为:0.94541862607
- 机器学习,分数为:0.943170130253
- 英雄联盟,分数为:0.9012748003005
从这就更容易看出向量的好处,能够基于向量快速的得到和文本相似的文本,这样就能非常适合用来做RAG,也就是检索增强生成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。