哈哈最近感觉自己不像算法倒像是DB,整天围着ES打转,今天查IO,明天查内存,一会优化查询,一会优化吞吐。毕竟RAG离不开知识库,我们的选型是ES,于是这一年都是和ES的各种纠葛。所以顺手把近期获得的一些小tips记下来,万一有人和我踩进了一样的坑,也能早日爬出来。当前使用的ES版本是8.13,和7版本有较大的差异,用7.X的朋友这一章可能有不适配。本章主要覆盖以下
- 多Query向量查询的各种方案:Script,Knn(mesearch)
- KNN查询IOUtil过高问题排查
- 如何使用Filter查询更高效
多Query向量查询的各种方法
大模型的知识库都离不开向量查询,并且当前的RAG往往会对用户query进行多角度的改写和发散,因此会涉及多query同时进行向量查询。如果用ES实现的话,常用的有以下几种形式
- 多向量Pooling Script查询:多个query的向量平均后进行查询,查询效果不好,因为Pooling往往会损失很多信息,虽然把多个向量压缩成了一个向量,查询效率更高压力更小,但是效果差的离谱。但是对使用ES 7.X版本的朋友可能也是一种选择。
- query_body = {
- "size":10
- "query": {
- "bool": {
- "must": [{
- "script_score": {
- "query": {"match_all": {}},
- "script": {
- "source": f"cosineSimilarity(params.query_vector, 'vectors')",
- "params": {"query_vector": avg_embedding}
- }
- }
- }]
- }
- }
- }
复制代码
- 向量script循环取cosine的最大值或者平均值:使用ES 7且的朋友一般的选项,因为7的版本里部分没有KNN的支持,因此只能使用script线性遍历向量。而不把所有向量召回的内容都取回来进行重排序主要是IO的考虑,返回的条数更少传输压力更小。以下为python的查询示例,embedding_list是多query的向量数组。
[code]query_body = { "query": { "function_score": { "script_score": { "script": { "source": """ double max_score = -1.0; if (doc[params.field].size() == 0) return 0; // 空值保护 for (int i=0; i |