当前位置: 首页 > news >正文

5. 基于Embedding实现超越elasticsearch高级搜索

Embedding介绍

        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个实现类:

  1. AstraDbEmbeddingStore
  2. AzureAiSearchEmbeddingStore
  3. CassandraEmbeddingStore
  4. ChromaEmbeddingStore
  5. ElasticsearchEmbeddingStore
  6. InMemoryEmbeddingStore
  7. InfinispanEmbeddingStore
  8. MemoryIdEmbeddingStore
  9. MilvusEmbeddingStore
  10. MinimalEmbeddingStore
  11. MongoDbEmbeddingStore
  12. Neo4jEmbeddingStore
  13. OpenSearchEmbeddingStore
  14. PgVectorEmbeddingStore
  15. PineconeEmbeddingStore
  16. QdrantEmbeddingStore
  17. RedisEmbeddingStore
  18. VearchEmbeddingStore
  19. VespaEmbeddingStore
  20. WeaviateEmbeddingStore

其中我们熟悉的有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,也就是检索增强生成。

 

 

 

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • python数据可视化(6)——绘制散点图
  • 【人工智能】Transformers之Pipeline(一):音频分类(audio-classification)
  • huggingface 数据集和模型加速下载, hfdata 输出为json
  • 实验二:图像灰度修正
  • 【vue深入学习第1章】Vue.js 中的 Ajax 处理:vue-resource 库的深度解析
  • 聊聊自动驾驶中的路径和轨迹
  • 算法力扣刷题记录 四十八【513.找树左下角的值】
  • Oralce笔记-解决Oracle18c中ORA-28001: 口令已经失效
  • 【持续集成_05课_Linux部署SonarQube及结合开发项目部署】
  • CSS3实现彩色变形爱心动画【附源码】
  • Linux命令更新-sort 和 uniq 命令
  • 【车载测试收徒】【UDS诊断中的协议:ISO-14229中文】
  • bash: ip: command not found
  • MagicClothing: 给人物照片换装的ComfyUI工作流(干货满满)
  • SpringMVC源码分析
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Date型的使用
  • JavaScript设计模式之工厂模式
  • laravel 用artisan创建自己的模板
  • magento2项目上线注意事项
  • nodejs:开发并发布一个nodejs包
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • Python_OOP
  • Quartz初级教程
  • quasar-framework cnodejs社区
  • 前端路由实现-history
  • 前端面试之CSS3新特性
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 译自由幺半群
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • mysql面试题分组并合并列
  • puppet连载22:define用法
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​io --- 处理流的核心工具​
  • ​插件化DPI在商用WIFI中的价值
  • # 透过事物看本质的能力怎么培养?
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #define,static,const,三种常量的区别
  • (04)odoo视图操作
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (每日一问)基础知识:堆与栈的区别
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (五)网络优化与超参数选择--九五小庞
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • **《Linux/Unix系统编程手册》读书笔记24章**
  • .a文件和.so文件
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET/C# 使窗口永不获得焦点
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .sdf和.msp文件读取
  • .sh 的运行
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @angular/cli项目构建--http(2)