任务需求
为增强KBQA问答应用的准确率,更好地获取用户问题返回用户答案,针对KG中实体名称构建实体链接表。
实现思路
构建方法:先构建比较重要的几个大类、军事装备、军事目标、国家、人物、部队;
别名:从数据库中拿取实体的别名,并根据类型进行删选,例如下图,在数据库中查询德国的别名有5个,只取类别是国家的,作为德国的实体链接映射结果
简称和缩略词:针对武器装备,根据人工整理出来的装备前缀后缀和本体概念,取实体中去掉前缀后缀的部分为简称,处理后再人工筛选
接口设计:接口设计成可以按类别构建,方便构建后人工检查;同时设计可以动态人工添加新的映射
思路:
代码思路
- 计划通过设计接口实现需求,设计md文档
- 实现代码:
@api.route('/gen_entity', )
class genQA(Resource):
@api.doc('生成实体名')
def post(self):
logger.debug('Process {} - Thread {}'.format(os.getpid(), threading.current_thread().ident))
logger.info('\n前台传参:{}'.format(api.payload))
try:
request_data = api.payload
entity_class = request_data['entity_class']
entityList = request_data['entityList']
get_entity.search_entityList(entity_class, entityList)
return {
'retCode': 0,
'data': {
'entity_class': entity_class
}
}
except Exception as e:
exception_id = str(uuid.uuid1())
logger.error('exceptionId:{}\tmessage:{}'.format(exception_id, traceback.format_exc()))
return {
'retCode': 999999,
'message': str(e),
'exceptionId': exception_id
}, 500
class entityLink(object):
def __init__(self):
global graph
graph = tf.get_default_graph()
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
global sess
sess = tf.Session(config=config)
#接口传入是后缀名情况下
def search_entityList(self,entity_class,entityList):
for entity_suffix in entityList:
#*python实现mongo中查询语法*
entity1 = qa_col1.find({"sourceName":re.compile(entity_suffix),"sourceType":{"$ne":"ontology"},"relationName":"名称"})
entity = pd.DataFrame(list(entity1))
for index,row in entity.iterrows():
sourceId = row["sourceId"]
sourceName = row["sourceName"]
sourceType = row["sourceType"]
relationName = row["relationName"]
#targetName 取值为去掉后缀名后的只保留前半部分信息
suffix_entity = sourceName.replace(entity_suffix, "")
targetName = suffix_entity
self.insert_to_mongo(sourceId,sourceName,sourceType,relationName,targetName,entity_class)
def insert_to_mongo(self,sourceId,sourceName,sourceType,relationName,targetName,entity_class):
record = {
"sourceId": sourceId,
"sourceName": sourceName,
'sourceType': sourceType,
'relationName': relationName,
'targetName':targetName,
'entity_class': entity_class,
}
qa_col2.insert_one(record)
以上代码展示了一个接口查询储存方式,接下来呈现几种限制条件的查询代码书写:
#避免sourceName重复条件下,以“_”切分,取切分后前面部分内容
def search_entityList_country(self, entityList):
for entity_suffix in entityList:
entity1 = qa_col1.find(
{"sourceName": re.compile(entity_suffix), "sourceType": "国家", "relationName": "别名"})
entity = pd.DataFrame(list(entity1))
temp_list = [] #添加列表进行暂存,避免sourceName重复
for index, row in entity.iterrows():
if row["sourceName"] in temp_list:
pass
else:
temp_list.append(row['sourceName'])
sourceId = row["sourceId"]
sourceName = row["sourceName"]
sourceType = row["sourceType"]
relationName = row["relationName"]
suffix_entity = sourceName.split("_")[0]
targetName = suffix_entity
self.insert_to_mongo(sourceId, sourceName, sourceType, relationName, targetName)
mongo知识学习
将该列列名值全部更改:
db.getCollection("集合名").update({"列名":"列名值"},{$set:{"列名":"列名新值"}},{multi:true})
删除targetName是布或者飞机
db.getCollection("entity_link_test").remove({'$or':[{"targetName":"布"},{"targetName":"飞机"}]})