基于Es和智普AI实现的语义检索
1、什么是语义检索
语义检索是一种利用自然语言处理(NLP)和人工智能(AI)技术来理解搜索查询的语义,以提供更准确和相关搜索结果的搜索技术,语义检索是一项突破性的技术,旨在通过深入理解单词和短语的含义及上下文来提供更为准确的搜索结果。与传统的基于关键词的搜索不同,语义检索侧重于查询的意图和语境,而不仅仅是关键词的直接匹配。这种搜索方式可以显著提高搜索结果的准确性和相关性,尤其适用于复杂查询和模糊不清的搜索需求
上面是比较"官方"的解释,举个例子来简单说明一下吧:
比如现在有一条数据,叫诸葛亮,输入关键字孔明,传统的查询(关系型数据)和搜索引擎(Elasticsearch)是查不出来诸葛亮这条数据的,因为这二者都是通过关键字来匹配的,但是语义检索能够查出来,这就是语义检索最大的亮点
2、语义检索能做什么
除了上面提到的文字检索,还可以实现基于文档内容(本质还是文字检索)、图片、和视频内容的检索
3、语义检索的实现思路
Elasticsearch在7.X版本开始支持knn查询,也就是近似查询(也叫向量查询),关于knn的深入理解就不在这里过多的赘述了,其底层原理我也不是很懂,整体的思路如下图:
其中图片和视频的转换为向量的时候有两种方式,一种是直接将图片和视频转换为向量,这种相对较复杂,第二种是通过把图片和视频交给大模型,让其理解其中的内容,并将内容提取出来转换为文字,然后将文字再转换为向量存入es
4、操作实践
准备工作:
Elasticsearch 8.12.0
智普AI向量转换:智谱AI开放平台(embedding-3)
1、建立Es索引mapping,其中几个关键的属性字段:
dims:向量的纬度数,本质就是一个float类型的数组,我自己测试的结果是1024效果比较好,一般这个值有738,1024,2048,具体要看模型支持多少唯独
type:int8_hnsw,这个是es8.8才提供的特性
{"my_embedding": {"mappings": {"dynamic": "strict","properties": {"department": {"type": "text","fields": {"keyword": {"type": "keyword"}},"analyzer": "my_analyzer"},"embedding": {"type": "dense_vector","dims": 1024,"index": true,"similarity": "l2_norm","index_options": {"type": "int8_hnsw","m": 16,"ef_construction": 100}}}}}
}
2、通过智普AI生成向量数据写入Elasticsearch:Authorization填写自己申请的智普的授权码
@Testpublic void vectorWriteV1() throws Exception {
// List<String> text = Stream.of("刘玄德", "桃园三结义", "刘备", "毛岸英", "毛泽东思想", "新中国", "江青", "杨开慧", "毛润之", "三国", "武当山", "二万五千里长征", "太极拳").collect(Collectors.toList());List<String> text = Stream.of(
// "武当山不仅是中国道教文化的圣地,也是自然与人文景观的完美融合之地。游客在这里可以体验丰富的历史文化和壮丽的自然风光",
// "庐山集自然美景与深厚文化底蕴于一体,无论是自然景观的雄奇险秀,还是人文景观的丰富多彩,基本都使其成为不可多得的旅游胜地。对于想要探访庐山的游客来说,春夏秋三季是最佳游览时节。"
// "西安事变是**由张学良和杨虎城于1936年12月12日为劝谏蒋介石改变“攘外必先安内”的国策、停止内战一致抗日而发动的兵谏,又称双十二事变**。这次事变对我国近现代史产生了深远的影响,不仅因为其直接参与者的身份特殊,更因为它标志着国内战争向抗日战争转折的重大历史节点"
// "大势智慧科技有限公司凭借其在实景三维数字化重建及三维数据服务的深厚技术积累和丰富的实践经验,已经成为该领域的领导者。面对未来的机遇与挑战,大势智慧有望继续发挥其在技术创新和行业应用方面的优势,为不同行业提供更多高质量的三维数字化解决方案,推动相关领域的技术进步和产业升级""关羽", "张飞").collect(Collectors.toList());String url = "https://open.bigmodel.cn/api/paas/v4/embeddings";Map<String, String> header = new HashMap<>();header.put("Content-Type", "application/json");header.put("Authorization", "");for (String s : text) {List<Float> embeddings = new LinkedList<>();EmbeddingParams embeddingParams = CommonBuilder.of(EmbeddingParams.class).with(EmbeddingParams::setInput, ListBuilder.<String>ofList().add(s).build()).build();String result = HttpRequestUtil.doPost(url, header, JSON.toJSONString(embeddingParams));JSONObject jsonObject = JSON.parseObject(result);JSONArray jsonArray = jsonObject.getJSONArray("data");JSONObject embeddingObj = (JSONObject) jsonArray.get(0);JSONArray embedding = embeddingObj.getJSONArray("embedding");for (Object o : embedding) {embeddings.add(((BigDecimal) o).floatValue());}MyVector myVector = CommonBuilder.of(MyVector.class).with(MyVector::setDepartment, s).with(MyVector::setEmbedding, embeddings).build();esClientUtil.writeData(myVector, IdUtil.getSnowflakeNextId() + "", "my_embedding");}}
3、测试验证knn检索:
@Testpublic void vectorSearchV1() throws Exception {
// List<String> text = Stream.of("刘备", "关羽", "毛泽东思想", "毛泽东", "林彪", "周恩来", "张三丰", "十堰").collect(Collectors.toList());
// List<String> text = Stream.of("西安", "十堰", "江西", "张学良", "蒋介石", "杨虎城", "黄先锋").collect(Collectors.toList());List<String> text = Stream.of("桃园三结义", "十堰", "江西", "张学良", "蒋介石", "大势智慧", "黄先锋").collect(Collectors.toList());String url = "https://open.bigmodel.cn/api/paas/v4/embeddings";Map<String, String> header = new HashMap<>();header.put("Content-Type", "application/json");header.put("Authorization", "");for (String s : text) {List<Float> embeddings = new LinkedList<>();EmbeddingParams embeddingParams = CommonBuilder.of(EmbeddingParams.class).with(EmbeddingParams::setInput, ListBuilder.<String>ofList().add(s).build()).build();String result = HttpRequestUtil.doPost(url, header, JSON.toJSONString(embeddingParams));JSONObject jsonObject = JSON.parseObject(result);JSONArray jsonArray = jsonObject.getJSONArray("data");JSONObject embeddingObj = (JSONObject) jsonArray.get(0);JSONArray embedding = embeddingObj.getJSONArray("embedding");for (Object o : embedding) {embeddings.add(((BigDecimal) o).floatValue());}// 设置查询向量KnnQuery.Builder builder = new KnnQuery.Builder();builder.field("embedding").numCandidates(100).k(10)
// .similarity(0.3f).queryVector(embeddings);// 创建搜索请求SearchRequest searchRequest = new SearchRequest.Builder().index("my_embedding").knn(builder.build()).size(10).build();// 执行搜索请求SearchResponse<Product> searchResponse = es8ClientUtil.searchData(searchRequest, "my_embedding", Product.class);StringJoiner stringJoiner = new StringJoiner("\t");StringJoiner score = new StringJoiner("\t");for (Hit<Product> hit : searchResponse.hits().hits()) {stringJoiner.add(hit.source().getDepartment());score.add(hit.score() + "");}System.err.println(s + "===检索结果===:");System.err.println(stringJoiner);System.err.println(score);System.err.println();}}
其中用到的HttpRequestUtil是我自己基于apachehttpclient封装的工具类:基于ApacheHttpclient封装的请求工具类(记笔记)_java apache请求工具类-CSDN博客
PS:经过几轮测试下来,得出以下结论:
1、knn检索确实可以实现语义检索,弥补传统的关键字检索的不足,二者结合可以实现更加智能的检索
2、knn检索的"准确性"问题,比如我在测试的时候输入林彪,也能查询到诸葛亮这条数据,在我们的认知里面,这两个人是八竿子打不着的, 但是在经过模型转换之后,他们之间可能确实存在一些相似性,比如都是历史名人,这个"偏差"很依赖于模型的理解和转换能力
3、我测试过智普、阿里云、百度千帆和百川智能四个模型,总体上智普的效果比较好
相关文章:

基于Es和智普AI实现的语义检索
1、什么是语义检索 语义检索是一种利用自然语言处理(NLP)和人工智能(AI)技术来理解搜索查询的语义,以提供更准确和相关搜索结果的搜索技术,语义检索是一项突破性的技术,旨在通过深入理解单词和…...

URI和URL的区别
1: 将 URI 转换为 URL import java.net.URI; import java.net.URL;public class UriToUrlExample {public static void main(String[] args) {// 创建一个 URI 对象URI uri = new URI("http://example.com/path/to/resource");// 将 URI 转换为 URLtry {URL url = u…...

Java 入门指南:获取对象的内存地址
文章目录 hashCode()应用重写 hashCode() 方法示例 Symstem . indentityHashCode()应用 注意事项 在 Java 开发中,了解对象的内存管理是十分重要的,尽管 Java 的设计初衷是让开发者更专注于业务逻辑而非底层资源管理。但在某些情况下,了解对象…...

【Linux】项目自动化构建工具-make/Makefile 详解
🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…...

嵌入式开发中学习C++的用处?
这个问题一直有同学在问,其实从我的角度是一定是需要学的,最直接的就是你面试大厂的嵌入式岗位或者相关岗位,最后一定会问c,而很多人是不会的,这就是最大的用处,至于从技术角度考量倒是其次,因为…...

基于SAM大模型的遥感影像分割工具,用于创建交互式标注、识别地物的能力,可利用Flask进行封装作为Web后台服务
如有帮助,支持一下(GitHub - Lvbta/ImageSegmentationTool-SAM: An interactive annotation case developed based on SAM for remote sensing image annotation, which can generate corresponding segmentation results based on point, multi-point, …...

Selenium入门
Selenium 是一个用于自动化 web 应用程序测试的工具,它支持多种浏览器和编程语言。 下载驱动程序:根据你的浏览器类型和版本,下载相应的 WebDriver。例如,Chrome 浏览器需要 ChromeDriver。 安装 Selenium 库 pip install sele…...

USB 3.1 Micro-A 与 Micro-B 插头,Micro-AB 与 Micro-B 插座,及其引脚定义
连接器配对 下表列出 USB 插座可接受的插头: USB 3.1 Micro-B 连接器 USB 3.1 Micro-B 插头和 USB 3.1 Micro-B 插座连接器是为小型手持设备和其他可能使用小尺寸连接器的应用而定义的。其定义使得 USB 3.1 Micro-B 插座既可以接受 USB 3.1 Micro-B 插头ÿ…...

MySQL多版本并发控制MVCC实现原理
MVCC MVCC 是多版本并发控制方法,用来解决读和写之间的冲突,比如脏读、不可重复读问题,MVCC主要针对读操作做限制,保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。 概述 当一个事务要对数据库中的数据进行selec…...

【并查集】[ABC372E] K-th Largest Connected Components 题解
题意 前置阅读:并查集算法介绍 洛谷链接 Atcoder 链接 给定 n ( 1 ≤ n ≤ 2 1 0 5 ) n(1 \leq n \leq 2\times 10^5) n(1≤n≤2105) 个点,初始没有边,您要进行以下操作: 1 a b,表示连接一条 ( a , b ) (a,b) …...

HarmonyOS面试题(持续更新中)
1、用过线程通信吗,线程是怎么进行通信的? emitter 和 eventHub 相同: 都是基于事件总线的 区别是: ① eventHub当前线程内通信 ② emitter是同一进程不同线程或者同一进程和同一线程也可以通信 2、页面和组件的生命周期 …...

QT中QWidget和QObject的区别与联系是什么
在Qt框架中,QWidget和QObject是两个核心类,它们各自扮演着不同的角色,但又紧密相连。以下是关于它们区别与联系的详细解释: 区别 基类和功能定位: QObject是Qt中所有类的基类,包括几乎所有的Qt对象。它提供…...

解决macOS安装redis以后不支持远程链接的问题
参考文档:https://blog.csdn.net/qq_37703224/article/details/142542179?spm1001.2014.3001.5501 安装的时候有个提示, 使用指定配置启动: /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis.conf那么我们可以尝试修改这个配置文件: code /opt/homebrew/…...

2024年研究生数学建模“华为杯”E题——肘部法则、k-means聚类、目标检测(python)、ARIMA、逻辑回归、混淆矩阵(附:目标检测代码)
文章目录 一、情况介绍二、思路情况二、代码展示三、感受 一、情况介绍 前几天也是参加了研究生数学建模竞赛(也就是华为杯),也是和本校的两个数学学院的朋友在网上组的队伍。昨天(9.25)通宵干完论文(一条…...

绝了,自从用了它,我每天能多摸鱼2小时!
大家好,我是可乐。 俗话说的好:“摸鱼一时爽,一直摸鱼一直爽”。 作为一个程序员,是否有过调试代码熬到深夜?是否有过找不到解决方案而挠秃头顶? 但现在你即将要解放了,用了这款工具——秘塔…...

C语言指针系列1——初识指针
祛魅:其实指针这块儿并不难,有人说难只是因为基础到进阶没有处理好,大家要好好跟着一步一步学习,今天我们先来认识一下指针 指针定义:指针就是内存地址,指针变量是用来存放内存地址的变量,在同一…...

传神论文中心|第26期人工智能领域论文推荐
在人工智能领域的快速发展中,我们不断看到令人振奋的技术进步和创新。近期,开放传神(OpenCSG)传神社区发现了一些值得关注的成就。传神社区本周也为对AI和大模型感兴趣的读者们提供了一些值得一读的研究工作的简要概述以及它们各自…...

NLP基础1
NLP基础1 深度学习中的NLP的特征输入 1.稠密编码(特征嵌入) 稠密编码(Dense Encoding):指将离散或者高纬的稀疏数据转化为低纬度的连续、密集向量表示 特征嵌入(Feature Embedding) 也称…...

001.docker30分钟速通版
docker简介 docker就是一个用于构建(build),运行(run),传送(share)应用程序的平台做一个不恰当的类比,就是外卖平台,如果你自己做华莱士不一定好吃࿰…...

Kafka 在 Linux 下的集群配置和安装
Kafka 在 Linux 下的集群配置和安装 Apache Kafka 是一个流行的分布式流处理平台,广泛用于实时数据管道和流处理应用。本文将详细讲解如何在 Linux 环境中配置和安装 Kafka 集群,并包括通过 Docker 安装和配置 Kafka 的步骤。每个步骤都将提供详细的解释…...

Python--操作列表
1.for循环 1.1 for循环的基本语法 for variable in iterable: # 执行循环体 # 这里可以是任何有效的Python代码块这里的variable是一个变量名,用于在每次循环迭代时临时存储iterable中的下一个元素。 iterable是一个可迭代对象,比如列表(…...

JMeter(需要补充请在留言区发给我,谢谢)
一、学习工具 1、CinfigElement(HTTP Request Defaults、HTTP Header Manager、HTTP Authorization、CSV Data Set Config、User Defined Variables、JDBC Connection Configuration、HTTP Cookie Manager、Random Variable) 二、协议 1、HTTP协议(消息体数据&am…...

线程池的执行流程和配置参数总结
一、线程池的执行流程总结 提交线程任务;如果线程池中存在空闲线程,则分配一个空闲线程给任务,执行线程任务;线程池中不存在空闲线程,则线程池会判断当前线程数是否超过核心线程数(corePoolSize)…...

node-red-L3-重启指定端口的 node-red
重启指定端口 目的步骤查找正在运行的Node.js服务的进程ID(PID):停止Node.js服务:启动Node.js服务: 目的 重启指定端口的 node-red 步骤 在Linux系统中,如果你想要重启一个正在运行的Node.js服务&#x…...

(done) 使用泰勒展开证明欧拉公式
问问神奇的 GPT,how to prove euler formula? 一个答案如下:...

红队apt--邮件钓鱼
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 免责声明: 本文仅供了解攻击方手法使用,切勿用于非授权情节 初步了解邮件基础 用途方面 这个我们应该比较熟悉,最常用于验证码接收,也有一些厂商会用这个来打广告,…...

十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)
十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式) 文章目录 十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)1. Spring Boot 配置 MyBatis 的详细步骤2. 最后: MyBatis 的官方文档:https://mybatis.p2hp.com/ 关于 MyBa…...

DNS协议解析
DNS协议解析 什么是DNS协议 IP地址:一长串唯一标识网络上的计算机的数字 域名:一串由点分割的字符串名字 网址包含了域名 DNS:域名解析协议 IP>域名 --反向解析 域名>IP --正向解析 域名 由ICANN管理,有级别…...

每日一题——第一百零八题
题目: 写几个函数, ①输入10个职工的姓名和职工号 ②按照职工号由小到大排列, 姓名顺序也随之调整 ③要求输入一个职工号, 用折半查找找出该职工的姓名 #include<stdio.h> #include<string.h> #define MAX_EMPOLYEES…...

使用Python免费将pdf转为docx
刚刚想将pdf转换为docx文档时,居然要收费 还好我学过编程,这不得露两手 将pdf 转换为 docx 文档 的操作步骤 我这里使用的是Python语言 (1)在终端上安装 pdf2docx 是一个 Python 库,它可以将 PDF 文件转换为 Word (…...