使用 ElasticSearch 作为知识库,存储向量及相似性搜索_elasticsearch cosinesimilarity

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

五、相似性搜索

1. 余弦相似度算法:cosineSimilarity
from elasticsearch import Elasticsearch
from transformers import BertTokenizer, BertModel
import torch


def embeddings\_doc(doc, tokenizer, model, max_length=300):
    encoded_dict = tokenizer.encode_plus(
        doc,
        add_special_tokens=True,
        max_length=max_length,
        padding='max\_length',
        truncation=True,
        return_attention_mask=True,
        return_tensors='pt'
    )
    input_id = encoded_dict['input\_ids']
    attention_mask = encoded_dict['attention\_mask']

    # 前向传播
    with torch.no_grad():
        outputs = model(input_id, attention_mask=attention_mask)

    # 提取最后一层的CLS向量作为文本表示
    last_hidden_state = outputs.last_hidden_state
    cls_embeddings = last_hidden_state[:, 0, :]
    return cls_embeddings[0]


def search\_similar(index_name, query_text, tokenizer, model, es, top_k=3):
    query_embedding = embeddings_doc(query_text, tokenizer, model)
    print(query_embedding.tolist())
    query = {
        "query": {
            "script\_score": {
                "query": {"match\_all": {}},
                "script": {
                    "source": "cosineSimilarity(params.queryVector, 'ask\_vector') + 1.0",
                    "lang": "painless",
                    "params": {
                        "queryVector": query_embedding.tolist()
                    }
                }
            }
        },
        "size": top_k
    }
    res = es.search(index=index_name, body=query)
    hits = res['hits']['hits']
    similar_documents = []
    for hit in hits:
        similar_documents.append(hit['\_source'])
    return similar_documents


def main():
    # 模型下载的地址
    model_name = 'D:\\AIGC\\model\\chinese-roberta-wwm-ext-large'
    # ES 信息
    es_host = "http://127.0.0.1"
    es_port = 9200
    es_user = "elastic"
    es_password = "elastic"
    index_name = "medical\_index"

    # 分词器和模型
    tokenizer = BertTokenizer.from_pretrained(model_name)
    model = BertModel.from_pretrained(model_name)

    # ES 连接
    es = Elasticsearch(
        [es_host],
        port=es_port,
        http_auth=(es_user, es_password)
    )

    query_text = "我有高血压可以拿党参泡水喝吗"

    similar_documents = search_similar(index_name, query_text, tokenizer, model, es)
    for item in similar_documents:
        print("================================")
        print('ask:', item['ask'])
        print('answer:', item['answer'])


if __name__ == '\_\_main\_\_':
    main()


打印日志如下:

在这里插入图片描述

================================
ask: 我有高血压这两天女婿来的时候给我拿了些党参泡水喝,您好高血压可以吃党参吗?
answer: 高血压病人可以口服党参的。党参有降血脂,降血压的作用,可以彻底消除血液中的垃圾,从而对冠心病以及心血管疾病的患者都有一定的稳定预防工作作用,因此平时口服党参能远离三高的危害。另外党参除了益气养血,降低中枢神经作用,调整消化系统功能,健脾补肺的功能。感谢您的进行咨询,期望我的解释对你有所帮助。

ask: 我准备过两天去看我叔叔,顺便带些人参,但是他有高血压,您好人参高血压可以吃吗?
answer: 人参有一定的调压作用,主要用来气虚体虚的患者,如果有气血不足,气短乏力,神经衰弱,神经衰弱健忘等不适症状的话,可以适当口服人参调养身体,但是对于高血压的病人,如果长期食用人参的话,可能会对血压引发一定影响,所以,比较好到医院中医科实施辨证论治调治,看如何适合食用人参。

ask: 我妈妈有点高血压,比较近我朋友送了我一些丹参片,我想知道高血压能吃丹参片吗?
answer: 丹参片具备活血化瘀打通血管的作用可以致使血液粘稠度减低,所以就容易致使血管内血液供应便好防止出现血液粘稠,致使血压下降,所以对降血压是有一定帮助的,高血压患者是经常使用丹参片实施治疗的。可以预防,因为血液粘稠引来的冠心病心绞痛以及外周血管脑水肿症状。

2. 点积算法:dotProduct

计算给定查询向量和文档向量之间的点积度量。

from elasticsearch import Elasticsearch
from transformers import BertTokenizer, BertModel
import torch


def embeddings\_doc(doc, tokenizer, model, max_length=300):
    encoded_dict = tokenizer.encode_plus(
        doc,
        add_special_tokens=True,
        max_length=max_length,
        padding='max\_length',
        truncation=True,
        return_attention_mask=True,
        return_tensors='pt'
    )
    input_id = encoded_dict['input\_ids']
    attention_mask = encoded_dict['attention\_mask']

    # 前向传播
    with torch.no_grad():
        outputs = model(input_id, attention_mask=attention_mask)

    # 提取最后一层的CLS向量作为文本表示
    last_hidden_state = outputs.last_hidden_state
    cls_embeddings = last_hidden_state[:, 0, :]
    return cls_embeddings[0]


def search\_similar(index_name, query_text, tokenizer, model, es, top_k=3):
    query_embedding = embeddings_doc(query_text, tokenizer, model)
    print(query_embedding.tolist())
    query = {
        "query": {
            "script\_score": {
                "query": {"match\_all": {}},
                "script": {
                    "source": "dotProduct(params.queryVector, 'ask\_vector')+1.0",
                    "lang": "painless",
                    "params": {
                        "queryVector": query_embedding.tolist()
                    }
                }
            }
        },
        "size": top_k
    }
    res = es.search(index=index_name, body=query)
    hits = res['hits']['hits']
    similar_documents = []
    for hit in hits:
        similar_documents.append(hit['\_source'])
    return similar_documents


def main():
    # 模型下载的地址
    model_name = 'D:\\AIGC\\model\\chinese-roberta-wwm-ext-large'
    # ES 信息
    es_host = "http://127.0.0.1"
    es_port = 9200
    es_user = "elastic"
    es_password = "elastic"
    index_name = "medical\_index"

    # 分词器和模型
    tokenizer = BertTokenizer.from_pretrained(model_name)
    model = BertModel.from_pretrained(model_name)

    # ES 连接
    es = Elasticsearch(
        [es_host],
        port=es_port,
        http_auth=(es_user, es_password)
    )

    query_text = "我有高血压可以拿党参泡水喝吗"

    similar_documents = search_similar(index_name, query_text, tokenizer, model, es)
    for item in similar_documents:
        print("================================")
        print('ask:', item['ask'])
        print('answer:', item['answer'])


if __name__ == '\_\_main\_\_':
    main()


在这里插入图片描述

================================
ask: 我有高血压这两天女婿来的时候给我拿了些党参泡水喝,您好高血压可以吃党参吗?
answer: 高血压病人可以口服党参的。党参有降血脂,降血压的作用,可以彻底消除血液中的垃圾,从而对冠心病以及心血管疾病的患者都有一定的稳定预防工作作用,因此平时口服党参能远离三高的危害。另外党参除了益气养血,降低中枢神经作用,调整消化系统功能,健脾补肺的功能。感谢您的进行咨询,期望我的解释对你有所帮助。

ask: 我准备过两天去看我叔叔,顺便带些人参,但是他有高血压,您好人参高血压可以吃吗?
answer: 人参有一定的调压作用,主要用来气虚体虚的患者,如果有气血不足,气短乏力,神经衰弱,神经衰弱健忘等不适症状的话,可以适当口服人参调养身体,但是对于高血压的病人,如果长期食用人参的话,可能会对血压引发一定影响,所以,比较好到医院中医科实施辨证论治调治,看如何适合食用人参。

ask: 我妈妈有点高血压,比较近我朋友送了我一些丹参片,我想知道高血压能吃丹参片吗?
answer: 丹参片具备活血化瘀打通血管的作用可以致使血液粘稠度减低,所以就容易致使血管内血液供应便好防止出现血液粘稠,致使血压下降,所以对降血压是有一定帮助的,高血压患者是经常使用丹参片实施治疗的。可以预防,因为血液粘稠引来的冠心病心绞痛以及外周血管脑水肿症状。

3. L1曼哈顿距离:l1norm

计算给定查询向量和文档向量之间的L1距离。

from elasticsearch import Elasticsearch
from transformers import BertTokenizer, BertModel
import torch


def embeddings\_doc(doc, tokenizer, model, max_length=300):
    encoded_dict = tokenizer.encode_plus(
        doc,
        add_special_tokens=True,
        max_length=max_length,
        padding='max\_length',
        truncation=True,
        return_attention_mask=True,
        return_tensors='pt'
    )
    input_id = encoded_dict['input\_ids']
    attention_mask = encoded_dict['attention\_mask']

    # 前向传播
    with torch.no_grad():
        outputs = model(input_id, attention_mask=attention_mask)

    # 提取最后一层的CLS向量作为文本表示
    last_hidden_state = outputs.last_hidden_state
    cls_embeddings = last_hidden_state[:, 0, :]
    return cls_embeddings[0]


def search\_similar(index_name, query_text, tokenizer, model, es, top_k=3):
    query_embedding = embeddings_doc(query_text, tokenizer, model)
    print(query_embedding.tolist())
    query = {
        "query": {
            "script\_score": {
                "query": {"match\_all": {}},
                "script": {
                    "source": "1 / (1 + l1norm(params.queryVector, doc['ask\_vector']))",
                    "lang": "painless",
                    "params": {
                        "queryVector": query_embedding.tolist()
                    }
                }
            }
        },
        "size": top_k
    }
    res = es.search(index=index_name, body=query)
    hits = res['hits']['hits']
    similar_documents = []
    for hit in hits:
        similar_documents.append(hit['\_source'])
    return similar_documents


def main():
    # 模型下载的地址
    model_name = 'D:\\AIGC\\model\\chinese-roberta-wwm-ext-large'
    # ES 信息
    es_host = "http://127.0.0.1"
    es_port = 9200
    es_user = "elastic"
    es_password = "elastic"
    index_name = "medical\_index"

    # 分词器和模型
    tokenizer = BertTokenizer.from_pretrained(model_name)
    model = BertModel.from_pretrained(model_name)

    # ES 连接
    es = Elasticsearch(
        [es_host],
        port=es_port,
        http_auth=(es_user, es_password)
    )

    query_text = "我有高血压可以拿党参泡水喝吗"

    similar_documents = search_similar(index_name, query_text, tokenizer, model, es)
    for item in similar_documents:
        print("================================")
        print('ask:', item['ask'])
        print('answer:', item['answer'])


if __name__ == '\_\_main\_\_':
    main()


在这里插入图片描述

================================
ask: 我有高血压这两天女婿来的时候给我拿了些党参泡水喝,您好高血压可以吃党参吗?
answer: 高血压病人可以口服党参的。党参有降血脂,降血压的作用,可以彻底消除血液中的垃圾,从而对冠心病以及心血管疾病的患者都有一定的稳定预防工作作用,因此平时口服党参能远离三高的危害。另外党参除了益气养血,降低中枢神经作用,调整消化系统功能,健脾补肺的功能。感谢您的进行咨询,期望我的解释对你有所帮助。

ask: 我准备过两天去看我叔叔,顺便带些人参,但是他有高血压,您好人参高血压可以吃吗?
answer: 人参有一定的调压作用,主要用来气虚体虚的患者,如果有气血不足,气短乏力,神经衰弱,神经衰弱健忘等不适症状的话,可以适当口服人参调养身体,但是对于高血压的病人,如果长期食用人参的话,可能会对血压引发一定影响,所以,比较好到医院中医科实施辨证论治调治,看如何适合食用人参。

ask: 我妈妈有点高血压,比较近我朋友送了我一些丹参片,我想知道高血压能吃丹参片吗?
answer: 丹参片具备活血化瘀打通血管的作用可以致使血液粘稠度减低,所以就容易致使血管内血液供应便好防止出现血液粘稠,致使血压下降,所以对降血压是有一定帮助的,高血压患者是经常使用丹参片实施治疗的。可以预防,因为血液粘稠引来的冠心病心绞痛以及外周血管脑水肿症状。

4. l2 欧几里得距离:l2norm

计算给定查询向量和文档向量之间的欧几里德距离。

from elasticsearch import Elasticsearch
from transformers import BertTokenizer, BertModel
import torch


def embeddings\_doc(doc, tokenizer, model, max_length=300):
    encoded_dict = tokenizer.encode_plus(
        doc,
        add_special_tokens=True,
        max_length=max_length,
        padding='max\_length',
        truncation=True,
        return_attention_mask=True,
        return_tensors='pt'
    )
    input_id = encoded_dict['input\_ids']
    attention_mask = encoded_dict['attention\_mask']

    # 前向传播
    with torch.no_grad():
        outputs = model(input_id, attention_mask=attention_mask)

    # 提取最后一层的CLS向量作为文本表示
    last_hidden_state = outputs.last_hidden_state
    cls_embeddings = last_hidden_state[:, 0, :]
    return cls_embeddings[0]


def search\_similar(index_name, query_text, tokenizer, model, es, top_k=3):
    query_embedding = embeddings_doc(query_text, tokenizer, model)
    print(query_embedding.tolist())
    query = {
        "query": {
            "script\_score": {
                "query": {"match\_all": {}},
                "script": {
                    "source": "1 / (1 + l2norm(params.queryVector, doc['ask\_vector']))",
                    "lang": "painless",
                    "params": {
                        "queryVector": query_embedding.tolist()
                    }
                }
            }
        },
        "size": top_k
    }
    res = es.search(index=index_name, body=query)
    hits = res['hits']['hits']
    similar_documents = []
    for hit in hits:
        similar_documents.append(hit['\_source'])
    return similar_documents


def main():
    # 模型下载的地址
    model_name = 'D:\\AIGC\\model\\chinese-roberta-wwm-ext-large'
    # ES 信息
    es_host = "http://127.0.0.1"
    es_port = 9200
    es_user = "elastic"
    es_password = "elastic"
    index_name = "medical\_index"

    # 分词器和模型
    tokenizer = BertTokenizer.from_pretrained(model_name)
    model = BertModel.from_pretrained(model_name)

    # ES 连接
    es = Elasticsearch(
        [es_host],
        port=es_port,
        http_auth=(es_user, es_password)
    )

    query_text = "我有高血压可以拿党参泡水喝吗"

    similar_documents = search_similar(index_name, query_text, tokenizer, model, es)
    for item in similar_documents:
        print("================================")
        print('ask:', item['ask'])
        print('answer:', item['answer'])


if __name__ == '\_\_main\_\_':
    main()


在这里插入图片描述

================================
ask: 我有高血压这两天女婿来的时候给我拿了些党参泡水喝,您好高血压可以吃党参吗?
answer: 高血压病人可以口服党参的。党参有降血脂,降血压的作用,可以彻底消除血液中的垃圾,从而对冠心病以及心血管疾病的患者都有一定的稳定预防工作作用,因此平时口服党参能远离三高的危害。另外党参除了益气养血,降低中枢神经作用,调整消化系统功能,健脾补肺的功能。感谢您的进行咨询,期望我的解释对你有所帮助。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

都有一定的稳定预防工作作用,因此平时口服党参能远离三高的危害。另外党参除了益气养血,降低中枢神经作用,调整消化系统功能,健脾补肺的功能。感谢您的进行咨询,期望我的解释对你有所帮助。

================================

[外链图片转存中…(img-YGisVZtp-1715401717506)]
[外链图片转存中…(img-cfE1KR6s-1715401717507)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值