微信扫码
与创始人交个朋友
我要投稿
在昨天员外分享的《TorchV的RAG实践分享(1)——RAG的定位、技术选型和RAG技术文章目录》一文中介绍了TorchV的由来,也分享了我们的几个基线产品和应用架构的方向,我们想的是在创业的过程中,将我们自己的一些产品理念、技术心得都通过公众号发文的方式分享出来,更多的和行业内的专家们共同交流,这对我们自己也是一种提升和锻炼,也期待和客户一起共创成长,逐步把产品打磨好。
在目前大模型应用技术架构中,通过召回上下文来回答用户的问题是解决大模型当下的幻觉问题最靠谱/经济实惠的一种解决方案,RAG检索增强技术在整个LLM技术架构体系中的作用越来越明显。而检索召回和用户的query问句的质量则直接关系到最终大模型的生成结果。在向量数据库基础设施普及的今天,仅仅通过语义搜索召回已经无法满足企业级的需求,大家发现传统的搜索技术(基于关键词、词频等相关性的搜索)的作用也显得尤为重要,混合检索也成为了目前在RAG的技术架构中的主流检索方式,混合检索通过扬长避短的方式,在不同的业务应用场景中形成了很好的互补,对于不同的业务场景需求中,可以更灵活的进行配置满足业务需要,是RAG技术架构体系中非常重要的重要一环。
本文中所提到的混合检索主要是两种搜索技术的结合,主要如下:
本文针对ElasticSearch中间件来实现整个外部知识库向量的存储和计算,在RAG技术架构中的混合检索进行探索和分析,结合我们自己的实际业务情况,如何通过底层的技术驱动,完善我们的产品设计,改善整个产品流程。
整篇文章主要包括:
在介绍ElasticSearch的混合检索之前,我们需要先简单回顾ElasticSearch这个中间件如何在目前AI技术场景的落地情况
在目前的RAG大模型技术架构体系中,向量Vector
技术已经作为大模型外挂知识库的非常重要的技术栈,向量的核心对于数据的表征(Embedding)然后执行相似度(Similarity)计算。2023年随着大模型技术的发布带火了非常多的向量数据库,特别是LangChain、llama_index等LLM数据应用框架的发布,包括:Milvus
、Qdrant
、Pinecone
、Chroma
等等专业的向量数据库中间件。向量数据结构的存储与计算可以说是当前做大模型应用的基建产品了,就好像传统软件工程中的数据库一样。
而对于ElasticSearch而言也同样如此,对于之前使用ElasticSearch中间件的开发人员而言,可能对于向量数据的存储和计算是比较陌生的,在传统软件工程用ES来储存搜索主要还是基于关键词搜索技术(BM25、TF-IDF)等实现,本质还是基于文本的精确匹配。而在最近ES组件发布的版本来看,特别是ES 8.0版本发布对于KNN算法搜索的优化支持来看,AI大模型这场技术革命风暴,似乎也不想袖手旁观。
我们选择ElasticSearch作为TorchV的基础RAG架构组件也是出于以下几个方面考虑:
在ElasticSearch的目前的版本中,要使用向量实现存储和计算对于开发者使用上非常简单,开发者在定义ES的索引结构时,定义向量字段类型dense_vector
,并且自定义向量维度dims
(最大维度不超过4096(自8.x版本开始)),如下索引结构:
PUT test-001
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3
},
"my_text" : {
"type" : "keyword"
}
}
}
}
在执行搜索时则可以通过k-最近邻(KNN)搜索找到与查询向量最近的K个向量结果值来获取结果,通过相似度值来衡量获取文档片段。
GET test-001/_knn_search
{
"knn": {
"field": "my_vector",
"query_vector": [0.3, 0.1, 1.2],
"k": 10,
"num_candidates": 100
},
"_source": ["name", "date"]
}
而我们在前面提到,混合检索(语义搜索+相关性搜索)是目前做RAG的非常重要文档召回技术手段,纯KNN搜索并不能完全满足业务的需求,因此在当前的RAG技术架构体系中,ES在保持传统相关性搜索的基础上,增加对语义搜索的技术支持就显得很有冲击力,毕竟在向量搜索火爆之前,ES作为搜索引擎的老大哥,在企业级的产品应用体系中,应用范围还是非常广泛的。
在做混合检索时,我们会接触到两类算法,需要对算法有一个基础了解,这有助于我们在应用产品的技术体系中做决策:
KNN算法:k近邻算法,是机器学习算法中一种基本分类和回归方法。在给定的一个数据集中,对于新的数据实例,找到与该实例最邻近的k个实例,这k个实例的多数属于某个分类。
这就像你在一个陌生的城市,你可能会问周围的k个人哪家餐馆最好。如果大多数人都推荐同一家餐馆,那么你可能会选择去那家餐馆。
而我们在选择餐馆的过程中,每一个餐馆会有非常多的维度来描述这个餐馆的信息,包括:地理位置、菜系、价格、环境、口味等等,这一系列参数属性就是特征工程,目前的向量Embedding模型用来对一段文本进行Embedding,其实就是对于该文本内容的的特征信息进行提取描述。
这个时候,你会根据你自己的诉求,对于餐馆的不同特征要求,最终选择你要去哪家餐馆吃饭。
在Elasticsearch中,KNN搜索主要通过使用向量相似度(特征空间中的两个实例点间的距离可以反映出两点间的相似程度)进行度量,文档根据向量数据集与查询向量的相似度进行排名。每个文档的 _score
将从相似度中得出,以确保分数为正并且分数越高对应于越高的排名。
ES目前主要提供了三种度量的标准供我们选择(考虑到本文是基于es,因此也只对该三种度量标准做介绍,对于其它的向量计算距离的方式,开发者可以自行搜索了解)
score
计算方式为:1 / (1 + l2_norm(query, vector)^2)
_score
计算为 (1 + dot_product(query, vector)) / 2
_score
计算为 (1 + cosine(query, vector)) / 2
我们在开发RAG的大模型应用产品中,通常会将外部的知识库通过chunk分段存储处理,对于用户的query,通过Embedding模型进行表征为向量后,与chunk片段的向量进行距离计算,此时作为距离度量的方式考虑,那么根据实际的业务场景,就可以考虑上面的三种类型中的一种。
一般默认选择cosine余弦相似度进行计算召回,主要考虑:
而ES自8.0版本发布后,同样也提供了对KNN搜索的优化,主要提供了两种策略:
script_score
函数扫描每个匹配文档计算向量距离获取文档结果集,这会导致搜索速度缓慢(大数据集的应用场景下)。开发者在选择KNN搜索的算法策略时,可以根据自己的实际业务需要进行抉择。
ES自5.0版本之后,针对文档的相关性评分机制默认采用了BM25相似度算法(之前是基于TF-IDF),BM25全称Okapi BM25。Okapi 是使用它的第一个系统的名称,即Okapi信息检索系统,于 20 世纪 80 年代和 1990 年代在伦敦城市大学实施。BM则是best matching的缩写。
因此对于词的相关性检索方案,我们对于TF-IDF和BM25也需要有一个基础的了解。
TF-IDF(Term Frequency-Inverse Document Frequency):词频-逆文档频率是一个常用于信息检索和文本挖掘的权重计算方法,函数公式如下:
主要由两部分组成:
n
,文本的总词条数为m
,则词频TF为n/m,也就是词频,比如一个单词:旅游
在我们的一篇文档中出现了4次,而我们的文档总共包含的词条数量是100,那么词频的值就是4/100
。词频越高,说明这个词在文档中越重要。TF-IDF就是将这两个值相乘,得到的结果就是一个词的权重,这个权重可以用来表示这个词对于文档的重要性,也可以用来比较不同文档的相似性。
TF-IDF在实践的发展中会存在一些问题:
这些问题都在BM25中得到了改进,BM25的词频部分使用了一个饱和函数,使得词频达到一定值后,增加词频对于最终得分的影响会变小。同时,BM25还考虑了文档长度的影响,通过一个归一化因子来调整不同长度文档中的词频。这使得BM25在处理词频未饱和和文档长度问题时,比TF-IDF有更好的性能。
BM25 的计算公式:
和TF-IDF的计算公式相比,BM25的公式着实有点吓人,不过其实我们关注几个核心的参数即可。
对于BM25算法在ElasticSearch中的应用公式和参数变量说明,可以参考这篇文章《BM25 算法及其变量》,这里我们只关心几个核心的参数
1.2
。较低的值导致较快的饱和,较高的值导致较慢的饱和。0.75
。这个参数值也是针对上面我们提到TF-IDF在文档长度未考虑的情况下一个加权计算,当然默认值0.75
是官方基于大量的数据实验得到的一个值,在默认场景下都会有较好的效果,我们可以不用调整。如果我们的默认检索效果不佳,应该从其它方面来考虑优化,这个后面我们再说在前面了解了ES的整个检索Score算法介绍之后,其实对于文本内容的检索召回Score分值计算,就比较清晰了,先说结论:
ElasticSearch在使用KNN+BM25检索的混合检索分值Score计算公式是:knn_score+bm25_score
使用ES混合检索的语法如下:
POST image-index/_search
{
"query": {
"match": {
"title": {
"query": "mountain lake",
"boost": 0.9
}
}
},
"knn": {
// 字段
"field": "image-vector",
// 输入向量
"query_vector": [54, 10, -2],
// k值
"k": 5,
// 每个分片要考虑的最近邻居候选数。不能超过 10,000
"num_candidates": 50,
// 加权参数值
"boost": 0.1,
// 档被视为匹配所需的最小相似度,配合filter使用,提高检索效率
"similarity": 0.7,
// 过滤条件
"filter": {
"term": {
"file-type": "png"
}
}
},
"size": 10
}
query
部分的检索所代表的是BM25算法的Score计算分值召回,而knn
部分的检索所代表的则是语义向量空间的距离Score分值,最终的结果值相加后倒排的一个文档列表结果集
score=
match_score*0.9 + knn_score*0.1
对于BM25算法的检索分值计算,开发者可以使用Explain API来查看整个Score
的计算过程,整个计算过程就和BM25算法公式那样,如下图:
图3-BM25算法Score分析
BM25算法会将用户输入的match参数,计算每一个分词的score分值,最终加起来,得到一个总的分值score数据,对于每一个分词,都可以通过该接口查看到完整的计算过程,是非常方便开发者进行理解的。
在这里进行BM25计算时,我前面提到BM25算法可能存在检索不到最终我们所期望的文本结果,会有一些其它参数影响最终效果,并非需要更改算法中的k1和b这两个参数,主要考虑如下:
对于KNN的检索分值计算,就非常的简单了,开发者在构建用户索引的时候,选择具体的向量距离类型,es在计算knn的时候,就会根据其算法进行计算
PUT my-index-2
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 1024,
// 选择类型,cosine、dot_product、l2_norm
"similarity": "cosine"
}
}
}
}
选择不同的类型, 就是单纯的向量距离计算了,按公式套用就可以了。
不过值得注意的是,对于使用最多的cosine
的文档 _score
计算为 (1 + cosine(query, vector)) / 2
。
当我们使用混合检索的时候,有一些注意事项值得我们关注:
filter
过滤参数会提高检索的效率,但是提高检索效率的同时,由于总是会计算召回文档进行相似度计算,所以可以配合similarity
来一起使用。对于混合检索,我们在算法层面有了直接的了解后,最终在产品层面会影响一些设计。
1、混合检索的权重设置:在上面的score分值计算公式中,我们其实知道es最终是通过bm25*boost
+knn*boost
,那么这个boost
则可以影响我们最终的内容,因为并不是所有的客户和业务场景都适合knn检索,可能在其他关键的场景中,关键词检索会更适合(比如一些利用大模型做一些异步的任务提取,报告输出等等业务场景),我们在产品设计中则可以根据不同的客户诉求以及业务诉求,就可以设置这个boost
来影响最终的召回结果天平,从而改善我们的产品效果。
在我们的TorchV的产品设计中,我们设计了一个alpha
参数值,取值范围在0-1之间,具体来说:
alpha = 1
:完全基于向量的搜索,也就是KNN近邻搜索alpha = 0
:完全基于关键词的搜索,基于ES的BM25算法检索2、在BM25算法的场景中,分词是非常重要的一个特性,对于不同的行业客户,词库的收集建立对于产品应用的提升肯定是会有质的提升,也是每个公司做RAG产品的核心竞争力。
3、持续运营能力的重要性,RAG问答检索功能在技术架构迭代优化上是一个方面,但是运营能力同样重要,哪怕是ChatGPT4,在针对特殊的数据文件,如果数据混乱,知识库质量不高,那么同样回答准确率不会很好的,这在我们和客户进行沟通交流的同时,虽然RAG可能会给客户眼前一亮的感觉,但是持续的提升他的能力,发挥更大的作用,产品的持续运营能力是必不可少的。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-12-22
2个简单技巧把 RAG 检索准确率从 50% 提高到 95 %
2024-12-22
Browser-Use + LightRAG Agent:可使用 LLM 抓取 99% 的网站
2024-12-22
Dynamic RAG实战:解决知识增强中的动态更新挑战
2024-12-21
构建行业RAG应用系统:金融、财务、保险、医疗等行业该怎么做?
2024-12-21
构建基于多智能体RAG的企业的AI应用程序
2024-12-21
必读!RAG好用的3种Router
2024-12-20
GraphRAG0.5.0:从安装到高效应用的全方位指南
2024-12-20
大模型之深入探索RAG流程
2024-07-18
2024-05-05
2024-06-20
2024-09-04
2024-05-19
2024-07-09
2024-07-09
2024-07-07
2024-07-07
2024-07-08
2024-12-21
2024-12-14
2024-12-01
2024-11-27
2024-11-25
2024-11-06
2024-11-06
2024-11-05