多读书多实践,勤思考善领悟

从零开始学习知识图谱 之 四.电影知识图谱构建 4.基于ElasticSearch的简单语义搜索

本文于1734天之前发表,文中内容可能已经过时。

一. 简介

本次我们基于浙江大学在openKG上提供的基于elasticsearch的KBQA实现及示例,我们将其精简并将应用到自己的知识图谱上。

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。我们将通过提供的接口进行查询,例如查询朱一龙的相关信息,可以通过下列命令进行查询:

1
curl -XGET 'localhost:9200/demo/baidu_baike/_search?&pretty' -H 'Content-Type:application/json' -d' { "query":{ "bool":{ "filter":{ "term":{"subj":"朱一龙"} } } } } '

我们的目的就是在数据导入elasticsearch后,通过将输入的自然语言分解来构建这样的查询模板,从而实现搜索功能。

本教程的项目代码放在github上,下载地址为《从零开始学习知识图谱》项目源代码

二. 环境准备

1. 操作系统

支持操作系统:windows、macOS、Linux。为了方便大家搭建开发环境,笔者尽可能在windows下构建,系列篇未特意说明时操作系统都是windows。Linux安装可以参考VirtualBox虚拟机安装UbuntuVirtualBox虚拟机安装CentOS8进行安装。

2. jdk

安装参见windows系统安装JDK

3. Python3

安装参见从零开始学习知识图谱 之 一

4. ElasticSearch

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。ElasticSearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。

安装

elasticsearch 官网下载安装包,软件不需要安装,需要配置相应的Java环境。详细使用可阅读官方教程

运行 ./bin/elasticsearch.bat即可开启服务。

在开启服务后,您可以通过 curl 'http://localhost:9200'来访问 elasticsearch。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"name" : "DESKTOP-3AFDEBF",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "0HpHJxLAREq6SntFdfVSPQ",
"version" : {
"number" : "7.4.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "22e1767283e61a198cb4db791ea66e3f11ab9910",
"build_date" : "2019-09-27T08:36:48.569419Z",
"build_snapshot" : false,
"lucene_version" : "8.2.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}

三. 数据准备

1. 数据库到JSON

elasticsearch 要求文档的输入格式为 JSON,因此我们需要把数据库中的数据转化为JSON形式。比如:

1
2
3
4
5
6
7
8
9
{
"subj": "周星驰",
"po": [ {"pred": "actor_foreName", "obj": "Stephen Chow"},
{"pred": "actor_nationality", "obj": "中国"},
{"pred": "actor_constellation", "obj": "巨蟹座"},
{"pred": "actor_birthPlace", "obj": "香港"},
{"pred": "actor_birthDay", "obj": "1962年6月22日"} ]
...
}

对应代码为./utils/get_json.py,该程序的工作流程为对数据库进行查表,而后将对应信息保存到字典里。通过 json.dumps()将Python对象转化为JSON格式并写成文件。

运行get_json.py,生成actor.json和movie.json

1
2
3
4
5
6
C:\my\Python\python.exe C:/d/mmm/pycharm/elasticsearch/utils/get_json.py
max_id: 13967
max_id: 22219
tuple index out of range

Process finished with exit code 0

可能出现的问题:
python pyahocorasick包安装失败解决方法

2. 属性同义词扩展

为了支持对同一类问题的不同询问方式,我们采用同意属性映射来扩展属性,当遇到同义属性时,我们将其映射到数据集中的属性上,对应于./data/attr_mapping.txt 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
actor_chName 中文名 名字 姓名
actor_foreName 英文名 外文名
actor_bio 简介 简历 介绍
actor_nationality 国籍
actor_constellation 星座
actor_birthPlace 出生地 老家
actor_birthPlace 出生日期 生日
actor_repWorks 代表作 作品
actor_achiem 成就 获奖 奖项
actor_birthPlace 经纪公司
movie_chName 片名
movie_foreName 英文片名 外文片名
movie_prodTime 出品时间
movie_foreName 出品公司 制作方
movie_director 导演
movie_screenwriter 编剧
movie_genre 类型
movie_star 主演 演员 参演人员
movie_length 片长 时长
movie_rekeaseTime 上映时间
movie_language 对白语言 语言 语种
movie_achiem 奖项 获奖 成就

3. 建立属性间映射 get_ac_attr.py

我们通过cpikle 对属性间映射进行打包,其中属性间的映射通过ahocorasic.Automaton()进行处理。对应的输出为./data/attr_ac.pkl.

运行get_ac_attr.py,生成./data/attr_ac.pkl

1
2
3
C:\my\Python\python.exe C:/d/mmm/pycharm/elasticsearch/utils/get_ac_attr.py

Process finished with exit code 0

4. 获取属性值和属性间的映射 get_total_val.py

通过对数据库进行查表得到各个实体的属性和属性值,而后将其存储为./data/total_val.txt 文件在搜索时使用。

运行get_total_val.py,生成actor.txt和movie.txt

1
2
3
4
5
6
C:\my\Python\python.exe C:/d/mmm/pycharm/elasticsearch/utils/get_total_val.py
max_id: 13967
max_id: 22219
tuple index out of range

Process finished with exit code 0

5. 获取所有实体

我们直接通过MySQL Workbench操作得到所有实体的倒出并存储为一个文件,名为./data/all_entity.txt。

文件格式如下:

1
2
3
4
5
6
7
8
9
周星驰
戚美珍
车保罗
黎小田
高雄
石天 (原名:刘伟城)
张学友
章子怡
......

四. 将数据导入到 elasticsearch

1. 在 elasticsearch 中新建 index 和 type

这里我们遵循教程中的要求,采用下列命令建立 index 和 type:

可以用elasticsearch-head或CURL。

ealsticsearch只是后端提供各种api,那么怎么直观的使用它呢?elasticsearch-head将是一款专门针对于elasticsearch的客户端工具。elasticsearch-head配置包,下载地址:https://github.com/mobz/elasticsearch-head 。安装可以参考文章windows下安装ElasticSearch的Head插件

我们这里选择用CURL,去curl官网下载对应版本的包,解压后打开CMD切换到对应目录下运行CURL.exe文件,

如果把该CURL.exe文件复制到C:\Windows\System32目录下,则不需要切换目录,可以直接运行curl命令。

a. 用下列命令建立 index 和 type:

1
curl -XPUT "localhost:9200/demo?pretty" -H "Content-Type: application/json" -d" { \"mappings\": { \"properties\": { \"subj\": {\"type\": \"keyword\"}, \"po\":{ \"type\": \"nested\", \"properties\":{ \"pred\":{\"type\":\"keyword\"}, \"obj\":{\"type\":\"keyword\"} } } } } } "

运行结果

1
2
3
4
5
6
C:\Users\mmm>curl -XPUT "localhost:9200/demo?pretty" -H "Content-Type: application/json" -d" { \"mappings\": { \"properties\": { \"subj\": {\"type\": \"keyword\"}, \"po\":{ \"type\": \"nested\", \"properties\":{ \"pred\":{\"type\":\"keyword\"}, \"obj\":{\"type\":\"keyword\"} } } } } } "
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "demo"
}

注意:笔者使用的Elasticsearch>7.0,Elasticsearch 7.0及以后版本移除映射类型

b. 可用下列命令查询是否添加成功

1
curl -XGET localhost:9200/_search?pretty

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C:\Users\mmm>curl -XGET localhost:9200/_search?pretty
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}

c. 如果创建错了,可用下列命令删除索引

1
curl -XDELETE localhost:9200/demo

2. 数据导入 insert.py

为了测试简单,把actor.json文件改名为../data/baidu_baike.json。

运行 insert.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
C:\my\Python\python.exe C:/d/mmm/pycharm/elasticsearch/utils/insert.py
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
11000
12000
13000

Process finished with exit code 0

此时已经可以通过curl方式检索知识库了。

五. 检索知识库

DOS默认的是(GB2312),让cmd dos 支持utf-8方法CHCP 65001,关闭cmd,CHCP又还原成936。

1
2
C:\Users\mmm>CHCP 65001 
Active code page: 65001

curl方式检索知识库,可用下列命令,如检索:周星驰

1
curl -XGET "localhost:9200/demo/_doc/_search?&pretty" -H "Content-Type:application/json" -d" { \"query\":{ \"bool\":{ \"filter\":{ \"term\":{\"subj\":\"\u5468\u661f\u9a70\"} } } } }

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
curl -XGET "localhost:9200/demo/_doc/_search?&pretty" -H "Content-Type:application/json" -d" { \"query\":{ \"bool\":{ \"filter\":{ \"term\":{\"subj\":\"\u5468\u661f\u9a70\"} } } } }"
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "demo",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.0,
"_source" : {
"subj" : "周星驰",
"po" : [
{
"pred" : "actor_bio",
"obj" : " 周星驰,1962622日生于香港,祖籍浙江宁波,中国香港演员、导演、编剧、制作人、商人,毕业于无线电视艺员训练班。1980年成为丽的电视台的特约演员,从而进入演艺圈。1981年出演个人首部电视剧《IQ成熟时》。1988年将演艺事业的重心转向大银幕,并于同年出演电 影处女作《捕风汉子》。1990年凭借喜剧片《一本漫画闯天涯》确立其无厘头的表演风格 [1] ;同年,因其主演的喜剧动作片《赌圣》打破香港地区票 房纪录而获得关注 [2] 。1991年主演喜剧片《逃学威龙》,并再次打破香港地区票房纪录 [3] 。1995年凭借喜剧爱情片《大话西游》奠定其在华语影 坛的地位。1999年自导自演的喜剧片《喜剧之王》获得香港电影年度票房冠军 [4] 。2002年凭借喜剧片《少林足球》获得第21届香港电影金像奖最佳男 主角奖以及最佳导演奖 [5] 。2003年成为美国《时代周刊》封面人物 [6] 。2005年凭借喜剧动作片《功夫》获得第42届台湾电影金马奖最佳导演奖 [7] 。2008年自导自演的科幻喜剧片《长江7号》获得香港电影年度票房冠军 [8] 。2013年执导古装喜剧片《西游·降魔篇》,该片以2.18亿美元的票房 成绩打破华语电影在全球的票房纪录 [9-10] 。2016年担任科幻喜剧片《美人鱼》的导演、编剧、制作人,该片以超过33亿元的票房创下中国内地电影票房纪录 [11-14] 。2017128日,担任监制、编剧的古装喜剧片《西游伏妖篇》上映 [15] 。2018年执导《美人鱼2》 [16] 。演艺事业外,周星驰 还涉足商界。1989年成立星炜有限公司 [17] 。1996年成立星辉公司 [18] 。2010年出任比高集团有限公司执行董事 [19] 。 "
},
{
"pred" : "actor_foreName",
"obj" : "Stephen Chow"
},
{
"pred" : "actor_nationality",
"obj" : "中国"
},
{
"pred" : "actor_constellation",
"obj" : "巨蟹座"
},
{
"pred" : "actor_birthPlace",
"obj" : "香港"
},
{
"pred" : "actor_birthDay",
"obj" : "1962622"
},
{
"pred" : "actor_repWorks",
"obj" : "赌圣、逃学威龙系列、唐伯虎点秋香、大话西游系列、喜剧之王、少林足球、功夫、长江七号"
},
{
"pred" : "actor_achiem",
"obj" : "获得两届香港电影金像奖最佳影片\n第21届香港电影金像奖最佳导演\n第21届香港电影金像奖最佳男主角\n第42届台湾电影金马奖最佳导演\n第42届台湾电影金马奖最佳剧情片\n\n第25届台湾电影金马奖最佳男配角\n第28届大众电影百花奖优秀故事片\n第23届香港电影评论学会大 奖最佳导演\n第8届香港电影评论学会大奖最佳电影\n第2届香港电影评论学会大奖最佳男主角\n第37届亚太电影节最佳男主角\n第13届亚洲电影博览会最 佳导演\n获得两届香港电影金紫荆奖最佳影片\n第01届香港电影金紫荆奖最佳男主角\n国际杰人会港澳杰人之星等\n收起"
},
{
"pred" : "actor_brokerage",
"obj" : "星辉公司、比高集团"
}
]
}
}
]
}
}

六. 程序核心 ./utils/views.py

改程序对输入的自然语言问题进行解析,识别出出现在其中的实体名、属性及属性值,并将其转换为对应的logical form。总体流程和浙大的类似,我只是将其从Django 中提取出来方便对于框架不懂的人直接使用。关于views.py的详细解释请看浙大的教程