将知识提取并生成结构化的数据,建立知识库。 KBQA:Knowledge Base Question Answer,即知识库问答。
简单讲就是将问题带入提前准备好的知识库寻求答案的一种问答系统。基本流程就是给定自然语言问题,问答系统通过对自然语言问题进行语义理解和解析,进而利用知识库进行查询、推理得出答案,这个过程主要运用$REFO$库的对象正则表达式匹配得到结果,然后利用对应的$SPARQL$查询语句,请求后台基于$TDB$知识谱图数据库的服务,最终得到问题对应的答案。如下图所示:
此系统是利用正则表达式来进行语义解析,这里利用第三方库(jieba)来完成初步的自然语言处理(分词、实体识别),然后利用支持词级别正则匹配的库来完成后续的语义匹配。
为了更好的理解句义 , 首先利用中文分词 、 命名实体识别等自然语言技术找到问句中所涉及到的实体和关键 词 , 然后去数据库中进行检索查找 。 分词和实体识别(人名和电影名)这里用$jieba$来完成,$jieba$是一个轻量级的中文分词工具,可以将问题文本中出现的词语识别出,在最短的时间内精确地分开词语,适合做大规模的文本分析。针对不同领域的专业词汇分词任务,$jieba$支持自定义词典。在本系统中,直接把数据库中的人民和电影名导出,作为外部词典;使用$jieba$的时候直接加载外部词典,提高电影实体识别的准确率。
将自然语言转为以词为基础的基本单位后,使用$REFO(Regular \ Expressions \ for \ Objects)$来完成语义匹配。
匹配成功后,得到其对应的预先编写的$SPARQL$语句模板,在向$Fuseki$服务器发送查询,最后返回结果并打印。
系统的简单架构图如下:
这里知识库存储的实现采用"Python查询Jena的电影知识图谱"这篇文章的方式,使用D2RQ来生成映射文件,这里取名为movie_mapping.ttl
,并将mapping文件中的数据列名对应到我们设计的本体文件中;然后根据修改后的mapping文件生成demo_movie.ttl
;最后利用Jena 装载RDF数据,将demo_movie.ttl 文件加载到 TDB 中,形成知识图谱的物理存储。
因为知识图谱问答需要很多推理规则,对可视化没有太多的要求,所以这里选择$Jena+Fuseki$的框架。
Apache jena
Apache Jena是一个开源的Java语义网框架,用于构建语义网和链接数据应用,是使用最广泛、文档最全、社区最活跃的一个开源语义网框架。这里用到的组件有:TDB、Fuseki。
首先利用中文分词 、 命名实体识别等自然语言技术找到问句中所涉及到的实体和关键词 , 然后去数据库中进行检索查找 。 分词和实体识别(人名和电影名)这里用$jieba$来完成,$jieba$是一个轻量级的中文分词工具,可以将问题文本中出现的词语识别出,在最短的时间内精确地分开词语,适合做大规模的文本分析。针对不同领域的专业词汇分词任务,$jieba$支持自定义词典。在本系统中,有些经常会被使用的词并不能被正确切分。如:“喜剧电影”、“恐怖电影”、“科幻电影”、“喜剧演员”、“出生日期”等,在分词时$jieba$把它们当作一个词来处理,所以手动调整词语的频率使得“喜剧电影”能被正确切分为“喜剧”和“电影”。至于实体识别,$jieba$对于人名的识别度还可以,但是电影名称的识别精度太低。因此直接把数据库中的人民和电影名导出,作为外部词典;使用$jieba$的时候直接加载外部词典,提高电影实体识别的准确率。
将自然语言转为以词为基础的基本单位后,使用$REFO(Regular \ Expressions \ for \ Objects)$来完成语义匹配。
匹配成功后,得到其对应的预先编写的$SPARQL$语句模板,在向$Fuseki$服务器发送查询,最后返回结果。
$SPARQL$语句模板如下(部分):
支持的问题类型有:
1. 某演员演了什么电影?
2. 某电影有哪些演员参演?
3. 演员A和演员B合作出演了哪些电影?
4. 某演员参演的评分大于X的电影有哪些?
5. 某演员出演过哪些类型的电影?
6. 某演员出演的XX类型电影有哪些?
7. 某演员出演了多少部电影?
8. 某演员的生日/出生地/英文名/简介。
9. 某电影的简介/上映日期/评分。
Streamlit 是一个基于 Python 的 Web 应用程序框架,使用方便简单。
安装streamlit
库,使用百度源:
pip install streamlit -i https://mirror.baidu.com/pypi/simple/
基于问题类型创建streamlit_app.py
文件:
# encoding=utf-8
from kg_demo_movie.KB_query.query_main import QAInterface
import streamlit as st
@st.cache(allow_output_mutation=True)
def get_interface():
interface = QAInterface()
return interface
qa_interface = get_interface()
st.title("电影知识图谱问答系统")
st.text_area('系统支持的问题类型', """1. 某演员演了什么电影?
2. 某电影有哪些演员参演?
3. 演员A和演员B合作出演了哪些电影?
4. 某演员参演的评分大于X的电影有哪些?
5. 某演员出演过哪些类型的电影?
6. 某演员出演的XX类型电影有哪些?
7. 某演员出演了多少部电影?
8. 某演员的生日/出生地/英文名/简介。
9. 某电影的简介/上映日期/评分。""", height=250)
question = st.text_input("请输入你的问题:")
if question != "":
st.text(qa_interface.answer(question))
# st.write(qa_interface.answer(question))
运行streamlit_app.py
,访问相应的端口即可得到系统界面:
第一步:安装相关的库
例如安装streamlit库;由于环境配置各不相同,这里不具体列举,使用时可运行py文件,通过提示来安装相关的库。
第二步:装载 RDF 数据,将 demo_movie.ttl 文件加载到 TDB 中
进入apache-jena-3.12.0/bin
目录,运行下面的命令将demo_movie.ttl加载到TDB文件中:
./tdbloader --loc="/home/kg/Desktop/KG-movie-demo/jena/apache-jena-fuseki-3.12.0/tdb" /home/kg/Desktop/KG-demo-for-movie-master/d2rq-0.8.1/demo_movie.ttl
参数说明:–loc 指定 tdb的存储位置,第二个参数/home/kg/KG-movie-demo/d2rq-0.8.1/demo_movie.ttl为通过d2rq生成的ttl文件。
第三步:开启Fuseki 服务
进入 /home/kg/Desktop/KG-movie-demo/jena/apache-jena-fuseki-3.12.0
路径, 运行./fuseki—server
,程序会在当前目录下自动创建 run 文件夹,在 run 文件夹下的 configuration 内创建名为 fuseki_conf.ttl 的配置文件;Fuseki默认的端口为3030,浏览器访问:http://localhost:3030/
这里需要自行修改配置文件,具体为修改本体文件路径和TDB路径。
第四步:运行web服务
在/home/kg/Desktop/KG-movie-demo
路径下,运行streamlit_app.py
文件:
streamlit run streamlit_app.py --server.enableCORS=true
窗口会给出相应的访问地址,并会自动跳转浏览器并打开相应窗口,如果没有自动打开,可以在浏览器手动输入指定的地址。
需要说明的是最重要的一步就是要修改fuseki_conf.ttl配置文件中本体文件路径和TDB文件的路径;TDB文件已经在apache-jena-fuseki-3.12.0
文件夹中生成,所以第二步可选择省略。