![21f040a2ac062d43825143a44765486d.png](https://i-blog.csdnimg.cn/blog_migrate/31ebcdd90baec14ba484b179fc881a8b.jpeg)
本次我们基于浙江大学在openKG上提供的基于elasticsearch的KBQA实现及示例,我们将其精简并将应用到自己的知识图谱上。目前的精力在知识图谱构建上,等有时间希望能完成一个自己的语义搜索和KBQA…
- 简介
- elasticsearch 的安装与运行
- 数据准备
- 数据库到JSON
- 属性同义词扩展
- 建立属性间映射 get_ac_attr.py
- 获取属性值和属性间的映射 get_total_val.py
- 获取所有实体 get_all_entity.py
- 将数据导入到 elasticsearch
- 在 elasticsearch 中新建 index 和 type
- 数据导入 insert.py
- 程序核心 ./utils/views.py
简介
基于ElasticSearch的简单语义搜索 项目地址github.comElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。我们将通过提供的接口进行查询,例如查询朱一龙的相关信息,可以通过下列命令进行查询:
curl -XGET 'localhost:9200/demo/baidu_baike/_search?&pretty' -H 'Content-Type:application/json' -d'
{
"query":{
"bool":{
"filter":{
"term":{"subj":"周星驰"}
}
}
}
}
'
我们的目的就是在数据导入elasticsearch后,通过将输入的自然语言分解来构建这样的查询模板,从而实现搜索功能。
![d456a313464e31f45c6d0666db48cd53.png](https://i-blog.csdnimg.cn/blog_migrate/22561b7e8093670e60f2166b354a1b8d.jpeg)
前置条件:需要在 SQL 数据库中有 百度百科数据,可以通过百度网盘下载,提取码 524j 。而后通过 mysql -uroot -pnlp < baidu_baike.sql; 命令导入 SQL 数据库,若报错提示 ERROR 1046 (3D000) at line 22: No database selected,是因为 sql 文件里没指定数据库,因此我们需要先创建数据库,而后指定使用它。因此首先在 21行添加 CREATE DATABASE movie_baidu_baike; 而后添加 USE movie_baidu_baike; (互动百科的就是 movie_baidu_baike)来指定使用该数据库。
elasticsearch 的安装与运行
本项目采用的是 es 5.0.1,通过如下命令进行安装:
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.0.1.tar.gz;
tar -xzf elasticsearch-5.0.1.tar.gz
cd elasticsearch-5.0.1/
而后运行 ./bin/elasticsearch.sh
即可开启服务。
在开启服务后,您可以通过 curl 'http://localhost:9200'
来访问 elasticsearch。
数据准备
数据库到JSON
elasticsearch 要求文档的输入格式为 JSON,因此我们需要把数据库中的数据转化为JSON形式。比如:
{
"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格式并写成文件。
这步会得到 baidu_baike.json。
属性同义词扩展
为了支持对同一类问题的不同询问方式,我们采用同意属性映射来扩展属性,当遇到同义属性时,我们将其映射到数据集中的属性上,对应于./data/attr_mapping.txt 文件:
actor_chname 中文名 名字 姓名
actor_forename 英文名 外文名
actor_bio 简介 简历 介绍
actor_nationality 国籍
actor_constellation 星座
actor_birthplace 出生地 老家
actor_birthday 出生日期 生日
actor_repworks 代表作 作品
actor_achiem 成就 获奖 奖项
actor_brokerage 经纪公司
movie_chname 片名
movie_forename 英文片名 外文片名
movie_prodtime 出品时间
movie_prodcompany 出品公司 制作方
movie_director 导演
movie_screenwriter 编剧
movie_genre 类型
movie_star 主演 演员 参演人员
movie_length 片长 时长
movie_releasetime 上映时间
movie_language 对白语言 语言 语种
movie_achiem 奖项 获奖 成就
建立属性间映射 get_ac_attr.py
我们通过cpikle 对属性间映射进行打包,其中属性间的映射通过ahocorasic.Automaton()进行处理。对应的输出为./data/attr_ac.pkl.
获取属性值和属性间的映射 get_total_val.py
通过对数据库进行查表得到各个实体的属性和属性值,而后将其存储为./data/total_val.txt 文件在搜索时使用。
获取所有实体 get_all_entity.py
我们直接通过Mysql的的操作得到所有实体的倒出并存储为一个文件,名为./data/all_entity.txt。
将数据导入到 elasticsearch
在 elasticsearch 中新建 index 和 type
这里我们遵循教程中的要求,采用下列命令建立 index 和 type:
curl -XPUT 'localhost:9200/demo?pretty' -H 'Content-Type: application/json' -d'
{
"mappings": {
"baidu_baike": {
"properties": {
"subj": {"type": "keyword"},
"height": {"type": "integer"},
"weight": {"type": "integer"},
"po":{
"type": "nested",
"properties":{
"pred":{"type":"keyword"},
"obj":{"type":"keyword"}
}
}
}
}
}
}
'
对应脚本存储在 utils/query_create.sh; 中,若想删除索引,则用 utils/query_delete.sh 里的命令。
数据导入 insert.py
我们直接调用浙大的./utils/inset.py 程序,修改数据路径为我们的即可。
begin_insert_job("demo", "baidu_baike", "../data/baidu_baike.json")
此时已经可以通过curl方式检索知识库了。您可以直接运行 ./utils/query_cmd.sh 进行简单查询,也可以通过 query_size.sh 查看 ES 中当前索引的数据量。
程序核心 ./utils/views.py
改程序对输入的自然语言问题进行解析,识别出出现在其中的实体名、属性及属性值,并将其转换为对应的logical form。总体流程和浙大的类似,我只是将其从Django 中提取出来方便对于框架不懂的人直接使用。关于views.py的详细解释请看
浙大的教程openkg1.oss-cn-beijing.aliyuncs.com