基于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、我测试过智普、阿里云、百度千帆和百川智能四个模型,总体上智普的效果比较好

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/430441.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用GLib的单向链表GSList

单向链表是一种基础的数据结构&#xff0c;也是一种简单而灵活的数据结构&#xff0c;本文讨论单向链表的基本概念及实现方法&#xff0c;并着重介绍使用GLib的GList实现单向链表的方法及步骤&#xff0c;本文给出了多个实际范例源代码&#xff0c;旨在帮助学习基于GLib编程的读…

uni-app快速入门

目录 一、什么是 uni-app二、快速创建 uni-app 项目1.创建 uni-app2.运行 uni-app 三、uni-app 相对传统 H5 的变化1.网络模型的变化2.文件类型变化3.文件内代码架构的变化4.外部文件引用方式变化5.组件/标签的变化6.js的变化&#xff08;1&#xff09;运行环境从浏览器变成v8引…

Leetcode—329. 矩阵中的最长递增路径【困难】

2024每日刷题&#xff08;165&#xff09; Leetcode—329. 矩阵中的最长递增路径 dfs dp实现代码 class Solution { public:int longestIncreasingPath(vector<vector<int>>& matrix) {// 9 9 4// 6 6 8// 2 1 1// 1 1 2// 2 2 1// 3 4 2int m …

fastadmin 根据选择数据来传参给selectpage输入框

文章目录 js代码php代码&#xff1a;完结 js代码 $(document).on(change,#table .bs-checkbox [type"checkbox"],function(){let url$(#chuancan).attr(data-url)urlurl.split(?)[0]let idsTable.api.selectedids(table)if(ids.length){let u_id[]ids.forEach(eleme…

CSS文档流以及脱离文档流的方法

文档流 文档流是文档中可显示对象在排列时占用的位置/空间。例如&#xff1a;块元素自上而下摆放&#xff0c;内联元素从左到右摆放。&#xff08;文档流中限制非常的多&#xff0c;导致很多页面效果无法实现)。 常见文档流限制 高低不齐&#xff0c;底边对齐 <head>&…

02【Matlab系统辨识】白噪声

1.白噪声与有色噪声 1.1 白噪声(white noise) 系统辨识中所用到的数据通常都含有噪声。从工程实际出发&#xff0c;这种噪声往往可以视为具有有理谱密度的平稳随机过程。白噪声是一种最简单的随机过程&#xff0c;是由一系列不相关的随机变量组成的理想化随机过程。白噪声的数…

构建数据分析模型,及时回传各系统监控监测数据进行分析反馈响应的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。增…

【深度学习】03-神经网络2-1损失函数

在神经网络中&#xff0c;不同任务类型&#xff08;如多分类、二分类、回归&#xff09;需要使用不同的损失函数来衡量模型预测和真实值之间的差异。选择合适的损失函数对于模型的性能至关重要。 这里的是API 的注意⚠️&#xff0c;但是在真实的公式中&#xff0c;目标值一定是…

面向对象 vs 面向过程

Java 和 C 语言的区别&#xff1a;面向对象 vs 面向过程 在编程世界中&#xff0c;不同的编程语言承载着不同的编程范式。C 语言作为一门经典的面向过程编程语言&#xff0c;注重函数的调用和操作&#xff1b;而Java则是典型的面向对象编程语言&#xff0c;重视对象与类的设计…

科技云报到:以数据“价值三角”为擎,探索数据治理实践路径

科技云报到原创。 过去四十年&#xff0c;经济发展主要来自于土地、劳动力、农业技术、工业技术等要素的充分释放。面向数字经济时代&#xff0c;无论是大模型、自动驾驶还是具身智能、人形机器人&#xff0c;数据已然成为继土地、劳动、资本和技术之后的又一种战略资产和新型…

【机器学习】11——矩阵求导

机器学习11——矩阵求导 打公式不太好标注&#xff0c;全图警告&#xff01;&#xff01;&#xff01; 文章目录 机器学习11——矩阵求导1.1标量对向量1.2标量对矩阵2.1向量对标量2.2向量对向量2.3向量对矩阵 1.1标量对向量 1.2标量对矩阵 X是m*n的矩阵&#xff0c;不严谨&am…

在vue中嵌入vitepress,基于markdown文件生成静态网页从而嵌入社团周报系统的一些想法和思路

什么是vitepress vitepress是一种将markdown文件渲染成静态网页的技术 其使用仅需几行命令即可 //在根目录安装vitepress npm add -D vitepress //初始化vitepress&#xff0c;添加相关配置文件&#xff0c;选择主题&#xff0c;描述&#xff0c;框架等 npx vitepress init //…

隐匿发案:David律所代理艺术家Ina Tomecek的两张青蛙版权画维权

案件基本情况&#xff1a;起诉时间&#xff1a;2024-8-14案件号&#xff1a;2024-cv-07196原告&#xff1a;Ina Tomecek原告律所&#xff1a;Law Office of David Gulbransen起诉地&#xff1a;伊利诺伊州北部法院涉案商标/版权&#xff1a;原告品牌简介&#xff1a;Ina Tomece…

内核是如何接收网络包的

1、数据如何从网卡到网络协议栈 1.1内核收包的过程 1、数据帧从外部网络到达网卡 2、网卡把数据帧从自己的缓存DMA(拷贝到)和内核共有的RingBuffer上 3、网卡发出硬中断通知CPU 4、CPU响应硬中断&#xff0c;简单处理后发出软中断 5、k’softirqd线程处理软中断&#xff0c;调…

颍川陈氏——平民崛起的典范

园子说颍川 广州有一处老建筑“陈家祠”&#xff0c;豪华精美堪比皇宫&#xff0c;誉为“岭南建筑艺术明珠”、“新世纪羊城八景”之一&#xff0c;是全国文保单位&#xff0c;4A 级景区。主体建筑以中轴线三座厅堂为中心&#xff0c;由大小十九座单体建筑组成&#xff0c;占地…

Windows如何查看已缓存的DNS信息

Windows server 2016如何查看已缓存的DNS信息 在Windows server 2016系统下&#xff0c;如何查看已缓存的DNS信息呢? 1.打开“运行”&#xff0c;输入cmd&#xff0c;点击“确定” 2.在命令行界面输入ipconfig /displaydns&#xff0c;按回车即可查看已缓存的dns信息

在vue中:style 的几种使用方式

在日常开发中:style的使用也是比较常见的&#xff1a; 亲测有效 1.最通用的写法 <p :style"{fontFamily:arr.conFontFamily,color:arr.conFontColor,backgroundColor:arr.conBgColor}">{{con.title}}</p> 2.三元表达式 <a :style"{height:…

Android15之源码分支qpr、dp、beta、r1含义(二百三十二)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

Java面向对象——内部类(成员内部类、静态内部类、局部内部类、匿名内部类,完整详解附有代码+案例)

文章目录 内部类17.1概述17.2成员内部类17.2.1 获取成员内部类对象17.2.2 成员内部类内存图 17.3静态内部类17.4局部内部类17.5匿名内部类17.5.1概述 内部类 17.1概述 写在一个类里面的类叫内部类,即 在一个类的里面再定义一个类。 如&#xff0c;A类的里面的定义B类&#x…