python使用elasticserch进行混合搜索构建知识库

python使用elasticserch进行混合搜索

基于python使用elasticserch

安装elasticsearch

复制代码
pip install elasticsearch

连接elasticsearch

复制代码
es_username = "elastic"
es_password = "123456"
es = Elasticsearch(
    ['https://0.0.0.0:9200'],
    basic_auth=(es_username, es_password),verify_certs=False
    )

创建索引

python 复制代码
#settings: 定义了索引的设置,包括了主分片数量和副本数量。一个主分片和0副本。
#id类型为 keyword,意味着它是一个精确值字段,不会被分词。
#title 和 content: 表示标题和内容的字段,类型为 text,使用了中文分词器(ik_smart 和 ik_max_word)进行分析,并且都被配置为存储。
#title_vec 和 vectors.features: 表示向量字段的字段,类型为 dense_vector,意味着它们存储了稠密向量。这些向量字段还指定了维度(dims),相似度度量方式(similarity,这里是余弦相似度),以及是否被索引(index,设置为 True)。
#vectors.segment: 表示文档中的某一段落的字段,类型为 text,使用了中文分词器,并且被配置为存储。
index_name = "zft_lnn"
index_settings = {
    'settings': {
        'number_of_shards': 1,
        'number_of_replicas': 0
    },
    'mappings': {
        "properties": {
            "id": {
                "store": True,
                "type": "keyword"
            },  
            "title": {
                "search_analyzer": "ik_smart",
                "analyzer": "ik_max_word",
                "store": True,
                "type": "text"
            },
            "content": {
                "search_analyzer": "ik_smart",
                "analyzer": "ik_max_word",
                "store": True,
                "type": "text"
            },
            "title_vec": {
                "dims": 768,
                "similarity": "cosine",
                "index": True,
                "type": "dense_vector"
            },
            "vectors": {
                "type": "nested",
                "properties": {
                    "features": {
                        "dims": 768,
                        "similarity": "cosine",
                        "index": True,
                        "type": "dense_vector"
                    },
                    "segment": {"search_analyzer": "ik_smart",
                                "analyzer": "ik_max_word",
                                "store": True,
                                "type": "text"}
                }
            }
        }
    }
}
python 复制代码
es.indices.create(index=index_name, body=index_settings)

写入数据

待写入数据存储在json文件中,里面是query和answer的对子。

复制代码
import json

# 读取JSON文件
with open('answer.json', 'r', encoding='utf-8') as file:
    data = json.load(file)
    
count = 1
for item in data:
    title = item["query"]
    content  = item["answer"]
    index_name = "zft_bge"
    title_vec = vector_model.encode(title)
    content_vec = vector_model.encode(content)
    id = str(count)
    count += 1

    datas = {}
    datas["id"] = id
    datas["title"] = title
    datas["content"] = content
    datas["title_vec"] = title_vec
    datas["content_vec"] = content_vec

    document = {
        "id": datas["id"],
        "title": datas["title"],
        "title_vec":datas["title_vec"],
        "content":datas["content"],
        "content_vec":datas["content_vec"]
    }
    response = es.index(index=index_name,id=datas["id"], body=document)

搜索数据

关键字搜索

IK 分词器可以将中文文本切分成一个个有意义的词语,并计算这些词语的词频(term frequency,TF),用于构建倒排索引。在搜索时,Elasticsearch 会根据查询词的词频和文档中各个词语的词频来计算文档的相关性得分,从而排序返回搜索结果。

python 复制代码
boostqu = {
          "match": {
            "title": {
              "query": qa,
              "boost": 1.5
            }
          }
        }
query = {
        "query": {
            "function_score": {
                "query": {
                    "bool": {
                        "should": boostqu
                    }
                },
                "functions": [
                    {
                        "script_score": {
                            "script": {
                                "source": "Math.sqrt(_score)/2",
                                "lang": "painless",
                            }
                        }
                    }
                ],
                "boost_mode": "replace"
            }
        },
}

results = es.search(index=index_name, body=query)
hits = results["hits"]["hits"]
for h in hits:
    print(h["_source"]["title"],h['_score'])

KNN搜索

在 Elasticsearch 中,KNN 搜索通常用于基于向量的相似性搜索,例如基于词嵌入向量或其他类型的向量来查找最相似的文档或项。

python 复制代码
query_vector = vector_model.encode(qa)
query = {
  "query": {
    "bool": {
      "should": [
        {
          "knn": {
            "field": "title_vec",
            "query_vector": query_vector,
            "num_candidates": 10,
            "boost": 1.0
          }
        }
      ]
    }
  }
}
results = es.search(index=index_name, body=query)
hits = results["hits"]["hits"]
for h in hits:
    print(h["_source"]["title"],h['_score'])

向量搜索

python 复制代码
query_vector = vector_model.encode(qa)
query = {
  "query": {
    # 通过 script score 来自定义查询的分值计算
    "script_score": {
      "query": {
        # 此处可以结合其他约束条件
        "match_all": {}
      },
      # 稠密向量查询的重点在此处,通过 script 的方式指定具体的计算方式
      # 此处是计算余弦相似度,也可以替换其他的相似度
      "script": {
		# 余弦相似度计算需要两个参数:本次待查询的向量 queryVector 和索引中的字段 entity_name_embedding
        "source": "cosineSimilarity(params.queryVector, 'title_vec')",
        "lang": "painless",
		# 此处将本次待查询的向量传入,注意"params"中 queryVector 和 "source"中的书写要保持一致。
        "params": {
          # 768 维的待查询向量
          "queryVector": query_vector
        }
      },
       "boost": 1.0,
    }
  },
}
results = es.search(index=index_name, body=query)
hits = results["hits"]["hits"]
for h in hits:
    print(h["_source"]["title"],h['_score'])

混合搜索

在混合搜索中,可以在不同方式的搜索加入权重,进行去权重的相加,从而得到一个更好的结果,这个权重参数更多的需要结合实际场景进行设置。

python 复制代码
#混合搜索
def multiserch(es,vector_model,qa):
    query_vector = vector_model.encode(qa)

    key_boostqu = [{"match": {"title": {"query": qa, "boost": 1.2}}},
               {"match": {"content": {"query": qa, "boost": 0.8}}},]

    query = {
    "query": {
        "bool": {
        "should": [
            {
            "function_score": {
                "query": {
                        "bool": {
                            "should": key_boostqu
                        }
                    },
                "functions": [
                {
                    "script_score": {
                    "script": {
                        "source": "Math.sqrt(_score)/2",
                        "lang": "painless"
                    }
                    }
                }
                ],
                "boost_mode": "replace"
            }
            },
        
            {
            "script_score": {
                "query": {
                "match_all": {}
                },
                "script": {
                "source": "cosineSimilarity(params.queryVector, 'title_vec')",
                "lang": "painless",
                "params": {
                    "queryVector": query_vector
                }
                },
                "boost": 1.0
            }
            }
        ]
        }
    },
        "knn": {
        "field": "title_vec",
        "query_vector": query_vector,
        "k": 1,
        "num_candidates": 10,
        "boost": 0.5
        },
        "knn": {
        "field": "content_vec",
        "query_vector": query_vector,
        "k": 1,
        "num_candidates": 10,
        "boost": 0.5
        },
    "size": 3
    }

    results = es.search(index=index_name, body=query)
    hits = results["hits"]["hits"]
    for h in hits:
        print(h["_source"]["title"],h['_score'])
        print(h["_source"]["content"])
    content = hits[0]["_source"]["content"]
    return content
相关推荐
程序员阿龙9 分钟前
【精选】计算机毕业设计Python Flask海口天气数据分析可视化系统 气象数据采集处理 天气趋势图表展示 数据可视化平台源码+论文+PPT+讲解
python·flask·课程设计·数据可视化系统·天气数据分析·海口气象数据·pandas 数据处理
ZHOU_WUYI15 分钟前
Flask与Celery 项目应用(shared_task使用)
后端·python·flask
且慢.58934 分钟前
Python_day47
python·深度学习·计算机视觉
佩奇的技术笔记41 分钟前
Python入门手册:异常处理
python
憨憨睡不醒啊1 小时前
如何让LLM智能体开发助力求职之路——构建属于你的智能体开发知识体系📚📚📚
面试·程序员·llm
大写-凌祁1 小时前
论文阅读:HySCDG生成式数据处理流程
论文阅读·人工智能·笔记·python·机器学习
柯南二号1 小时前
深入理解 Agent 与 LLM 的区别:从智能体到语言模型
人工智能·机器学习·llm·agent
爱喝喜茶爱吃烤冷面的小黑黑1 小时前
小黑一层层削苹果皮式大模型应用探索:langchain中智能体思考和执行工具的demo
python·langchain·代理模式
Blossom.1182 小时前
使用Python和Flask构建简单的机器学习API
人工智能·python·深度学习·目标检测·机器学习·数据挖掘·flask
Love__Tay3 小时前
【学习笔记】Python金融基础
开发语言·笔记·python·学习·金融