热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Elasticsearch做一个简易的检索式聊天机器人

Elasticsearch是一个全文搜索引擎,可以快速地储存、搜索和分析海量数据。它是一个开源的搜索引擎,建立在ApacheLuceneTMApacheLucene^{TM}Apa

Elasticsearch是一个全文搜索引擎,可以快速地储存、搜索和分析海量数据。它是一个开源的搜索引擎,建立在 A p a c h e L u c e n e T M Apache Lucene^{TM} ApacheLuceneTM基础之上。ElasticSearch不仅仅是一个简易的Lucene封装,它可以被形容为:

  • 具有分布式实时文档存储,每个字段可以被索引与搜索
  • 一个分布式实时分析搜索引擎
  • 能胜任上百个服务节点的扩展,并支持PB级别的结构化或者非结构化数据

关于Elasticsearch就不做过多的介绍了,下面开始做聊天机器人。
首先是Elasticsearch的安装,可以参考这篇文章:【ElasticSearch】win10 安装elasticSearch 6.6.1,另外我们还需要安装elasticsearch-analysis-ik用于中文分词。
然后接下来我们需要了解一下Elasticsearch的基本用法,当然我这里采用的是Python版本,它的基本使用可以参考这篇文章:Elasticsearch 基本介绍及其与 Python 的对接实现或者是参考官方API文档。
接下来是要准备语料了,我们可以使用小黄鸡的语料,链接为:用于对话系统的中英文语料。这个链接里还有其他的语料,需要的可以自取。
我将语料整理为csv格式,数据包含两列,一列为question,一列为answer,大致如下:

question,answer
呵呵,是王若猫的。
"我还喜欢她,怎么办",我帮你告诉她?发短信还是打电话?
短信,嗯嗯。我也相信
你知道谁么,肯定不是我,是阮德培
许兵是谁,吴院四班小帅哥

然后调用如下代码,将数据插入Elasticsearch。

class ESUtils(object):
def __init__(self, index_name, create_index=False):
self.es = Elasticsearch()
self.index = index_name
if create_index:
mapping = {
'properties': {
'question': {
'type': 'text',
'analyzer': 'ik_max_word',
'search_analyzer': 'ik_smart'
}
}
}
# 创建index
if self.es.indices.exists(index=self.index):
self.es.indices.delete(index=self.index)
self.es.indices.create(index=self.index)
# 创建mapping
self.es.indices.put_mapping(body=mapping, index=self.index)
def insert_qa_pairs(self, qa_pairs, data_source):
count = self.es.count(index=self.index)['count'] # 获取当前数据库中的已有document数量
def gen_data():
for i, qa in enumerate(qa_pairs):
yield {
'_index': self.index,
'_id': i + count,
'data_source': data_source,
'question': qa[0],
'answer': qa[1]
}
bulk(self.es, gen_data())

上述代码第一次调用需要创建index,则__init__方法的create_index参数要为True。之后调用insert_qa_pairs方法插入数据。这里的qa_pairs可以通过以下代码读取之前整理好的csv文件得到。

def get_qa_pairs(csv_path):
qa_pairs = pd.read_csv(csv_path)
qa_pairs = list(zip(qa_pairs['question'], qa_pairs['answer']))
return qa_pairs

经过上述步骤,我们就准备好了聊天数据了(需要注意的是,这里都是单轮对话数据,多轮对话功能还在进一步开发中)。
接着,使用下面的代码我们就可以愉快的开始聊天了。

import sys
from elasticsearch import Elasticsearch
class ESChat(object):
def __init__(self, ip, port, index_name):
self.es = Elasticsearch(hosts=[ip], port=port)
self.index = index_name
def search(self, input_str):
""" Args: input_str: 用户问句 Returns: 由匹配的question、answer和其分数score构成的字典的列表 """
dsl = {
"query": {
"match": {
"question": input_str
}
}
}
hits = self.es.search(index=self.index, body=dsl)["hits"]["hits"]
qa_pairs = []
for h in hits:
qa_pairs.append(
{ 'score': h['_score'], 'question': h['_source']['question'], 'answer': h['_source']['answer']})
return qa_pairs
def chat(self):
"""聊天方法,在系统输出'> '后输入句子,得到系统回复,输入exit结束聊天。"""
sys.stdout.write("> ")
sys.stdout.flush()
sentence = sys.stdin.readline().strip()
while sentence:
if sentence == 'exit':
break
print(self.search(sentence)[0]['answer'])
print("> ", end='')
sys.stdout.flush()
sentence = sys.stdin.readline().strip()
if __name__ == '__main__':
es_chat = ESChat(ip='localhost', port=9200, index_name='qa')
es_chat.chat()

聊天效果截图如下:
《使用Elasticsearch做一个简易的检索式聊天机器人》
好吧,聊天体验看来并不愉快。总结原因,一个是搜集的语料可能有问题或者是我整理的过程出错了,还有一个主要的原因是这里没有结合语义等信息,只是单纯的检索匹配。
虽然效果不理想,但不失为一个制作聊天机器人的尝试,对于这个检索式机器人我的下一步优化方案大致是:

  • 清理语料,提升语料质量
  • 结合语义信息
  • 完善搜索匹配方式

推荐阅读
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 本文介绍了Hive常用命令及其用途,包括列出数据表、显示表字段信息、进入数据库、执行select操作、导出数据到csv文件等。同时还涉及了在AndroidManifest.xml中获取meta-data的value值的方法。 ... [详细]
  • {moduleinfo:{card_count:[{count_phone:1,count:1}],search_count:[{count_phone:4 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 前言:拿到一个案例,去分析:它该是做分类还是做回归,哪部分该做分类,哪部分该做回归,哪部分该做优化,它们的目标值分别是什么。再挑影响因素,哪些和分类有关的影响因素,哪些和回归有关的 ... [详细]
author-avatar
cr罗详青
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有