LLM应用实战:当KBQA集成LLM(二) | 木戈手机站

木戈手机站

当前位置: 首页 » 攻略 » LLM应用实战:当KBQA集成LLM(二)

LLM应用实战:当KBQA集成LLM(二)

1. 背景

又两周过去了,本qiang~依然奋斗在上周提到的项目KBQA集成LLM,感兴趣的可通过传送门查阅先前的文章《
LLM应用实战:当KBQA集成LLM
》。

本次又有什么更新呢?主要是针对上次提到的缺点进行优化改进。主要包含如下方面:


1. 数据落库

上次文章提到,KBQA服务会将图谱的概念、属性、实体、属性值全部加载到内存,所有的查询均在内存中进行,随之而来的问题就是如果图谱的体量很大呢,那内存不爆了么…


2. 支持基于属性值查实体

上篇文章不支持属性值查找实体,比如”最会照顾宝宝的是什么龙”,”什么龙是大龙和大龙生活,小龙和小龙生活”。本次已经此问题优化。

此篇文章是对这两周工作的一个整体总结,其中包含部分工程层面的优化。

2. 整体框架

整体框架和上篇大致相同,不同之处在于:


1. 对齐模块:先前是基于SIM筛选候选实体,本次基于ES进行候选实体召回


2. 解析模块:先前是基于hugegraph和内存中的实体信息进行解析,本次优化为基于hugegraph和elasticsearch

3. 核心功能

3.1 数据库选型

由于需要支撑语义相似度检索,因此数据库选型为Milvus与Elasticsearch。

二者之间的比对如下:

Milvus

Elastic

扩展性层面

存储和计算分离





查询和插入分类

组件级别支持

服务器层面支持

多副本





动态分段 vs 静态分片

动态分段

静态分片

云原生





十亿级规模向量支持





功能性层面

权限控制





磁盘索引支撑





混合搜索





分区/命名空间/逻辑组





索引类型

11个(FLAT, IVF_FLAT, HNSW)等

1个(HNSW)

多内存索引支持





专门构建层面

为向量而设计





可调一致性





流批向量数据支持





二进制向量支持





多语言SDK

python, java, go, c++, node.js, ruby

python, java, go, c++, node.js, ruby, Rust, C#, PHP, Perl

数据库回滚






但由于Milvus针对国产化环境如华为Atlas适配不佳,而Es支持国产化环境,因此考虑到环境通用性,选择Es,且其文本搜索能力较强。

3.2 表结构设计

由于知识图谱的概念、属性一般量级较少,而实体数随着原始数据的丰富程度客场可短。因此将实体及其属性值在Es中进行存储。

针对KBQA集成LLM的场景,有两块内容会涉及语义搜索召回。

1. 对齐prompt中的候选实体

2. 解析模块中存在需要基于属性值查询实体的情况。

3. 涉及到数值类型的查询,如大于xx,最大,最小之类。

综合考虑,将Es的index结构设计如下:


属性


含义


类型


备注


name


实体名


keyword



concepts


所属概念


keyword


一个实体可能存在多个概念


property


属性


keyword


属性名称


value


属性值


text


ik分词器进行分词


numbers


数值属性值


double_range


会存在一个区间范围


embeddings


向量


elastiknn_dense_float_vector


1. 非数值属性对应value的向量


2. 使用elastiknn插件

3.3 安装部署

项目使用的Es版本是8.12.2,原因是elastiknn插件和Ik插件针对该版本均支持,且8.12.2版本是当前阶段的次新版本。

3.3.1 基于docker的ES部署

3.3.2 elastiknn插件集成


elastiknn插件是为了优化ES自身的向量检索性能,安装此插件后,ES的向量检索性能会提升数倍,如果再增加SSD固态硬盘,性能会进一步提升数倍。

采坑总结:


1. elastiknn插件导入始终无法安装,且报错。


解决:


(1) 一定要注意,安装es插件需要指定路径,且增加”file:” 的前缀,不加此前缀,那就等着报错吧


(2) 拷贝到容器内部,一定要注意,不要将elastiknn-8.12.2.1.zip拷贝至/usr/share/elasticsearch/plugins目录,否则安装也报错。

3.3.3 ik分词器插件集成

采坑总结:


1. ik分词器插件导入始终无法安装,且报错。


解决:一定要注意,安装es插件需要指定路径,且增加”file:” 的前缀,不加此前缀,那就等着报错吧


2. ik分词器添加自定义专有名词以及停用词不生效(浪费了1天的时间来排查)


解决:


(1) 一定要注意,8.12.2版本的ik分词器如果想要配置自定义专有名词或停用词,配置的完整目录是/usr/share/elasticsearch/config/analysis-ik,而不是/usr/share/elasticsearch/plugins/analysis-ik,这点需要注意下。

在config/analysis-ik中配置IKAnalyzer.cfg.xml,修改内容如下:


(2) 一定要注意,extra_main.dic和extra_stopword.dic的编码格式是UTF-8,如果编码格式不对的话,分词也不生效。

4. Es操作相关源码

4.1 es_client连接

4.2 构建表结构

说明:


1. value字段需要经过IK分词,分词方式ik_max_word,查询方式是ik_smart


2. embeddings的类型为elastiknn_dense_float_vector,其中向量维度为768,相似度计算使用cosine

4.3 候选实体查询

说明:


1. ‘_source’: {‘excludes’: [“embeddings”]}表示输出结果中过滤embeddings字段


2. 查询以function_score方式,其中的query表示别名或名称与问题的匹配程度,functions表示打分方式,目前的打分是基于向量相似度进行打分,其中, self.get_callback_ans表示语义相似度模型将文本转换为向量。注意:最终的得分由两部分组成,一部分是文本匹配,一部分是语义相似度匹配,不过可以增加参数boost_mode进行设置。

4.4 基于属性及属性值进行查询

4.5 数值属性范围查询

主要解决的场景有:体重大于9吨的恐龙有哪些?身长小于10米的角龙类有哪些?

其中,如果提供了实体名称,则查询范围是基于这些实体进行查询比较。

4.6 数值属性最大最小查询


实现最大最小的逻辑,采用了sort机制,按照numbers进行排序,最大则顺排,最小则倒排。

5. 效果

上一版未解决的问题,在本版本优化的结果。


1. 问:头像鸭头的龙有哪些?

答:头像鸭头的有慈母龙、原角龙、鹦鹉嘴龙、姜氏巴克龙、奇异辽宁龙、多背棘沱江龙、陆家屯鹦鹉嘴龙、盖斯顿龙、小盾龙、肿头龙、弯龙


2. 问:老师说的有一个特别会照顾宝宝的恐龙是什么龙?

答:慈母龙会照顾宝宝。


3. 问:有哪些恐龙会游泳啊?

答:滑齿龙、慢龙和色雷斯龙是会游泳的恐龙。


4. 问:科学家在意大利阿尔卑斯山脉Preone山谷的乌迪内附近发现了一个会飞的史前动物化石,它是谁的化石?

答:科学家在意大利阿尔卑斯山脉Preone山谷的乌迪内附近发现的会飞的史前动物化石是沛温翼龙的化石。

6. 总结

一句话足矣~


本文主要是针对KBQA方案基于LLM实现存在的问题进行优化,主要涉及到图谱存储至Es,且支持Es的向量检索,还有解决了一部分基于属性值倒查实体的场景,且效果相对提升。


其次,提供了部分Es的操作源码,以飧读者。

附件:

1. es vs milvus:
https://zilliz.com/comparison/milvus-vs-elastic

2. docker安装es:
https://www.elastic.co/guide/en/elasticsearch/reference/8.12/docker.html

3. elastiknn性能分析:
https://blog.csdn.net/star1210644725/article/details/134021552

4. es的function_score:
https://www.elastic.co/guide/en/elasticsearch/reference/8.12/query-dsl-function-score-query.html

猜你喜欢
本类排行