commit
This commit is contained in:
parent
2bc1109af8
commit
47e1f40355
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
from ExcelReader import convertFile
|
||||
from ExcelReader import generateOutputPaths
|
||||
from ExcelReader import generateSimilarWordMap
|
||||
|
||||
if __name__ == "__main__":
|
||||
targetPath = "..\\..\\COVID19"
|
||||
|
||||
vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath = generateOutputPaths(targetPath, "COVID19")
|
||||
|
||||
excelPath ="..\\excel\\COVID19\\SmartKG_KGDesc_COVID19_zh.xlsx"
|
||||
|
||||
similarWordMap = generateSimilarWordMap("..\\excel\\COVID19\\similarWords_COVID19_zn.tsv")
|
||||
|
||||
convertFile(excelPath, [], ["COVID19"], similarWordMap, vJsonPath, eJsonPath, intentPath, entityMapPath, True, colorJsonPath)
|
|
@ -0,0 +1,15 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
from ExcelReader import convertFile
|
||||
from ExcelReader import generateOutputPaths
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
targetPath = "..\\..\\COVID19_en"
|
||||
|
||||
vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath = generateOutputPaths(targetPath, "COVID19_en")
|
||||
|
||||
excelPath = "..\\excel\\COVID19\\SmartKG_KGDesc_COVID19_en.xlsx"
|
||||
|
||||
convertFile(excelPath, [], ["COVID19_en"], [], vJsonPath, eJsonPath, intentPath, entityMapPath, True, colorJsonPath)
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
from ExcelReader import convertFile
|
||||
from ExcelReader import generateOutputPaths
|
||||
|
||||
default_rules = ["PhonicsGrade7\tPOSITIVE\t声|音调|传播", "MechanicsGrade7\tPOSITIVE\t力|运动|向量"]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
targetPath = "..\\..\\Physics"
|
||||
|
||||
vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath = generateOutputPaths(targetPath, "PhonicsGrade7")
|
||||
excelPath = "..\\excel\\Physics\\SmartKG_KGDesc_PhonicsGrade7_zh.xlsx"
|
||||
convertFile(excelPath, [], ["PhonicsGrade7"], [], vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath)
|
||||
|
||||
vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath = generateOutputPaths(targetPath, "MechanicsGrade7")
|
||||
excelPath = "..\\excel\\Physics\\SmartKG_KGDesc_MechanicsGrade7_zh.xlsx"
|
||||
convertFile(excelPath, [], ["MechanicsGrade7"], [], vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath)
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
from ExcelReader import convertFile
|
||||
from ExcelReader import generateOutputPaths
|
||||
|
||||
default_rules = []
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
targetPath = "..\\..\\Physics2"
|
||||
|
||||
scenario = "MotionAndPower"
|
||||
|
||||
vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath = generateOutputPaths(targetPath, scenario, True)
|
||||
excelPath = "..\\excel\\Physics2\\SmartKG_KGDesc_MotionAndPower_zh.xlsx"
|
||||
convertFile(excelPath, [], [scenario], [], vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath)
|
||||
|
||||
scenario = "Phonics"
|
||||
|
||||
vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath = generateOutputPaths(targetPath, scenario, False)
|
||||
excelPath = "..\\excel\\Physics\\SmartKG_KGDesc_PhonicsGrade7_zh.xlsx"
|
||||
convertFile(excelPath, [], [scenario], [], vJsonPath, eJsonPath, intentPath, entityMapPath, colorJsonPath)
|
|
@ -0,0 +1,178 @@
|
|||
[
|
||||
{
|
||||
"headVertexId": "entity_gainian1_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian2_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian3_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian7_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian3_MotionAndPower",
|
||||
"relationType": "测量工具为",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian4_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian5_MotionAndPower",
|
||||
"relationType": "产生",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian3_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian3_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian6_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian8_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian9_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian8_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian13_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian9_MotionAndPower",
|
||||
"relationType": "相关物理量有",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian10_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian9_MotionAndPower",
|
||||
"relationType": "相关物理量有",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian11_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian8_MotionAndPower",
|
||||
"relationType": "判断标准",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian12_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian13_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian14_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian14_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian15_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian14_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian16_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian15_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian17_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian15_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian18_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_MotionAndPower",
|
||||
"relationType": "属于",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian19_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian8_MotionAndPower",
|
||||
"relationType": "属于",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian19_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian19_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian20_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian20_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian21_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian19_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian22_MotionAndPower"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian19_MotionAndPower",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
],
|
||||
"tailVertexId": "entity_gainian23_MotionAndPower"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,98 @@
|
|||
[
|
||||
{
|
||||
"headVertexId": "entity_gainian1_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian2_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian3_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian4_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian8_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian1_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian11_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian4_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian5_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian4_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian6_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian4_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian7_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian8_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian9_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian8_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian10_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian11_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian12_Phonics"
|
||||
},
|
||||
{
|
||||
"headVertexId": "entity_gainian11_Phonics",
|
||||
"relationType": "包含",
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
],
|
||||
"tailVertexId": "entity_gainian13_Phonics"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,444 @@
|
|||
[
|
||||
{
|
||||
"id": "entity_gainian1_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "力",
|
||||
"nodeType": "ROOT",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "物体对物体的作用"
|
||||
},
|
||||
{
|
||||
"name": "作用效果",
|
||||
"value": "改变物体运动状态;改变物体形状"
|
||||
},
|
||||
{
|
||||
"name": "三要素",
|
||||
"value": "大小、方向、作用点"
|
||||
},
|
||||
{
|
||||
"name": "特点",
|
||||
"value": "力的作用是相互的"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian2_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "重力",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "由于地球的吸引而使物体受到的力"
|
||||
},
|
||||
{
|
||||
"name": "公式",
|
||||
"value": "G=mg"
|
||||
},
|
||||
{
|
||||
"name": "方向",
|
||||
"value": "竖直向下"
|
||||
},
|
||||
{
|
||||
"name": "作用点",
|
||||
"value": "重心(悬挂法)"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian3_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "弹力",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "物体由于发生弹性形变而产生的力"
|
||||
},
|
||||
{
|
||||
"name": "产生条件",
|
||||
"value": "1.物体相互接触;2.物体具有弹性,且发生弹性形变"
|
||||
},
|
||||
{
|
||||
"name": "包括",
|
||||
"value": "弹簧伸长与压缩时的力,压力、支持力、绳子拉力等"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian4_MotionAndPower",
|
||||
"label": "物体",
|
||||
"leadSentence": "",
|
||||
"name": "弹簧测力计",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "原理",
|
||||
"value": "在弹性限度内,弹簧的伸长量与受到的拉力成正比"
|
||||
},
|
||||
{
|
||||
"name": "构造",
|
||||
"value": "弹簧、刻度盘、指针、挂钩、吊环"
|
||||
},
|
||||
{
|
||||
"name": "使用",
|
||||
"value": "量程、分度值"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian5_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "弹性形变",
|
||||
"nodeType": "ROOT",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "对弹性物体来说,形变后能自动恢复原状的最大限度叫弹性限度;物体在弹性限度内发生的形变叫做弹性形变"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian6_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "弹簧伸长与压缩时的力,压力、支持力、绳子拉力等",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian7_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "摩擦力",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "两个相互接触的物体,当它们相对滑动或有相对运动趋势时,在接触面上会产生一种阻碍相对运动或相对运动趋势的力,这种力叫做滑动摩擦力"
|
||||
},
|
||||
{
|
||||
"name": "产生条件",
|
||||
"value": "1.接触面粗糙 2.想物体相互接触并相互挤压 3.两物体间发生相对运动或有相对运动趋势"
|
||||
},
|
||||
{
|
||||
"name": "分类",
|
||||
"value": "静摩擦力、滑动摩擦力"
|
||||
},
|
||||
{
|
||||
"name": "影响滑动摩擦力因素",
|
||||
"value": "压力大小、接触面的粗糙程度"
|
||||
},
|
||||
{
|
||||
"name": "作用效果",
|
||||
"value": "阻碍物体的相对运动或相对运动趋势"
|
||||
},
|
||||
{
|
||||
"name": "作用点",
|
||||
"value": "在接触面上"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian8_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "机械运动",
|
||||
"nodeType": "ROOT",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": " 一个物体相对于另一个物体的位置,或者一个物体的某些部分相对于其他部分的位置,随着时间而变化的过程叫做机械运动"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian9_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "描述运动位置",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian10_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "长度",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "单位",
|
||||
"value": "国际单位米m"
|
||||
},
|
||||
{
|
||||
"name": "测量工具",
|
||||
"value": "刻度尺,估读到准确值的下一位"
|
||||
},
|
||||
{
|
||||
"name": "估测",
|
||||
"value": "选取标准进行对比"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian11_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "时间",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "单位",
|
||||
"value": "国际单位s"
|
||||
},
|
||||
{
|
||||
"name": "测量工具",
|
||||
"value": "停表"
|
||||
},
|
||||
{
|
||||
"name": "估测",
|
||||
"value": "选取标准进行对比"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian12_MotionAndPower",
|
||||
"label": "物体",
|
||||
"leadSentence": "",
|
||||
"name": "参照物",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "判断物体运动还是静止时,作为标准的物体"
|
||||
},
|
||||
{
|
||||
"name": "选择原则",
|
||||
"value": "不以研究对象本身为参照物"
|
||||
},
|
||||
{
|
||||
"name": "相对性",
|
||||
"value": "运动和静止的相对性"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian13_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "描述运动快慢",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [
|
||||
{
|
||||
"name": "三种比较方法",
|
||||
"value": "1.时间相同比路程 2路程相同比时间 3.时间路程均不相同比较路程与时间的比值"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian14_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "速度",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "路程与时间的比值"
|
||||
},
|
||||
{
|
||||
"name": "公式",
|
||||
"value": "v=s/t"
|
||||
},
|
||||
{
|
||||
"name": "单位",
|
||||
"value": "m/s"
|
||||
},
|
||||
{
|
||||
"name": "物理意义",
|
||||
"value": "描述物体运动快慢的物理量"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian15_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "直线运动",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian16_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "曲线运动",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian17_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "匀速直线运动",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian18_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "变速直线运动",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian19_MotionAndPower",
|
||||
"label": "关联",
|
||||
"leadSentence": "",
|
||||
"name": "运动和力",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [
|
||||
{
|
||||
"name": "关系",
|
||||
"value": "静止或匀速直线运动时不受力或者二力平衡;变速运动时,受非平衡力"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian20_MotionAndPower",
|
||||
"label": "规律",
|
||||
"leadSentence": "",
|
||||
"name": "牛顿第一定律",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "一切物体在没受到力的作用时,总保持静止状态或匀速直线运动状态"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian21_MotionAndPower",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "惯性",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "一切物体都有保持原来运动状态不变的性质,这种性质叫做惯性"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian22_MotionAndPower",
|
||||
"label": "规律",
|
||||
"leadSentence": "",
|
||||
"name": "二力平衡",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "物体受到几个力的作用时,如果保持静止或者匀速直线运动状态,则这几个力相互平衡。"
|
||||
},
|
||||
{
|
||||
"name": "条件",
|
||||
"value": "同体、等大、反向、共线"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian23_MotionAndPower",
|
||||
"label": "规律",
|
||||
"leadSentence": "",
|
||||
"name": "同一直线上二力的合成",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "大小",
|
||||
"value": "二力同向,合力为两个力的和;二力反向,合力为两个力的差的绝对值"
|
||||
},
|
||||
{
|
||||
"name": "方向",
|
||||
"value": "二力同向,方向不变;二力反向,方向与较大力的方向一致"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"MotionAndPower"
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,234 @@
|
|||
[
|
||||
{
|
||||
"id": "entity_gainian1_Phonics",
|
||||
"label": "概念",
|
||||
"leadSentence": "相关的概念有下面这些,请输入对应选项查看详情",
|
||||
"name": "声现象",
|
||||
"nodeType": "ROOT",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian2_Phonics",
|
||||
"label": "行为",
|
||||
"leadSentence": "",
|
||||
"name": "产生",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "原因",
|
||||
"value": "声源的振动"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian3_Phonics",
|
||||
"label": "行为",
|
||||
"leadSentence": "",
|
||||
"name": "传播",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "条件",
|
||||
"value": "需要介质"
|
||||
},
|
||||
{
|
||||
"name": "形式",
|
||||
"value": "声波"
|
||||
},
|
||||
{
|
||||
"name": "速度",
|
||||
"value": "v固>v液>v气;15℃空气中传播速度为340m/s"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian4_Phonics",
|
||||
"label": "属性",
|
||||
"leadSentence": "相关的概念有下面这些,请输入对应选项查看详情",
|
||||
"name": "特性",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian5_Phonics",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "音调",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "表示声音的高低"
|
||||
},
|
||||
{
|
||||
"name": "影响因素",
|
||||
"value": "发生物体振动的频率"
|
||||
},
|
||||
{
|
||||
"name": "分类",
|
||||
"value": "超声波、声音、次声波"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian6_Phonics",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "响度",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "人耳感受到的声音强弱"
|
||||
},
|
||||
{
|
||||
"name": "影响因素",
|
||||
"value": "发声体的振幅、距离发声体的远近"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian7_Phonics",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "音色",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "含义",
|
||||
"value": "每个物体发出的声音特有的品质"
|
||||
},
|
||||
{
|
||||
"name": "影响因素",
|
||||
"value": "发声体材料、结构、振动方式"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian8_Phonics",
|
||||
"label": "行为",
|
||||
"leadSentence": "相关的概念有下面这些,请输入对应选项查看详情",
|
||||
"name": "声的利用",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian9_Phonics",
|
||||
"label": "行为",
|
||||
"leadSentence": "",
|
||||
"name": "传递信息",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "内容",
|
||||
"value": "回声定位、声呐、B超等"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian10_Phonics",
|
||||
"label": "行为",
|
||||
"leadSentence": "",
|
||||
"name": "传递能量",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "内容",
|
||||
"value": "超声波碎石、超声波清洗机器等"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian11_Phonics",
|
||||
"label": "属性",
|
||||
"leadSentence": "相关的概念有下面这些,请输入对应选项查看详情",
|
||||
"name": "类别",
|
||||
"nodeType": "MIDDLE",
|
||||
"properties": [],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian12_Phonics",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "乐音",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "物理角度定义",
|
||||
"value": "指发生物体有规律振动产生的声音"
|
||||
},
|
||||
{
|
||||
"name": "环境角度定义",
|
||||
"value": "指悦耳动听、令人愉悦的声音"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "entity_gainian13_Phonics",
|
||||
"label": "概念",
|
||||
"leadSentence": "",
|
||||
"name": "噪声",
|
||||
"nodeType": "LEAF",
|
||||
"properties": [
|
||||
{
|
||||
"name": "物理角度定义",
|
||||
"value": "发声体做无规则的振动时发出的声音"
|
||||
},
|
||||
{
|
||||
"name": "环境角度定义",
|
||||
"value": "凡是妨碍人正常休息,学习和工作的声音,以及对人民要听的声音起干扰作用的声音都属于噪声"
|
||||
},
|
||||
{
|
||||
"name": "等级",
|
||||
"value": "用分贝表示dB"
|
||||
},
|
||||
{
|
||||
"name": "危害",
|
||||
"value": "影响注意力甚至是身体健康"
|
||||
},
|
||||
{
|
||||
"name": "噪声控制途径",
|
||||
"value": "1.声源处减弱 2.传播过程中减弱 3.人耳出减弱"
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
"Phonics"
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,53 @@
|
|||
MotionAndPower 力 力 NodeName
|
||||
MotionAndPower 速度 速度 NodeName
|
||||
MotionAndPower 重力 重力 NodeName
|
||||
MotionAndPower 匀速直线运动 匀速直线运动 NodeName
|
||||
MotionAndPower 时间 时间 NodeName
|
||||
MotionAndPower 摩擦力 摩擦力 NodeName
|
||||
MotionAndPower 弹力 弹力 NodeName
|
||||
MotionAndPower 曲线运动 曲线运动 NodeName
|
||||
MotionAndPower 惯性 惯性 NodeName
|
||||
MotionAndPower 弹簧伸长与压缩时的力,压力、支持力、绳子拉力等 弹簧伸长与压缩时的力,压力、支持力、绳子拉力等 NodeName
|
||||
MotionAndPower 机械运动 机械运动 NodeName
|
||||
MotionAndPower 描述运动位置 描述运动位置 NodeName
|
||||
MotionAndPower 二力平衡 二力平衡 NodeName
|
||||
MotionAndPower 直线运动 直线运动 NodeName
|
||||
MotionAndPower 同一直线上二力的合成 同一直线上二力的合成 NodeName
|
||||
MotionAndPower 弹簧测力计 弹簧测力计 NodeName
|
||||
MotionAndPower 弹性形变 弹性形变 NodeName
|
||||
MotionAndPower 描述运动快慢 描述运动快慢 NodeName
|
||||
MotionAndPower 运动和力 运动和力 NodeName
|
||||
MotionAndPower 参照物 参照物 NodeName
|
||||
MotionAndPower 牛顿第一定律 牛顿第一定律 NodeName
|
||||
MotionAndPower 长度 长度 NodeName
|
||||
MotionAndPower 变速直线运动 变速直线运动 NodeName
|
||||
MotionAndPower 构造 构造 PropertyName
|
||||
MotionAndPower 测量工具 测量工具 PropertyName
|
||||
MotionAndPower 使用 使用 PropertyName
|
||||
MotionAndPower 作用效果 作用效果 PropertyName
|
||||
MotionAndPower 方向 方向 PropertyName
|
||||
MotionAndPower 特点 特点 PropertyName
|
||||
MotionAndPower 作用点 作用点 PropertyName
|
||||
MotionAndPower 原理 原理 PropertyName
|
||||
MotionAndPower 条件 条件 PropertyName
|
||||
MotionAndPower 关系 关系 PropertyName
|
||||
MotionAndPower 单位 单位 PropertyName
|
||||
MotionAndPower 物理意义 物理意义 PropertyName
|
||||
MotionAndPower 产生条件 产生条件 PropertyName
|
||||
MotionAndPower 相对性 相对性 PropertyName
|
||||
MotionAndPower 选择原则 选择原则 PropertyName
|
||||
MotionAndPower 含义 含义 PropertyName
|
||||
MotionAndPower 影响滑动摩擦力因素 影响滑动摩擦力因素 PropertyName
|
||||
MotionAndPower 大小 大小 PropertyName
|
||||
MotionAndPower 估测 估测 PropertyName
|
||||
MotionAndPower 分类 分类 PropertyName
|
||||
MotionAndPower 包括 包括 PropertyName
|
||||
MotionAndPower 公式 公式 PropertyName
|
||||
MotionAndPower 三种比较方法 三种比较方法 PropertyName
|
||||
MotionAndPower 三要素 三要素 PropertyName
|
||||
MotionAndPower 产生 产生 RelationType
|
||||
MotionAndPower 属于 属于 RelationType
|
||||
MotionAndPower 相关物理量有 相关物理量有 RelationType
|
||||
MotionAndPower 判断标准 判断标准 RelationType
|
||||
MotionAndPower 测量工具为 测量工具为 RelationType
|
||||
MotionAndPower 包含 包含 RelationType
|
|
|
@ -0,0 +1,27 @@
|
|||
Phonics 音调 音调 NodeName
|
||||
Phonics 音色 音色 NodeName
|
||||
Phonics 传递信息 传递信息 NodeName
|
||||
Phonics 产生 产生 NodeName
|
||||
Phonics 传递能量 传递能量 NodeName
|
||||
Phonics 乐音 乐音 NodeName
|
||||
Phonics 噪声 噪声 NodeName
|
||||
Phonics 类别 类别 NodeName
|
||||
Phonics 声的利用 声的利用 NodeName
|
||||
Phonics 传播 传播 NodeName
|
||||
Phonics 声现象 声现象 NodeName
|
||||
Phonics 特性 特性 NodeName
|
||||
Phonics 响度 响度 NodeName
|
||||
Phonics 影响因素 影响因素 PropertyName
|
||||
Phonics 条件 条件 PropertyName
|
||||
Phonics 危害 危害 PropertyName
|
||||
Phonics 噪声控制途径 噪声控制途径 PropertyName
|
||||
Phonics 速度 速度 PropertyName
|
||||
Phonics 原因 原因 PropertyName
|
||||
Phonics 内容 内容 PropertyName
|
||||
Phonics 物理角度定义 物理角度定义 PropertyName
|
||||
Phonics 等级 等级 PropertyName
|
||||
Phonics 分类 分类 PropertyName
|
||||
Phonics 环境角度定义 环境角度定义 PropertyName
|
||||
Phonics 形式 形式 PropertyName
|
||||
Phonics 含义 含义 PropertyName
|
||||
Phonics 包含 包含 RelationType
|
|
|
@ -0,0 +1 @@
|
|||
MotionAndPower POSITIVE 力|速度|重力|匀速直线运动|时间|摩擦力|弹力|曲线运动|惯性|弹簧伸长与压缩时的力,压力、支持力、绳子拉力等|机械运动|描述运动位置|二力平衡|直线运动|同一直线上二力的合成|弹簧测力计|弹性形变|描述运动快慢|运动和力|参照物|牛顿第一定律|长度|变速直线运动
|
|
|
@ -0,0 +1 @@
|
|||
Phonics POSITIVE 音调|音色|传递信息|产生|传递能量|乐音|噪声|类别|声的利用|传播|声现象|特性|响度
|
|
|
@ -0,0 +1,49 @@
|
|||
[
|
||||
{
|
||||
"labelsOfVertexes": [
|
||||
{
|
||||
"color": "#E83344",
|
||||
"itemLabel": "物体"
|
||||
},
|
||||
{
|
||||
"color": "#F5A100",
|
||||
"itemLabel": "关联"
|
||||
},
|
||||
{
|
||||
"color": "#9DE7B7",
|
||||
"itemLabel": "概念"
|
||||
},
|
||||
{
|
||||
"color": "#009DDC",
|
||||
"itemLabel": "规律"
|
||||
}
|
||||
],
|
||||
"relationTypesOfEdges": [
|
||||
{
|
||||
"color": "#E83344",
|
||||
"itemLabel": "产生"
|
||||
},
|
||||
{
|
||||
"color": "#F5A100",
|
||||
"itemLabel": "属于"
|
||||
},
|
||||
{
|
||||
"color": "#9DE7B7",
|
||||
"itemLabel": "相关物理量有"
|
||||
},
|
||||
{
|
||||
"color": "#009DDC",
|
||||
"itemLabel": "判断标准"
|
||||
},
|
||||
{
|
||||
"color": "#FD9F7F",
|
||||
"itemLabel": "测量工具为"
|
||||
},
|
||||
{
|
||||
"color": "#025CEA",
|
||||
"itemLabel": "包含"
|
||||
}
|
||||
],
|
||||
"scenario": "MotionAndPower"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
[
|
||||
{
|
||||
"labelsOfVertexes": [
|
||||
{
|
||||
"color": "#E83344",
|
||||
"itemLabel": "行为"
|
||||
},
|
||||
{
|
||||
"color": "#F5A100",
|
||||
"itemLabel": "概念"
|
||||
},
|
||||
{
|
||||
"color": "#9DE7B7",
|
||||
"itemLabel": "属性"
|
||||
}
|
||||
],
|
||||
"relationTypesOfEdges": [
|
||||
{
|
||||
"color": "#E83344",
|
||||
"itemLabel": "包含"
|
||||
}
|
||||
],
|
||||
"scenario": "Phonics"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
red #E83344
|
||||
lightred #FD9F7F
|
||||
pink #FF4C94
|
||||
orange #F5A100
|
||||
yellow #E5E516
|
||||
lightyellow #FFFF70
|
||||
green #00D86C
|
||||
lightgreen #9DE7B7
|
||||
icegreen #7FFFBF
|
||||
blue #009DDC
|
||||
iceblue #7BCDFF
|
||||
bluepurple #025CEA
|
||||
purple #9257ae
|
||||
lightpurple #78A7FF
|
||||
icepurple #D89ADA
|
||||
lightgrey #EAEAEA
|
||||
lightblack #333333
|
||||
grey #808080
|
|
|
@ -0,0 +1,20 @@
|
|||
和尚 grey
|
||||
妖怪 red
|
||||
妖怪_活 pink
|
||||
妖怪_死 red
|
||||
神仙 blue
|
||||
神仙_佛派 lightgreen
|
||||
神仙_道派 blue
|
||||
凡人 yellow
|
||||
团体 orange
|
||||
团体_妖怪 orange
|
||||
上下级 blue
|
||||
父子 blue
|
||||
父女 blue
|
||||
母子 blue
|
||||
母女 blue
|
||||
兄弟 lightblue
|
||||
夫妻 green
|
||||
兄弟 green
|
||||
亲戚 lightgreen
|
||||
组成 lightred
|
|
Binary file not shown.
|
@ -0,0 +1,19 @@
|
|||
# cpic-portal
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "cpic-portal",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"core-js": "^3.6.4",
|
||||
"element-ui": "^2.13.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.1.5",
|
||||
"vuex": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.2.0",
|
||||
"@vue/cli-plugin-router": "^4.2.0",
|
||||
"@vue/cli-plugin-vuex": "^4.2.0",
|
||||
"@vue/cli-service": "^4.2.0",
|
||||
"axios": "^0.19.2",
|
||||
"echarts": "^4.6.0",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
var urlapi = "http://localhost:5000"
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT license.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="SHORTCUT ICON" href="https://c.s-microsoft.com/favicon.ico?v2" type="image/x-icon" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
||||
<title>知识图谱</title>
|
||||
<script src="config.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Handle History Mode and custom 404/500" stopProcessing="true">
|
||||
<match url="(.*)" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="/" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
</configuration>
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/*
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
*/
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
#nav {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
#nav a {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
#nav a.router-link-exact-active {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
Binary file not shown.
After Width: | Height: | Size: 1000 B |
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
*/
|
||||
.main {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.chart-page {
|
||||
height: 100%;
|
||||
background: #f3f3f3;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chart-wrap {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
background: none;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.chart-result {
|
||||
margin-top: 45px;
|
||||
background: #ffffff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 3px #d8d8d8;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.chart-result .item-list.close {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.expand {
|
||||
max-height: 250px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.chart-result .title {
|
||||
background: #fefaf1;
|
||||
padding: 5px 10px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.chart-result .item-list {
|
||||
margin-top: 10px;
|
||||
list-style: none;
|
||||
background: #f6f6f6;
|
||||
padding: 0 10px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.chart-result .item-list li {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chart-result .result-num {
|
||||
padding: 0 5px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.chart-result .item-list li {
|
||||
line-height: 200%;
|
||||
}
|
||||
|
||||
.control {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 200%;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
background-size: 20px 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
position: relative;
|
||||
top: 5px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.down {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.up {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.chart-search {
|
||||
height: 100px;
|
||||
position: relative;
|
||||
width: 400px;
|
||||
/* background: #ffffff; */
|
||||
border-radius: 5px;
|
||||
/* box-shadow: 0 2px 3px #d8d8d8; */
|
||||
}
|
||||
|
||||
.chart-search-text {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 20px;
|
||||
line-height: 40px;
|
||||
font-size: 15px;
|
||||
color: #025cea;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.chart-search-div {
|
||||
position: absolute;
|
||||
top: 96px;
|
||||
left: 0;
|
||||
line-height: 25px;
|
||||
width: 300px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #025cea;
|
||||
background: #ffffff;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.chart-search-div input {
|
||||
width: 100%;
|
||||
height: 25px;
|
||||
text-indent: 10px;
|
||||
border: 0;
|
||||
background: none;
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.chart-search-div .chart-search-btn {
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
top: 0;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
text-align: center;
|
||||
background: #025cea;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
background-size: 25px 25px;
|
||||
background-position: center center;
|
||||
outline: none;
|
||||
background-image: url("../assets/zoom.png");
|
||||
}
|
||||
|
||||
#echart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.list-item {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
#tip button {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: none;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
.bot {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.bot-info-wrap {
|
||||
position: relative;
|
||||
margin: 10px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.bot-icon {
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.bot-info {
|
||||
line-height: 180%;
|
||||
max-width: 60%;
|
||||
background: #f3f3f3;
|
||||
border: 1px solid #ccc;
|
||||
margin-left: 30px;
|
||||
display: inline-block;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.user-info-wrap {
|
||||
position: relative;
|
||||
margin: 10px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.user-icon {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
margin-right: 30px;
|
||||
line-height: 180%;
|
||||
max-width: 60%;
|
||||
background: #f3f3f3;
|
||||
border: 1px solid #ccc;
|
||||
padding: 0 5px;
|
||||
float: right;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #0084FB;
|
||||
}
|
||||
|
||||
.bot-wrap {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f8f8f8;
|
||||
z-index: 11;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.bot {
|
||||
width: 400px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bot .left {
|
||||
width: 70%;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bot .chat {
|
||||
border: 1px solid #ccc;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
height: 523px;
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bot .chat .send {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.bot .chat .send .chat-input {
|
||||
border: 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.bot .chat .send input {
|
||||
height: 30px;
|
||||
border: 0;
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
margin: 3px;
|
||||
flex-grow: 1;
|
||||
padding-right: 30px;
|
||||
padding-left: 5px;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
.bot .chat .send input:focus {
|
||||
border: 1px solid #0084FB;
|
||||
}
|
||||
|
||||
.bot .chat .send input:focus+.btn>i {
|
||||
color: #0084FB;
|
||||
}
|
||||
|
||||
.bot .chat .send .btnsend {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
height: 22px;
|
||||
top: 4px;
|
||||
cursor: pointer;
|
||||
color: #0084FB;
|
||||
font-size: 20px;
|
||||
z-index: 333;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
.bot .chat .send .btn i {
|
||||
font-size: 22px;
|
||||
margin-top: 1px;
|
||||
color: #ccc;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
.history {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
padding: 5px;
|
||||
flex-grow: 1;
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
|
||||
.history::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.history::-webkit-scrollbar-track {
|
||||
border-radius: 5px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.history::-webkit-scrollbar-thumb {
|
||||
border-radius: 5px;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.chat-title {
|
||||
background: #0084FB;
|
||||
height: 35px;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
box-shadow: 0px 0px 2px #000;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
font-size: 14px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
padding: 2px 10px;
|
||||
min-width: 70px;
|
||||
height: 29px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.bot-title {
|
||||
line-height: 26px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.el-popover.el-popper{
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
|
@ -0,0 +1,279 @@
|
|||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#progress {
|
||||
height: 10px;
|
||||
width: 500px;
|
||||
border: 1px solid gold;
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#progress .progress-item {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: chartreuse;
|
||||
border-radius: 5px;
|
||||
transition: width .3s linear;
|
||||
}
|
||||
|
||||
#upload {
|
||||
position: relative;
|
||||
width: 334px;
|
||||
height: 40px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#upload .upload-spin {
|
||||
position: absolute;
|
||||
left: 370px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
#spin {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#upload .upload-success {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
color: rgb(111, 172, 20);
|
||||
position: absolute;
|
||||
left: 370px;
|
||||
top: 8px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#file {
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
height: 35px;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#filetext {
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
height: 35px;
|
||||
text-indent: 10px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 50%;
|
||||
margin: 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
box-shadow: 1px 1px 1px #ccc;
|
||||
margin-top: 30px;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#uploadfile {
|
||||
position: absolute;
|
||||
left: 270px;
|
||||
top: 2px;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
height: 35px;
|
||||
border-radius: 3px;
|
||||
padding: 0 20px;
|
||||
border: 1px solid #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#uploadfile:hover {
|
||||
background-color: #66b1ff;
|
||||
}
|
||||
|
||||
.title {
|
||||
line-height: 300%;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
padding-left: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#log {
|
||||
margin-top: 20px;
|
||||
color: #666;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#log p {
|
||||
color: #666;
|
||||
line-height: 200%;
|
||||
width: 400px;
|
||||
text-align: left;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#download {
|
||||
text-align: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
#downloadbtn {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
height: 35px;
|
||||
border-radius: 3px;
|
||||
padding: 0 20px;
|
||||
border: 1px solid #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#downloadbtn:hover {
|
||||
background-color: #66b1ff;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
position: relative;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 15px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 15px;
|
||||
text-align: right;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: block;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.layui-table tr th {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
border: 1px solid #ccc;
|
||||
line-height: 200%;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.layui-table tr td {
|
||||
font-size: 16px;
|
||||
border: 1px solid #ccc;
|
||||
line-height: 200%;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-spin img {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.list li {
|
||||
line-height: 200%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.file {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.add-btn.el-icon-circle-plus-outline {
|
||||
font-size: 20px;
|
||||
display: block;
|
||||
text-align: left;
|
||||
margin-top: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.color-p{
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.color-item1{
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
line-height: 180%;
|
||||
}
|
||||
|
||||
.color-item2{
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
line-height: 180%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.color-item2 input{
|
||||
background-color: #FFF;
|
||||
background-image: none;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #DCDFE6;
|
||||
box-sizing: border-box;
|
||||
color: #606266;
|
||||
display: inline-block;
|
||||
font-size: inherit;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
outline: 0;
|
||||
padding: 0 15px;
|
||||
transition: border-color .2s cubic-bezier(.645,.045,.355,1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.color-block{
|
||||
display: inline-block;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
background: #409eff;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.other-color{
|
||||
margin-top: 20px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.other-color .other-color-item{
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.other-color .other-color-item .color-block{
|
||||
top: 1px;
|
||||
left: 85px;
|
||||
}
|
||||
|
||||
.error-info{
|
||||
position:absolute;
|
||||
right: -65px;
|
||||
color: red;
|
||||
font-size: 12px;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import ElementUI from 'element-ui';
|
||||
import 'element-ui/lib/theme-chalk/index.css';
|
||||
import "babel-polyfill";
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.use(ElementUI);
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from '../views/Home.vue'
|
||||
import Upload from '../views/Upload.vue'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/upload',
|
||||
name: 'Upload',
|
||||
component: () => import('../views/Upload.vue')
|
||||
},
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
|
@ -0,0 +1,15 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
},
|
||||
mutations: {
|
||||
},
|
||||
actions: {
|
||||
},
|
||||
modules: {
|
||||
}
|
||||
})
|
|
@ -0,0 +1,544 @@
|
|||
<template>
|
||||
<div class="main">
|
||||
<div class="chart-page">
|
||||
<div id="echart" width="400" height="400"></div>
|
||||
<div id="tip">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="400"
|
||||
trigger="click"
|
||||
style="padding: 0 !important"
|
||||
>
|
||||
<div class="bot">
|
||||
<div class="chat">
|
||||
<div class="chat-title">
|
||||
<span class="bot-title">SmartKG bot</span>
|
||||
</div>
|
||||
<div class="history" id="history">
|
||||
<div v-for="item of histroyList" v-bind:key="item.key">
|
||||
<div v-if="item.from == 'user'" class="user-info-wrap">
|
||||
<div class="user-info">{{ item.info }}</div>
|
||||
<i class="el-icon-user-solid user-icon"></i>
|
||||
</div>
|
||||
<div v-if="item.from == 'bot'" class="bot-info-wrap">
|
||||
<i class="el-icon-service bot-icon"></i>
|
||||
<div class="bot-info">
|
||||
<pre>{{ item.info }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="send">
|
||||
<div class="chat-input">
|
||||
<input
|
||||
v-model="currentText"
|
||||
type="text"
|
||||
id="curentChat"
|
||||
style="border-radius: 5px"
|
||||
v-on:keyup.enter="send"
|
||||
/>
|
||||
<div class="btnsend" @click="send()" title="send">
|
||||
<i class="el-icon-chat-round"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button slot="reference">
|
||||
<i class="el-icon-service" style="font-size: 30px"></i>
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="chart-wrap">
|
||||
<div class="chart-search">
|
||||
<div class="chart-search-div">
|
||||
<input
|
||||
class="chart-search-input"
|
||||
type="text"
|
||||
:placeholder="
|
||||
selectSce == '' ? '请先选择数据库和场景' : '请输入实体名称'
|
||||
"
|
||||
v-model="keyWord"
|
||||
v-on:input="gotochart"
|
||||
v-on:keyup.enter="gotochartEnter"
|
||||
ref="search"
|
||||
:disabled="selectSce == ''"
|
||||
/>
|
||||
<button
|
||||
class="chart-search-btn"
|
||||
@click="gotochartSmallBtn()"
|
||||
></button>
|
||||
</div>
|
||||
<el-select
|
||||
v-model="selectDataStore"
|
||||
placeholder="请选择数据库"
|
||||
style="left: -88px; width: 222px; margin-bottom: 10px"
|
||||
:change="changeDataStore()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in datastoreList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="selectSce"
|
||||
placeholder="请选择场景"
|
||||
style="left: -88px; width: 222px"
|
||||
:change="getScenColor()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in scenariosList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-button
|
||||
@click="changeScen()"
|
||||
style="left: 236px; top: 50px; position: absolute"
|
||||
>展示</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="chart-result">
|
||||
<p class="title" v-if="isExpand">
|
||||
模糊搜索结果信息:共找到
|
||||
<span class="result-num">{{ list.length }}</span
|
||||
>结果
|
||||
</p>
|
||||
<ul class="item-list" :class="{ close: !isExpand, expand: isExpand }">
|
||||
<li
|
||||
class="list-item"
|
||||
style="justify-content: left"
|
||||
v-for="item of list"
|
||||
v-bind:key="item.id"
|
||||
:class="{ active: item.id == currentId }"
|
||||
@click="getNodes(item.id, item.name)"
|
||||
v-html="changeListKey(item.name)"
|
||||
></li>
|
||||
</ul>
|
||||
<hr v-if="isExpand" />
|
||||
<div class="control">
|
||||
<span class="control-btn" @click="isExpand = !isExpand">
|
||||
全部收起
|
||||
<span
|
||||
class="arrow"
|
||||
:class="{ up: isExpand, down: !isExpand }"
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style type="text/css" scoped>
|
||||
@import "../assets/home.css";
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
import axios from "axios";
|
||||
import echarts from "echarts";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
data() {
|
||||
return {
|
||||
keyWord: "",
|
||||
hotkeyList: [],
|
||||
isExpand: true,
|
||||
list: [],
|
||||
nodes: [],
|
||||
edges: [],
|
||||
sendTime: new Date().getTime(),
|
||||
timer: null,
|
||||
charts: null,
|
||||
currentId: "",
|
||||
baseURL: window.urlapi,
|
||||
scenariosList: [],
|
||||
datastoreList: [],
|
||||
colorList: [],
|
||||
selectSce: "",
|
||||
lastScen: "",
|
||||
selectDataStore: "",
|
||||
lastDataStore: "",
|
||||
histroyList: [],
|
||||
currentText: "",
|
||||
sessionId: "",
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
methods: {
|
||||
send() {
|
||||
if (this.currentText.trim() == "") {
|
||||
return;
|
||||
}
|
||||
axios
|
||||
.post(`${this.baseURL}/api/bot`, {
|
||||
userId: "",
|
||||
sessionId: this.sessionId,
|
||||
datastoreName: this.selectDataStore,
|
||||
query: this.currentText,
|
||||
})
|
||||
.then((res) => {
|
||||
this.sessionId = res.data.sessionId;
|
||||
this.histroyList.push({
|
||||
from: "bot",
|
||||
info: res.data.result.responseMessage,
|
||||
key: new Date().valueOf(),
|
||||
});
|
||||
setTimeout(() => {
|
||||
document.querySelector("#history").scrollTop = 99999;
|
||||
}, 150);
|
||||
});
|
||||
this.histroyList.push({
|
||||
from: "user",
|
||||
info: this.currentText,
|
||||
key: new Date().valueOf(),
|
||||
});
|
||||
this.currentText = "";
|
||||
setTimeout(() => {
|
||||
document.querySelector("#history").scrollTop = 99999;
|
||||
}, 150);
|
||||
},
|
||||
getScenColor() {
|
||||
if (this.selectSce == "" || this.selectSce == this.lastScen) {
|
||||
return;
|
||||
}
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Config/entitycolor?datastoreName=${encodeURI(
|
||||
this.selectDataStore
|
||||
)}&scenarioName=${encodeURI(this.selectSce)}`
|
||||
)
|
||||
.then((response) => {
|
||||
for (let [key, value] of Object.entries(
|
||||
response.data.entityColorConfig
|
||||
)) {
|
||||
this.colorList.push({ name: key, color: value });
|
||||
}
|
||||
});
|
||||
},
|
||||
changeScen() {
|
||||
if (this.selectSce == "" || this.selectSce == this.lastScen) {
|
||||
return;
|
||||
}
|
||||
this.lastScen = this.selectSce;
|
||||
// axios
|
||||
// .get(
|
||||
// `${this.baseURL}/api/Graph/visulize?datastoreName=${encodeURI(
|
||||
// this.selectDataStore
|
||||
// )}&scenarioName=${encodeURI(this.selectSce)}`
|
||||
// )
|
||||
// .then((res) => {
|
||||
// this.nodes = res.data.nodes;
|
||||
// this.edges = res.data.relations;
|
||||
// this.process();
|
||||
// this.generate();
|
||||
// });
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Graph/visulize?datastoreName=${encodeURI(
|
||||
this.selectDataStore
|
||||
)}&scenarioName=${encodeURI(this.selectSce)}`
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.data.success == false) {
|
||||
alert(res.data.responseMessage);
|
||||
} else {
|
||||
this.nodes = res.data.nodes;
|
||||
this.edges = res.data.relations;
|
||||
this.process();
|
||||
this.generate();
|
||||
}
|
||||
});
|
||||
},
|
||||
changeDataStore() {
|
||||
if (
|
||||
this.selectDataStore == "" ||
|
||||
this.selectDataStore == this.lastDataStore
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.lastDataStore = this.selectDataStore;
|
||||
this.getScenarios();
|
||||
this.keyWord = "";
|
||||
this.lastScen = "";
|
||||
this.selectSce = "";
|
||||
},
|
||||
gotochartEnter() {
|
||||
axios
|
||||
.get(`${this.baseURL}/api/Search?keyword=${encodeURI(this.keyWord)}`)
|
||||
.then((response) => {
|
||||
this.currentId = response.data.nodes[0].id;
|
||||
axios
|
||||
.get(`${this.baseURL}/api/Search/${response.data.nodes[0].id}`)
|
||||
.then((res) => {
|
||||
this.nodes = res.data.nodes;
|
||||
this.edges = res.data.relations;
|
||||
this.process();
|
||||
this.generate();
|
||||
});
|
||||
});
|
||||
},
|
||||
changeListKey(item) {
|
||||
return item.replace(
|
||||
new RegExp(this.keyWord, "g"),
|
||||
`<span style='color:red'>${this.keyWord}</span>`
|
||||
);
|
||||
},
|
||||
gotochartSmallBtn() {
|
||||
this.gotochartEnter();
|
||||
this.gotochart();
|
||||
},
|
||||
gotochart() {
|
||||
if (this.keyWord != "") {
|
||||
setTimeout(() => {
|
||||
this.$refs.search.focus();
|
||||
this.$refs.search.selectionStart = 100;
|
||||
this.$refs.search.selectionEnd = 100;
|
||||
}, 10);
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
let now = new Date().getTime();
|
||||
if (now - this.sendTime < 600 || this.keyWord == "") {
|
||||
clearTimeout(this.timer);
|
||||
return;
|
||||
}
|
||||
this.sendTime = new Date().getTime();
|
||||
if (this.keyWord == "") {
|
||||
return;
|
||||
}
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Graph/search?datastoreName=${this.selectDataStore}&keyword=${this.keyWord}&scenarioName=${this.selectSce}`
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.data.nodes === null) {
|
||||
this.list = [];
|
||||
this.charts.dispose();
|
||||
this.charts.hideLoading();
|
||||
} else {
|
||||
this.list = response.data.nodes;
|
||||
}
|
||||
});
|
||||
}, 2000);
|
||||
},
|
||||
getNodes(id, name) {
|
||||
// this.lastScen = "";
|
||||
// this.selectSce = "";
|
||||
this.currentId = id;
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Graph/relations/${id}?datastoreName=${this.selectDataStore}`
|
||||
)
|
||||
.then((res) => {
|
||||
this.nodes = res.data.nodes;
|
||||
this.edges = res.data.relations;
|
||||
this.process();
|
||||
this.generate();
|
||||
this.charts.hideLoading();
|
||||
});
|
||||
},
|
||||
generate() {
|
||||
this.charts = echarts.init(document.getElementById("echart"));
|
||||
var option = {
|
||||
title: {
|
||||
top: "bottom",
|
||||
left: "right",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: (params, ticket) => {
|
||||
if (params.data.fullname == undefined) {
|
||||
return;
|
||||
}
|
||||
let str = "";
|
||||
for (let count = 0; count < params.data.fullname.length; count++) {
|
||||
str += params.data.fullname[count];
|
||||
if (count % 20 == 0 && count != 0) {
|
||||
str += "<br/>";
|
||||
}
|
||||
}
|
||||
return str;
|
||||
},
|
||||
textStyle: {
|
||||
width: "100px",
|
||||
},
|
||||
extraCssText: "text-align:left;",
|
||||
},
|
||||
draggable: true,
|
||||
series: [
|
||||
{
|
||||
nodeScaleRatio: 0,
|
||||
zoom: 1,
|
||||
animation: false,
|
||||
name: "Les Miserables",
|
||||
type: "graph",
|
||||
edgeSymbol: ["", "arrow"],
|
||||
focusNodeAdjacency: true,
|
||||
layout: "force",
|
||||
force: {
|
||||
initLayout: false,
|
||||
layoutAnimation: false,
|
||||
repulsion: 300,
|
||||
edgeLength: 140,
|
||||
gravity: 0.1,
|
||||
},
|
||||
edgeLabel: {
|
||||
show: true,
|
||||
},
|
||||
data: this.nodes,
|
||||
links: this.edges,
|
||||
roam: true,
|
||||
label: {
|
||||
color: "#000",
|
||||
normal: {
|
||||
position: "right",
|
||||
},
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
curveness: 0.2,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
this.charts.setOption(option);
|
||||
if (this.charts) {
|
||||
this.charts.off("click");
|
||||
}
|
||||
this.charts.on("click", (e) => {
|
||||
this.charts = echarts.init(document.getElementById("echart"));
|
||||
this.charts.showLoading({
|
||||
text: "正在加载数据",
|
||||
color: "none",
|
||||
});
|
||||
this.getChildNode(e.data).then(() => {
|
||||
this.process();
|
||||
option.series[0].data = this.nodes;
|
||||
option.series[0].links = this.edges;
|
||||
this.charts.setOption(option);
|
||||
this.charts.resize({
|
||||
width: "auto",
|
||||
});
|
||||
this.charts.hideLoading();
|
||||
});
|
||||
});
|
||||
},
|
||||
getChildNode(node) {
|
||||
let url = "";
|
||||
if (/属性/.test(node.info)) {
|
||||
url = `${this.baseURL}/api/Graph/Search/property?name=${encodeURI(
|
||||
node.displayName
|
||||
)}&value=${encodeURI(node.name)}&datastoreName=${this.selectDataStore}`;
|
||||
} else {
|
||||
url = `${this.baseURL}/api/Graph/relations/${node.id}?datastoreName=${this.selectDataStore}`;
|
||||
}
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
axios({
|
||||
method: "get",
|
||||
url,
|
||||
}).then((res) => {
|
||||
this.nodes = res.data.nodes;
|
||||
this.edges = res.data.relations;
|
||||
this.process();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
process() {
|
||||
for (let i = 0; i < this.nodes.length; i++) {
|
||||
this.nodes[i].draggable = false;
|
||||
if (this.nodes[i].name.length > 7) {
|
||||
if (!this.nodes[i].fullname) {
|
||||
this.nodes[i].fullname = this.nodes[i].name;
|
||||
this.nodes[i].name = this.nodes[i].name.substring(0, 6) + "...";
|
||||
}
|
||||
}
|
||||
if (this.nodes[i].info == undefined) {
|
||||
this.nodes[i].info = this.nodes[i].label;
|
||||
}
|
||||
this.nodes[i].label = {
|
||||
show: true,
|
||||
position: "bottom",
|
||||
width: "30",
|
||||
color: "#000",
|
||||
};
|
||||
this.nodes[i].symbolSize = 30;
|
||||
if (this.nodes[i].name == "true") {
|
||||
this.nodes[i].symbolSize = 10;
|
||||
this.nodes[i].label = { show: false };
|
||||
}
|
||||
this.nodes[i].itemStyle = {
|
||||
color: "#cccccc",
|
||||
borderColor: "#cccccc",
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)",
|
||||
shadowBlur: 3,
|
||||
};
|
||||
for (let k = 0; k < this.colorList.length; k++) {
|
||||
if (this.nodes[i].info == this.colorList[k].name) {
|
||||
this.nodes[i].itemStyle = {
|
||||
color: this.colorList[k].color,
|
||||
borderColor: "#ffffff",
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)",
|
||||
shadowBlur: 3,
|
||||
};
|
||||
this.nodes[i].label.color = this.colorList[k].color;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this.edges.length; i++) {
|
||||
this.edges[i].source = this.edges[i].sourceId;
|
||||
this.edges[i].target = this.edges[i].targetId;
|
||||
for (let j = 0; j < this.nodes.length; j++) {
|
||||
if (this.edges[i].target == this.nodes[j].id)
|
||||
this.edges[i].lineStyle = {
|
||||
width: 2,
|
||||
color: "#000000",
|
||||
};
|
||||
}
|
||||
this.edges[i].label = {
|
||||
formatter: this.edges[i].value,
|
||||
};
|
||||
}
|
||||
},
|
||||
getScenarios() {
|
||||
this.scenariosList = [];
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Graph/scenarios?datastoreName=${this.selectDataStore}`
|
||||
)
|
||||
.then((response) => {
|
||||
for (let i = 0; i < response.data.scenarioNames.length; i++) {
|
||||
this.scenariosList.push({
|
||||
id: i,
|
||||
name: response.data.scenarioNames[i],
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getDataStore() {
|
||||
this.datastoreList = [];
|
||||
axios.get(`${this.baseURL}/api/DataStoreMgmt`).then((response) => {
|
||||
for (let i = 0; i < response.data.datastoreNames.length; i++) {
|
||||
this.datastoreList.push({
|
||||
id: i,
|
||||
name: response.data.datastoreNames[i],
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getDataStore();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,471 @@
|
|||
<template>
|
||||
<div class="main">
|
||||
<div class="container">
|
||||
<p class="title">请您选择数据仓库</p>
|
||||
<div id="download">
|
||||
<div class="list">
|
||||
<!-- <div v-for="item of dataStores" v-bind:key="item.key">
|
||||
<div class="list-item">
|
||||
<el-radio
|
||||
v-model="radio"
|
||||
:label="item.name"
|
||||
border
|
||||
style="margin-bottom: 10px"
|
||||
>
|
||||
{{ item.name }}
|
||||
<i
|
||||
class="el-icon-s-flag"
|
||||
v-if="item.name == defaultDataStore"
|
||||
></i>
|
||||
</el-radio>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="openUploadwin(item.name)"
|
||||
style="height: 40px"
|
||||
>上传数据</el-button
|
||||
>
|
||||
</div>
|
||||
</div> -->
|
||||
<el-select
|
||||
v-model="radio"
|
||||
placeholder="请选择数据库"
|
||||
:change="getDataStore()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in dataStores"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button type="primary" @click="dialogCreateVisible = true"
|
||||
>新建数据仓库</el-button
|
||||
>
|
||||
<el-button type="primary" @click="openDel()">删除仓库</el-button>
|
||||
<el-button type="primary" @click="openUploadwin(radio)"
|
||||
>上传数据</el-button
|
||||
>
|
||||
<el-button type="primary" @click="reloadData()">加载数据</el-button>
|
||||
<el-button type="primary" @click="colorVisible = true"
|
||||
>设置颜色</el-button
|
||||
>
|
||||
<el-button type="primary" @click="download()">下载模板</el-button>
|
||||
<el-dialog
|
||||
title="新建数据库"
|
||||
:visible.sync="dialogCreateVisible"
|
||||
width="30%"
|
||||
>
|
||||
<p>请输入数据仓库的名称</p>
|
||||
<p>
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="请输入仓库名称"
|
||||
style="width: 60%; margin-top: 20px"
|
||||
></el-input>
|
||||
</p>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogCreateVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveDataStore()">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<!-- -->
|
||||
<el-dialog title="设置颜色" :visible.sync="colorVisible" width="40%">
|
||||
<div style="margin-bottom: 20px">
|
||||
<el-select
|
||||
v-model="selectDataStore"
|
||||
placeholder="请选择数据库"
|
||||
:change="changeDataStore()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in dataStores"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="selectSce"
|
||||
placeholder="请选择场景"
|
||||
:change="changeScen()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in scenariosList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<p v-for="item in colorList" :key="item.id" class="color-p">
|
||||
<span class="color-item1">{{ item.name }}</span>
|
||||
<span class="color-item2">
|
||||
<input
|
||||
v-model="item.color"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="请输入颜色数值"
|
||||
class="el-input__inner"
|
||||
/>
|
||||
<span
|
||||
class="color-block"
|
||||
v-bind:style="{ background: item.color }"
|
||||
></span>
|
||||
<span v-if="checkColor(item.color)" class="error-info">
|
||||
格式错误!</span
|
||||
>
|
||||
</span>
|
||||
</p>
|
||||
<div class="other-color">
|
||||
<h5 v-if="otherColorList.length > 0" style="margin-bottom: 10px">
|
||||
其他备选颜色
|
||||
</h5>
|
||||
<span
|
||||
v-for="item in otherColorList"
|
||||
:key="item.id"
|
||||
class="other-color-item"
|
||||
>
|
||||
<span>{{ item.color }}</span>
|
||||
<span
|
||||
class="color-block"
|
||||
v-bind:style="{ background: item.color }"
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="colorVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveColor()">保 存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<!-- -->
|
||||
<el-dialog
|
||||
title="删除数据库"
|
||||
:visible.sync="dialogDelVisible"
|
||||
width="30%"
|
||||
>
|
||||
<p>您确实要删除这个数据仓库吗?</p>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogDelVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="del()">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="上传数据"
|
||||
:visible.sync="dialogUploadVisible"
|
||||
width="30%"
|
||||
>
|
||||
<div
|
||||
class="file-item"
|
||||
v-for="item of uploadFiles"
|
||||
v-bind:key="item.key"
|
||||
>
|
||||
<el-input
|
||||
v-model="item.scenario"
|
||||
size="small"
|
||||
placeholder="请输入场景名称"
|
||||
style="width: 40%; margin-right: 30px"
|
||||
></el-input>
|
||||
<input class="file" type="file" @change="getFile($event, item)" />
|
||||
</div>
|
||||
<div>
|
||||
<i
|
||||
class="add-btn el-icon-circle-plus-outline"
|
||||
@click="addFile()"
|
||||
></i>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogUploadVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="uploadSend()">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style type="text/css" scoped>
|
||||
@import "../assets/upload.css";
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
import axios from "axios";
|
||||
import qs from "qs";
|
||||
|
||||
export default {
|
||||
name: "Upload",
|
||||
data() {
|
||||
return {
|
||||
baseURL: window.urlapi,
|
||||
dataStores: [],
|
||||
dialogCreateVisible: false,
|
||||
dialogDefaultVisible: false,
|
||||
dialogDelVisible: false,
|
||||
dialogUploadVisible: false,
|
||||
colorVisible: false,
|
||||
input: "",
|
||||
radio: "",
|
||||
uploadFiles: [],
|
||||
defaultDataStore: "",
|
||||
selectDataStore: "",
|
||||
lastDataStore: "",
|
||||
scenariosList: [],
|
||||
selectSce: "",
|
||||
colorList: [],
|
||||
otherColorList: [],
|
||||
lastScen: "",
|
||||
lastDataStore: "",
|
||||
selectRadioDataStore: "",
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
methods: {
|
||||
handleClose(done) {
|
||||
this.$confirm("确认关闭?")
|
||||
.then((_) => {
|
||||
done();
|
||||
})
|
||||
.catch((_) => {});
|
||||
},
|
||||
saveDataStore() {
|
||||
axios
|
||||
.post(`${this.baseURL}/api/DataStoreMgmt`, {
|
||||
datastoreName: this.input,
|
||||
})
|
||||
.then((res) => {
|
||||
this.input = "";
|
||||
this.getList();
|
||||
this.dialogCreateVisible = false;
|
||||
});
|
||||
},
|
||||
|
||||
openDel() {
|
||||
if (this.radio == "") {
|
||||
alert("请选择要删除的数据库");
|
||||
return;
|
||||
}
|
||||
this.dialogDelVisible = true;
|
||||
},
|
||||
|
||||
reloadData() {
|
||||
if (this.radio == "") {
|
||||
alert("请选择要加载的数据库");
|
||||
return;
|
||||
}
|
||||
axios
|
||||
.post(
|
||||
`${this.baseURL}/api/DataStoreMgmt/preprocess/reload`,
|
||||
qs.stringify({ DatastoreName: this.radio })
|
||||
)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
},
|
||||
|
||||
changeScen() {
|
||||
if (this.selectSce == "" || this.selectSce == this.lastScen) {
|
||||
return;
|
||||
}
|
||||
this.lastScen = this.selectSce;
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Config/entitycolor?datastoreName=${encodeURI(
|
||||
this.selectDataStore
|
||||
)}&scenarioName=${encodeURI(this.selectSce)}`
|
||||
)
|
||||
.then((response) => {
|
||||
this.colorList = [];
|
||||
for (let [key, value] of Object.entries(
|
||||
response.data.entityColorConfig
|
||||
)) {
|
||||
this.colorList.push({ name: key, color: value });
|
||||
}
|
||||
console.log(this.colorList);
|
||||
axios.get(`${this.baseURL}/api/Config/colors`).then((res) => {
|
||||
this.otherColorList = [];
|
||||
for (let [key, value] of Object.entries(res.data.colors)) {
|
||||
this.otherColorList.push({ name: key, color: value });
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
saveColor() {
|
||||
let str = "";
|
||||
for (let i = 0; i < this.colorList.length; i++) {
|
||||
if (this.checkColor(this.colorList[i].color)) {
|
||||
alert("颜色格式错误");
|
||||
return false;
|
||||
}
|
||||
str +=
|
||||
"&" +
|
||||
encodeURI(this.colorList[i].name) +
|
||||
"=" +
|
||||
encodeURIComponent(this.colorList[i].color);
|
||||
}
|
||||
|
||||
axios
|
||||
.post(
|
||||
`${
|
||||
this.baseURL
|
||||
}/api/Config/entitycolor?user=skuser1&datastoreName=${encodeURI(
|
||||
this.selectDataStore
|
||||
)}&scenarioName=${encodeURI(this.selectSce)}${str}`,
|
||||
{}
|
||||
)
|
||||
.then((res) => {
|
||||
alert("颜色设置保存成功");
|
||||
this.colorVisible = false;
|
||||
this.colorList = [];
|
||||
this.selectDataStore = "";
|
||||
this.selectSce = "";
|
||||
this.otherColorList = [];
|
||||
this.lastScen = "";
|
||||
this.selectSce = "";
|
||||
});
|
||||
},
|
||||
|
||||
checkColor(color) {
|
||||
return /^#([0-9a-fA-F]{6})$/.test(color) ? false : true;
|
||||
},
|
||||
//
|
||||
|
||||
getDataStore() {
|
||||
// this.radio = this.r
|
||||
},
|
||||
changeDataStore() {
|
||||
if (
|
||||
this.selectDataStore == "" ||
|
||||
this.selectDataStore == this.lastDataStore
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.lastDataStore = this.selectDataStore;
|
||||
this.getScenarios();
|
||||
this.lastScen = "";
|
||||
this.selectSce = "";
|
||||
},
|
||||
|
||||
getScenarios() {
|
||||
this.scenariosList = [];
|
||||
axios
|
||||
.get(
|
||||
`${this.baseURL}/api/Graph/scenarios?datastoreName=${this.selectDataStore}`
|
||||
)
|
||||
.then((response) => {
|
||||
for (let i = 0; i < response.data.scenarioNames.length; i++) {
|
||||
this.scenariosList.push({
|
||||
id: i,
|
||||
name: response.data.scenarioNames[i],
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//
|
||||
|
||||
download() {
|
||||
window.location.href = `./SmartKG_KGDesc_Template.xlsx`;
|
||||
},
|
||||
|
||||
getList() {
|
||||
this.dataStores = [];
|
||||
axios.get(`${this.baseURL}/api/DataStoreMgmt`).then((res) => {
|
||||
for (let i = 0; i < res.data.datastoreNames.length; i++) {
|
||||
this.dataStores.push({
|
||||
name: res.data.datastoreNames[i],
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
del() {
|
||||
let config = {
|
||||
headers: {
|
||||
accept: "text/plain",
|
||||
"Content-Type": "application/json-patch+json",
|
||||
},
|
||||
data: { datastoreName: this.radio },
|
||||
};
|
||||
axios.delete(`${this.baseURL}/api/DataStoreMgmt`, config).then((res) => {
|
||||
this.getList();
|
||||
this.dialogDelVisible = false;
|
||||
this.radio = "";
|
||||
});
|
||||
},
|
||||
|
||||
getFile(event, item) {
|
||||
item.file = event.target.files[0];
|
||||
},
|
||||
openUploadwin(name) {
|
||||
if (this.radio == "") {
|
||||
alert("请选择要上传的数据库");
|
||||
return;
|
||||
}
|
||||
this.currentDataStore = name;
|
||||
this.uploadFiles = [];
|
||||
this.uploadFiles.push({ scenario: "", file: "" });
|
||||
this.dialogUploadVisible = true;
|
||||
},
|
||||
addFile() {
|
||||
this.uploadFiles.push({ scenario: "", file: "" });
|
||||
},
|
||||
uploadSend() {
|
||||
let result = [];
|
||||
console.log(this.uploadFiles.length);
|
||||
for (let i = 0; i < this.uploadFiles.length; i++) {
|
||||
let formData = new FormData();
|
||||
formData.append("DatastoreName", this.currentDataStore);
|
||||
formData.append("Scenario", this.uploadFiles[i].scenario);
|
||||
formData.append("UploadFile", this.uploadFiles[i].file);
|
||||
let config = {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
};
|
||||
setTimeout(() => {
|
||||
axios
|
||||
.post(
|
||||
`${this.baseURL}/api/DataStoreMgmt/preprocess/upload`,
|
||||
formData,
|
||||
config
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.data.success == false) {
|
||||
alert(res.data.responseMessage);
|
||||
this.dialogUploadVisible = false;
|
||||
} else {
|
||||
result.push(true);
|
||||
}
|
||||
});
|
||||
}, i * 1000);
|
||||
}
|
||||
let timer = setInterval(() => {
|
||||
if (result.length == this.uploadFiles.length) {
|
||||
if (result.every((item) => item == true)) {
|
||||
alert("上传成功");
|
||||
this.dialogUploadVisible = false;
|
||||
this.radio = "";
|
||||
let formData = new FormData();
|
||||
formData.append("DatastoreName", this.currentDataStore);
|
||||
axios
|
||||
.post(
|
||||
`${this.baseURL}/api/DataStoreMgmt/preprocess/reload`,
|
||||
formData
|
||||
)
|
||||
.then((res) => {});
|
||||
} else {
|
||||
alert("上传失败");
|
||||
}
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
FROM python36
|
||||
|
||||
COPY aspnetcore-runtime-2.1.16-linux-x64.tar.gz /data/
|
||||
|
||||
RUN mkdir -p /dotnet && \
|
||||
tar zxf /data/aspnetcore-runtime-2.1.16-linux-x64.tar.gz -C /dotnet
|
||||
ENV PATH=/dotnet:$PATH \
|
||||
ASPNETCORE_URLS=http://+:8080 \
|
||||
DOTNET_RUNNING_IN_CONTAINER=true \
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
Binary file not shown.
|
@ -0,0 +1,16 @@
|
|||
version: '2.3'
|
||||
|
||||
services:
|
||||
aspnetcore:
|
||||
image: aspnetcore
|
||||
build: ./aspnetcore/
|
||||
smartkg:
|
||||
image: smartkg
|
||||
build: ./smartkg/
|
||||
ports:
|
||||
- 8082:8080
|
||||
ui:
|
||||
image: ui
|
||||
build: ./ui/
|
||||
ports:
|
||||
- 8083:8080
|
|
@ -0,0 +1,28 @@
|
|||
version: '2.3'
|
||||
|
||||
services:
|
||||
aspnetcore:
|
||||
image: aspnetcore
|
||||
build: ./aspnetcore/
|
||||
mongo:
|
||||
image: mongo
|
||||
restart: always
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: dialogdatabase
|
||||
MONGO_INITDB_ROOT_PASSWORD: erN9XzDa785DSKrB
|
||||
volumes:
|
||||
# Persist data
|
||||
- ./MongoData:/data/db
|
||||
ports:
|
||||
- 27000:27017
|
||||
smartkg:
|
||||
image: smartkg
|
||||
build: ./smartkg/
|
||||
ports:
|
||||
- 8082:8080
|
||||
ui:
|
||||
image: ui
|
||||
build: ./ui/
|
||||
ports:
|
||||
- 8083:8080
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
version: '2.3'
|
||||
|
||||
services:
|
||||
aspnetcore:
|
||||
image: aspnetcore
|
||||
build: ./aspnetcore/
|
||||
mongo:
|
||||
image: mongo
|
||||
restart: always
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: dialogdatabase
|
||||
MONGO_INITDB_ROOT_PASSWORD: erN9XzDa785DSKrB
|
||||
volumes:
|
||||
# Persist data
|
||||
- ./MongoData:/data/db
|
||||
ports:
|
||||
- 27000:27017
|
||||
smartkg:
|
||||
image: smartkg
|
||||
build: ./smartkg/
|
||||
ports:
|
||||
- 8082:8080
|
||||
ui:
|
||||
image: ui
|
||||
build: ./ui/
|
||||
ports:
|
||||
- 8083:8080
|
|
@ -0,0 +1,23 @@
|
|||
FROM aspnetcore
|
||||
|
||||
ARG DOCKER_HOST
|
||||
|
||||
COPY requirements.txt /tmp/
|
||||
RUN pip install -r /tmp/requirements.txt
|
||||
|
||||
COPY SmartKGLocalBase.zip /tmp/
|
||||
RUN unzip /tmp/SmartKGLocalBase.zip -d /app
|
||||
|
||||
COPY smartkg.zip /tmp/
|
||||
RUN unzip /tmp/smartkg.zip -d /app
|
||||
|
||||
COPY appsettings.json /app/smartkg/
|
||||
|
||||
RUN sed -i "s/localhost/${DOCKER_HOST}/g" /app/smartkg/appsettings.json
|
||||
|
||||
ENV PATH=/opt/rh/rh-python36/root/usr/bin:$PATH \
|
||||
LD_LIBRARY_PATH=/app/smartkg/lib64:$LD_LIBRARY_PATH
|
||||
|
||||
|
||||
CMD cd /app/smartkg && \
|
||||
dotnet SmartKG.KGBot.dll
|
Binary file not shown.
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"RunningMode": "Production",
|
||||
"PersistanceType": "MongoDB",
|
||||
"ConnectionStrings": {
|
||||
"MongoDbConnection": "mongodb://dialogdatabase:erN9XzDa785DSKrB@localhost:27000",
|
||||
"DataStoreMgmtDatabaseName": "DataStoreMgmt",
|
||||
"ContextDatabaseName": "KGbot_Context"
|
||||
},
|
||||
"FileUploadConfig": {
|
||||
"ColorConfigPath":"/app/SmartKGLocalBase/config",
|
||||
"ExcelDir": "/app/SmartKGLocalBase/temp"
|
||||
},
|
||||
"KGDisplayConfig": {
|
||||
"MaxEntityNumOfScenarioToDisplay": 200
|
||||
},
|
||||
"Scenarios": [
|
||||
{
|
||||
"ScenarioName": "MotionAndPower",
|
||||
"MaxOptions": 3,
|
||||
"Slots": []
|
||||
}
|
||||
],
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning"
|
||||
},
|
||||
"Using": [
|
||||
"Serilog.Sinks.Console",
|
||||
"Serilog.Sinks.File"
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "RollingFile",
|
||||
"Args": {
|
||||
"pathFormat": "/applog/SmartKG.KGBot-{Date}.log",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] <{SourceContext} : {MemberName}() - line{LineNumber}> {Message} {NewLine} {Exception}",
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true,
|
||||
"retainedFileCountLimit": 20
|
||||
}
|
||||
}
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "SmartKG.KGBot Web Service",
|
||||
"ServiceType": "Chatbot based on KG"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"RunningMode": "Production",
|
||||
"PersistanceType": "File",
|
||||
"FileDataPath": {
|
||||
"RootPath": "..\\SmartKGLocalBase\\DataStores",
|
||||
"ContextFilePath": "..\\SmartKGLocalBase\\kgbot_context.json"
|
||||
},
|
||||
"FileUploadConfig": {
|
||||
"ColorConfigPath": "..\\SmartKGLocalBase\\config",
|
||||
"ExcelDir": "..\\SmartKGLocalBase\\temp"
|
||||
},
|
||||
"KGDisplayConfig": {
|
||||
"MaxEntityNumOfScenarioToDisplay": 200
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning"
|
||||
},
|
||||
"Using": [
|
||||
"Serilog.Sinks.Console",
|
||||
"Serilog.Sinks.File"
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "RollingFile",
|
||||
"Args": {
|
||||
"pathFormat": "/applog/SmartKG.KGBot-{Date}.log",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] <{SourceContext} : {MemberName}() - line{LineNumber}> {Message} {NewLine} {Exception}",
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true,
|
||||
"retainedFileCountLimit": 20
|
||||
}
|
||||
}
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "SmartKG.KGBot Web Service",
|
||||
"ServiceType": "Chatbot based on KG"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"RunningMode": "Production",
|
||||
"PersistanceType": "MongoDB",
|
||||
"ConnectionStrings": {
|
||||
"MongoDbConnection": "mongodb://dialogdatabase:erN9XzDa785DSKrB@104.214.140.219:27000",
|
||||
"DataStoreMgmtDatabaseName": "DataStoreMgmt",
|
||||
"ContextDatabaseName": "KGbot_Context"
|
||||
},
|
||||
"FileUploadConfig": {
|
||||
"ColorConfigPath": "..\\SmartKGLocalBase\\config",
|
||||
"ExcelDir": "..\\SmartKGLocalBase\\temp"
|
||||
},
|
||||
"KGDisplayConfig": {
|
||||
"MaxEntityNumOfScenarioToDisplay": 200
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Serilog": {
|
||||
"MinimumLevel": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning"
|
||||
},
|
||||
"Using": [
|
||||
"Serilog.Sinks.Console",
|
||||
"Serilog.Sinks.File"
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "RollingFile",
|
||||
"Args": {
|
||||
"pathFormat": "/applog/SmartKG.KGBot-{Date}.log",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] <{SourceContext} : {MemberName}() - line{LineNumber}> {Message} {NewLine} {Exception}",
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true,
|
||||
"retainedFileCountLimit": 20
|
||||
}
|
||||
}
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "SmartKG.KGBot Web Service",
|
||||
"ServiceType": "Chatbot based on KG"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
xlrd
|
||||
xlsxwriter
|
||||
argparse
|
||||
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
FROM node
|
||||
|
||||
ARG DOCKER_HOST
|
||||
|
||||
COPY smartkgui.zip /tmp/
|
||||
RUN unzip /tmp/smartkgui.zip -d /app
|
||||
|
||||
COPY config.js /app/smartkgui/public/
|
||||
|
||||
RUN sed -i "s/localhost/${DOCKER_HOST}/g" /app/smartkgui/public/config.js
|
||||
|
||||
CMD cd /app/smartkgui && npm i && npm run serve
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
var urlapi = "http://localhost:8082"
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
var urlapi = "http://localhost:5000"
|
Binary file not shown.
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Logger;
|
||||
using SmartKG.Common.Data.Configuration;
|
||||
|
||||
namespace SmartKG.Common.ContextStore
|
||||
{
|
||||
public class ContextAccessor
|
||||
{
|
||||
private static ContextAccessor uniqueInstance;
|
||||
private IContextAccessor accessor;
|
||||
|
||||
private ILogger log;
|
||||
|
||||
private ContextAccessor(IConfiguration config)
|
||||
{
|
||||
log = Log.Logger.ForContext<ContextAccessor>();
|
||||
|
||||
string persistanceType = config.GetSection("PersistanceType").Value;
|
||||
|
||||
log.Here().Information("PersistanceType is " + persistanceType);
|
||||
|
||||
if (persistanceType == "File")
|
||||
{
|
||||
FilePathConfig filePaths = config.GetSection("FileDataPath").Get<FilePathConfig>();
|
||||
string contextPath = filePaths.ContextFilePath;
|
||||
|
||||
this.accessor = new ContextFileAccessor(contextPath);
|
||||
|
||||
this.accessor.CleanContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
string connectionString = config.GetConnectionString("MongoDbConnection");
|
||||
string dbName = config.GetConnectionString("ContextDatabaseName");
|
||||
|
||||
this.accessor = new ContextDBAccessor(connectionString, dbName);
|
||||
|
||||
this.accessor.CleanContext();
|
||||
}
|
||||
}
|
||||
|
||||
public static ContextAccessor GetInstance()
|
||||
{
|
||||
return uniqueInstance;
|
||||
}
|
||||
|
||||
|
||||
public static ContextAccessor initInstance(IConfiguration config)
|
||||
{
|
||||
if (uniqueInstance == null)
|
||||
{
|
||||
uniqueInstance = new ContextAccessor(config);
|
||||
}
|
||||
|
||||
return uniqueInstance;
|
||||
}
|
||||
|
||||
public (bool, DialogContext) GetContext(string userId, string sessionId)
|
||||
{
|
||||
return this.accessor.GetContext(userId, sessionId);
|
||||
|
||||
}
|
||||
|
||||
public void UpdateContext(string userId, string sessionId, DialogContext context)
|
||||
{
|
||||
this.accessor.UpdateContext(userId, sessionId, context);
|
||||
}
|
||||
|
||||
public void CleanContext()
|
||||
{
|
||||
this.accessor.CleanContext();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data;
|
||||
using MongoDB.Driver;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SmartKG.Common.Logger;
|
||||
using MongoDB.Bson;
|
||||
|
||||
namespace SmartKG.Common.ContextStore
|
||||
{
|
||||
public class ContextDBAccessor : IContextAccessor
|
||||
{
|
||||
private ILogger log;
|
||||
|
||||
private IMongoCollection<DialogContext> collection;
|
||||
|
||||
int MAX_DURATION_INVALID_INPUT = 3;
|
||||
|
||||
public ContextDBAccessor(string connectionString, string dbName) {
|
||||
log = Log.Logger.ForContext<ContextDBAccessor>();
|
||||
|
||||
MongoClient client = new MongoClient(connectionString);
|
||||
|
||||
IMongoDatabase db = client.GetDatabase(dbName);
|
||||
this.collection = db.GetCollection<DialogContext>("Contexts");
|
||||
|
||||
log.Here().Information("Context in MongoDB. connectionString: " + connectionString + ", ContextDatabaseName: " + dbName);
|
||||
}
|
||||
|
||||
public (bool, DialogContext) GetContext(string userId, string sessionId)
|
||||
{
|
||||
bool newlyCreated = true;
|
||||
|
||||
DialogContext context = null;
|
||||
try
|
||||
{
|
||||
var results = collection.FindAsync(x => x.userId == userId && x.sessionId == sessionId).Result;
|
||||
List<DialogContext> contexts = null;
|
||||
|
||||
if (results != null)
|
||||
{
|
||||
contexts = results.ToList<DialogContext>();
|
||||
}
|
||||
|
||||
if (contexts != null && contexts.Count() > 0)
|
||||
{
|
||||
context = contexts[0];
|
||||
newlyCreated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
context = new DialogContext(userId, sessionId, MAX_DURATION_INVALID_INPUT);
|
||||
this.collection.InsertOneAsync(context);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.Error(e, e.Message);
|
||||
throw (e);
|
||||
}
|
||||
|
||||
return (newlyCreated, context);
|
||||
}
|
||||
|
||||
public bool UpdateContext(string userId, string sessionId, DialogContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.collection.ReplaceOneAsync<DialogContext>(x => x.userId == userId && x.sessionId == sessionId, context);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, e.Message);
|
||||
throw (e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void CleanContext()
|
||||
{
|
||||
BsonDocument allFilter = new BsonDocument();
|
||||
this.collection.DeleteMany(allFilter);
|
||||
this.collection.InsertOne(new DialogContext("000", "000", 3));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SmartKG.Common.ContextStore
|
||||
{
|
||||
public class ContextFileAccessor : IContextAccessor
|
||||
{
|
||||
private string filePath;
|
||||
int MAX_DURATION_INVALID_INPUT = 3;
|
||||
public ContextFileAccessor(string filePath)
|
||||
{
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
private string GetKey(string userId, string sessionId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
{
|
||||
userId = "";
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(sessionId))
|
||||
{
|
||||
sessionId = "";
|
||||
}
|
||||
|
||||
return userId + "_" + sessionId;
|
||||
}
|
||||
|
||||
public (bool, DialogContext) GetContext(string userId, string sessionId)
|
||||
{
|
||||
DialogContext context = null;
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
|
||||
string content = File.ReadAllText(filePath);
|
||||
|
||||
|
||||
string[] lines = content.Split('\n');
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] tmps = line.Split("\t");
|
||||
|
||||
if (tmps.Length != 2)
|
||||
{
|
||||
throw new Exception("Context File is invalid.");
|
||||
}
|
||||
|
||||
string key = tmps[0];
|
||||
string contextJsonStr = tmps[1];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
throw new Exception("Context Key cannot be empty.");
|
||||
}
|
||||
|
||||
if (key == GetKey(userId, sessionId))
|
||||
{
|
||||
return (false, JsonConvert.DeserializeObject<DialogContext>(contextJsonStr));
|
||||
}
|
||||
}
|
||||
|
||||
context = new DialogContext(userId, sessionId, MAX_DURATION_INVALID_INPUT);
|
||||
|
||||
string newLine = GetKey(userId, sessionId) + "\t" + JsonConvert.SerializeObject(context) + Environment.NewLine;
|
||||
|
||||
File.AppendAllText(this.filePath, newLine);
|
||||
return (true, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
context = new DialogContext(userId, sessionId, MAX_DURATION_INVALID_INPUT);
|
||||
|
||||
string newLine = GetKey(userId, sessionId) + "\t" + JsonConvert.SerializeObject(context) + Environment.NewLine;
|
||||
|
||||
File.WriteAllText(this.filePath, newLine);
|
||||
return (true, context);
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateContext(string userId, string sessionId, DialogContext context)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new Exception("Context File doesn't exist. Cannot update context into it.");
|
||||
}
|
||||
|
||||
string content = File.ReadAllText(filePath);
|
||||
|
||||
string[] lines = content.Split('\n');
|
||||
|
||||
string newContent = "";
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] tmps = line.Split("\t");
|
||||
|
||||
if (tmps.Length != 2)
|
||||
{
|
||||
throw new Exception("Context File is invalid.");
|
||||
}
|
||||
|
||||
string key = tmps[0];
|
||||
string contextJsonStr = tmps[1];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
throw new Exception("Context Key cannot be empty.");
|
||||
}
|
||||
|
||||
if (key == GetKey(userId, sessionId))
|
||||
{
|
||||
newContent += key + "\t" + JsonConvert.SerializeObject(context) + Environment.NewLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
newContent += line + Environment.NewLine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File.WriteAllText(this.filePath, newContent);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void CleanContext()
|
||||
{
|
||||
File.WriteAllText(this.filePath, "");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data;
|
||||
using MongoDB.Driver;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Logger;
|
||||
using SmartKG.Common.Data.LU;
|
||||
|
||||
namespace SmartKG.Common.ContextStore
|
||||
{
|
||||
public class ContextManager : KGBotLogHandler
|
||||
{
|
||||
public const int MAX_DURATION_INVALID_INPUT = 3;
|
||||
|
||||
private DialogContext context;
|
||||
|
||||
private string userId;
|
||||
private string sessionId;
|
||||
private string datastoreName;
|
||||
|
||||
private ContextAccessor accController = ContextAccessor.GetInstance();
|
||||
|
||||
private ILogger log;
|
||||
public ContextManager(string datastoreName, string userId, string sessionId)
|
||||
{
|
||||
this.datastoreName = datastoreName;
|
||||
this.userId = userId;
|
||||
this.sessionId = sessionId;
|
||||
|
||||
log = Log.Logger.ForContext<ContextManager>();
|
||||
}
|
||||
|
||||
public void LogInformation(ILogger log, string title, string content)
|
||||
{
|
||||
log.Information("userId: " + this.userId + ", sessionId:" + this.sessionId + "\n" + title + " " + content);
|
||||
}
|
||||
|
||||
public void LogError(ILogger log, Exception e)
|
||||
{
|
||||
log.Error("userId: " + this.userId + ", sessionId:" + this.sessionId + "\n" + e.Message, e);
|
||||
}
|
||||
|
||||
public bool GetContext()
|
||||
{
|
||||
(bool isNewlyCreated, DialogContext aContext) = accController.GetContext(userId, sessionId);
|
||||
|
||||
if (isNewlyCreated)
|
||||
{
|
||||
aContext.datastoreName = this.datastoreName;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aContext.datastoreName != this.datastoreName)
|
||||
{
|
||||
if (aContext.status != DialogStatus.PENDING)
|
||||
{
|
||||
this.context = aContext;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
aContext.datastoreName = this.datastoreName;
|
||||
}
|
||||
}
|
||||
|
||||
this.context = aContext;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdateContext()
|
||||
{
|
||||
accController.UpdateContext(this.userId, this.sessionId, this.context);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public string GetStartVertexName()
|
||||
{
|
||||
return this.context.startVertexName;
|
||||
}
|
||||
|
||||
public void SetStartVertexName(string name)
|
||||
{
|
||||
this.context.startVertexName = name;
|
||||
}
|
||||
|
||||
public int GetMaxDurationTime()
|
||||
{
|
||||
return MAX_DURATION_INVALID_INPUT;
|
||||
}
|
||||
|
||||
public int GetCurrentSlotSeqNum()
|
||||
{
|
||||
return this.context.currentSlotSeqNum;
|
||||
}
|
||||
|
||||
public bool DureInvalidInput()
|
||||
{
|
||||
this.context.currentDurationTime -= 1;
|
||||
if (this.context.currentDurationTime >= 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public void RefreshDurationTime()
|
||||
{
|
||||
this.context.currentDurationTime = MAX_DURATION_INVALID_INPUT;
|
||||
}
|
||||
|
||||
public void SaveQuestion(string question)
|
||||
{
|
||||
LogInformation(log.Here(), "saved question:", question);
|
||||
this.context.question = question;
|
||||
}
|
||||
|
||||
public string GetQuestion()
|
||||
{
|
||||
return this.context.question;
|
||||
}
|
||||
public bool IsAllSlotsFilled()
|
||||
{
|
||||
if (this.context.slots == null)
|
||||
return true;
|
||||
|
||||
if (this.context.currentSlotSeqNum < this.context.slots.Count())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddAttributeFilterCondition(AttributePair attribute)
|
||||
{
|
||||
LogInformation(log.Here(), "get attribute:", JsonConvert.SerializeObject(attribute));
|
||||
|
||||
string key = attribute.attributeName;
|
||||
|
||||
if (this.context.savedAttributes.Keys.Contains(key))
|
||||
{
|
||||
this.context.savedAttributes[key] = attribute;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.context.savedAttributes.Add(key, attribute);
|
||||
}
|
||||
}
|
||||
|
||||
public List<AttributePair> GetSavedAttributes()
|
||||
{
|
||||
return this.context.savedAttributes.Values.ToList();
|
||||
}
|
||||
|
||||
public void SetSlots(List<DialogSlot> slots)
|
||||
{
|
||||
this.context.slots = slots;
|
||||
}
|
||||
|
||||
public DialogSlot GetSlot(int stepNum)
|
||||
{
|
||||
if (stepNum > this.context.slots.Count())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.context.slots[stepNum - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public void SetIntent(string intent)
|
||||
{
|
||||
this.context.intent = intent;
|
||||
}
|
||||
|
||||
public void AddEntity(Object entity)
|
||||
{
|
||||
this.context.entities.Add(entity);
|
||||
}
|
||||
|
||||
public void SetCandidates(Dictionary<int, Vertex> candidates)
|
||||
{
|
||||
LogInformation(log.Here(), "set candidates:", JsonConvert.SerializeObject(candidates));
|
||||
this.context.vertexCandidates = candidates;
|
||||
}
|
||||
|
||||
public string GetIntent()
|
||||
{
|
||||
return this.context.intent;
|
||||
}
|
||||
|
||||
public void SetScenarioName(string scenarioName)
|
||||
{
|
||||
this.context.scenarioName = scenarioName;
|
||||
}
|
||||
|
||||
public string GetSecnarioName()
|
||||
{
|
||||
return this.context.scenarioName;
|
||||
}
|
||||
|
||||
public List<Object> GetEntities()
|
||||
{
|
||||
return this.context.entities;
|
||||
}
|
||||
|
||||
public Dictionary<int, Vertex> GetCandidates()
|
||||
{
|
||||
return this.context.vertexCandidates;
|
||||
}
|
||||
|
||||
public void StartDialog()
|
||||
{
|
||||
LogInformation(log.Here(), "start a dialog", "");
|
||||
this.context.status = DialogStatus.INPROCESS;
|
||||
}
|
||||
|
||||
public void EnterSlotFilling()
|
||||
{
|
||||
LogInformation(log.Here(), "begine to fill slots", "");
|
||||
this.context.status = DialogStatus.SLOTFILLING;
|
||||
this.context.currentSlotSeqNum = 1;
|
||||
}
|
||||
|
||||
public void ForwardSlotFilling()
|
||||
{
|
||||
LogInformation(log.Here(), "slot [" + this.context.currentSlotSeqNum.ToString() + "]", "is processed");
|
||||
this.context.currentSlotSeqNum += 1;
|
||||
}
|
||||
|
||||
public DialogStatus GetStatus()
|
||||
{
|
||||
return this.context.status;
|
||||
}
|
||||
|
||||
public void ExitDialog()
|
||||
{
|
||||
LogInformation(log.Here(), "exit dialog", "");
|
||||
this.context.datastoreName = null;
|
||||
this.context.vertexCandidates = null;
|
||||
this.context.status = DialogStatus.PENDING;
|
||||
this.context.slots = null;
|
||||
this.context.currentSlotSeqNum = 0;
|
||||
this.context.savedAttributes = new Dictionary<string, AttributePair>();
|
||||
|
||||
this.context.currentDurationTime = MAX_DURATION_INVALID_INPUT;
|
||||
this.context.question = null;
|
||||
this.context.intent = null;
|
||||
this.context.startVertexName = null;
|
||||
this.context.scenarioName = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data;
|
||||
|
||||
namespace SmartKG.Common.ContextStore
|
||||
{
|
||||
public interface IContextAccessor
|
||||
{
|
||||
(bool, DialogContext) GetContext(string userId, string sessionId);
|
||||
bool UpdateContext(string userId, string sessionId, DialogContext context);
|
||||
|
||||
void CleanContext();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SmartKG.Common.Data.Configuration
|
||||
{
|
||||
public class FilePathConfig
|
||||
{
|
||||
public string RootPath { get; set; }
|
||||
public string DefaultDataStore { get; set; }
|
||||
public string ContextFilePath { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.Configuration
|
||||
{
|
||||
public class FileUploadConfig
|
||||
{
|
||||
public string PythonEnvPath { get; set; }
|
||||
public string ConvertScriptPath { get; set; }
|
||||
|
||||
public string ColorConfigPath { get; set; }
|
||||
public string ExcelDir { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.Configuration
|
||||
{
|
||||
public class KGDisplayConfig
|
||||
{
|
||||
|
||||
public int MaxEntityNumOfScenarioToDisplay { get; set; } = 150;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SmartKG.Common.Data
|
||||
{
|
||||
[BsonIgnoreExtraElements]
|
||||
public class DatastoreItem
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string creator { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
using SmartKG.Common.Data;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data
|
||||
{
|
||||
public enum RUNNINGMODE
|
||||
{
|
||||
PRODUCTION, DEVELOPMENT
|
||||
}
|
||||
|
||||
public enum DialogStatus
|
||||
{
|
||||
PENDING, SLOTFILLING, INPROCESS
|
||||
}
|
||||
|
||||
[BsonIgnoreExtraElements]
|
||||
public class DialogContext
|
||||
{
|
||||
public string datastoreName { get; set; }
|
||||
public DialogStatus status { get; set; }
|
||||
public string intent { get; set; }
|
||||
public string scenarioName { get; set; }
|
||||
public List<Object> entities { get; set; }
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<int, Vertex> vertexCandidates { get; set; }
|
||||
public List<DialogSlot> slots { get; set; }
|
||||
public int currentSlotSeqNum { get; set; }
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<string, AttributePair> savedAttributes { get; set; }
|
||||
public string startVertexName { get; set; }
|
||||
public int currentDurationTime { get; set; }
|
||||
public string question { get; set; }
|
||||
public string sessionId { get; set; }
|
||||
public string userId { get; set; }
|
||||
|
||||
public DialogContext(string userId, string sessionId, int maxDurationInvalidInput)
|
||||
{
|
||||
this.datastoreName = null;
|
||||
this.entities = new List<object>();
|
||||
this.vertexCandidates = null;
|
||||
this.status = DialogStatus.PENDING;
|
||||
this.startVertexName = null;
|
||||
this.currentDurationTime = maxDurationInvalidInput;
|
||||
|
||||
this.currentSlotSeqNum = 0;
|
||||
this.savedAttributes = new Dictionary<string, AttributePair>();
|
||||
this.question = null;
|
||||
|
||||
this.userId = userId;
|
||||
this.sessionId = sessionId;
|
||||
this.scenarioName = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data
|
||||
{
|
||||
public class DialogSlot
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string kgKey { get; set; }
|
||||
public string question { get; set; }
|
||||
|
||||
public List<OptionItem> items { get; set; }
|
||||
|
||||
public List<string> answerValues { get; set; }
|
||||
public string correspondingAttribute { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data.KG
|
||||
{
|
||||
[BsonIgnoreExtraElements]
|
||||
public class Edge
|
||||
{
|
||||
public List<string> scenarios { get; set; }
|
||||
public string relationType { get; set; }
|
||||
public string headVertexId { get; set; }
|
||||
public string tailVertexId { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.KG
|
||||
{
|
||||
|
||||
public class RelationLink
|
||||
{
|
||||
public string relationType { get; set; }
|
||||
public string scenarioName { get; set; }
|
||||
|
||||
public RelationLink(string relationType, string scenarioName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(relationType))
|
||||
{
|
||||
this.relationType = "ALL";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.relationType = relationType;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
this.scenarioName = "ALL";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.scenarioName = scenarioName;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Equals(RelationLink other)
|
||||
{
|
||||
if (this.relationType == other.relationType && this.scenarioName == other.scenarioName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsCompatible(RelationLink other)
|
||||
{
|
||||
if (this.relationType != "ALL" && other.relationType != "ALL" && this.relationType != other.relationType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.scenarioName != "ALL" && other.scenarioName != "ALL" && this.scenarioName != other.scenarioName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data.KG
|
||||
{
|
||||
public class Vertex
|
||||
{
|
||||
|
||||
public string id { get; set; }
|
||||
public string name { get; set; }
|
||||
public string label { get; set; }
|
||||
public List<string> scenarios { get; set; }
|
||||
public string nodeType { get; set; }
|
||||
|
||||
public string leadSentence { get; set; }
|
||||
|
||||
public List<VertexProperty> properties { get; set; }
|
||||
|
||||
public bool isRoot()
|
||||
{
|
||||
if (nodeType == "ROOT")
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool isLeaf()
|
||||
{
|
||||
if (nodeType == "LEAF")
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetContent()
|
||||
{
|
||||
string result = this.name + "\n";
|
||||
|
||||
foreach(VertexProperty p in this.properties)
|
||||
{
|
||||
result += p.name + ": " + p.value + "\n";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public string GetPropertyValue(string name)
|
||||
{
|
||||
if (this.properties == null || this.properties.Count == 0)
|
||||
return null;
|
||||
|
||||
foreach (VertexProperty p in this.properties)
|
||||
{
|
||||
string value = p.GetValue(name);
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.KG
|
||||
{
|
||||
public class VertexProperty
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string value { get; set; }
|
||||
|
||||
|
||||
public string GetValue(string name)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(this.name) && !string.IsNullOrWhiteSpace(name) && this.name == name)
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.LU
|
||||
{
|
||||
public class AttributePair
|
||||
{
|
||||
public string attributeName { get; set; }
|
||||
public string attributeValue { get; set; }
|
||||
|
||||
public AttributePair(string name, string value)
|
||||
{
|
||||
this.attributeName = name;
|
||||
this.attributeValue = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.LU
|
||||
{
|
||||
public class EntityAttributeData
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string intentName { get; set; }
|
||||
public string entityValue { get; set; }
|
||||
public string entityType { get; set; }
|
||||
public string attributeName { get; set; }
|
||||
public string attributeValue { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.LU
|
||||
{
|
||||
public class EntityData
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string intentName { get; set; }
|
||||
public string similarWord { get; set; }
|
||||
public string entityValue { get; set; }
|
||||
public string entityType { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.LU
|
||||
{
|
||||
public class NLUEntity
|
||||
{
|
||||
private string type { get; set; }
|
||||
private string value { get; set; }
|
||||
|
||||
public NLUEntity(string value, string type)
|
||||
{
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public string GetEntityValue()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public string GetEntityType()
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public static string GenerateIdentity(string value, string type)
|
||||
{
|
||||
string identity = "";
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
identity += type + "_";
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
identity += value;
|
||||
}
|
||||
|
||||
if (identity == "")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetIdentity()
|
||||
{
|
||||
string identity = "";
|
||||
|
||||
if (this.type != null)
|
||||
{
|
||||
identity += this.type + "_";
|
||||
}
|
||||
|
||||
if (this.value != null)
|
||||
{
|
||||
identity += this.value;
|
||||
}
|
||||
|
||||
if (identity == "")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
|
||||
public NLUEntity Clone()
|
||||
{
|
||||
NLUEntity newOne = new NLUEntity( this.value, this.type);
|
||||
return newOne;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data.LU
|
||||
{
|
||||
public enum IntentRuleType
|
||||
{
|
||||
NEGATIVE, POSITIVE
|
||||
}
|
||||
public class NLUIntentRule
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string intentName { get; set; }
|
||||
public IntentRuleType type { get; set; }
|
||||
public List<String> ruleSecs { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace SmartKG.Common.Data.LU
|
||||
{
|
||||
|
||||
public enum NLUResultType
|
||||
{
|
||||
[Description("Not Completed")]
|
||||
NORMAL, NUMBER, QUITDIALOG, UNKNOWN, NOTEXIST
|
||||
}
|
||||
|
||||
public class NLUResult
|
||||
{
|
||||
private NLUResultType type;
|
||||
private string intent = null;
|
||||
private List<NLUEntity> entities = null;
|
||||
private List<AttributePair> attributes = null;
|
||||
private HashSet<string> relationTypeSet = null;
|
||||
private int option = -1;
|
||||
|
||||
public NLUResult(int option)
|
||||
{
|
||||
this.type = NLUResultType.NUMBER;
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
public NLUResult(NLUResultType type)
|
||||
{
|
||||
this.type = type;
|
||||
|
||||
if (type == NLUResultType.QUITDIALOG)
|
||||
{
|
||||
this.option = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public NLUResult(string intent)
|
||||
{
|
||||
this.type = NLUResultType.NORMAL;
|
||||
this.intent = intent;
|
||||
this.entities = new List<NLUEntity>();
|
||||
this.attributes = new List<AttributePair>();
|
||||
}
|
||||
|
||||
public NLUResult(string intent, List<NLUEntity> entities, List<AttributePair> attributes, HashSet<string> relationTypeSet)
|
||||
{
|
||||
this.type = NLUResultType.NORMAL;
|
||||
this.intent = intent;
|
||||
this.entities = entities;
|
||||
|
||||
if (attributes != null)
|
||||
{
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
if (relationTypeSet.Count > 0)
|
||||
{
|
||||
this.relationTypeSet = relationTypeSet;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetIntent()
|
||||
{
|
||||
return this.intent;
|
||||
}
|
||||
|
||||
public List<NLUEntity> GetEntities()
|
||||
{
|
||||
return this.entities;
|
||||
}
|
||||
|
||||
public List<AttributePair> GetAttributes()
|
||||
{
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
public HashSet<string> GetRelationTypeSet()
|
||||
{
|
||||
return relationTypeSet;
|
||||
}
|
||||
|
||||
public int GetOption()
|
||||
{
|
||||
return this.option;
|
||||
}
|
||||
|
||||
public new NLUResultType GetType()
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
|
||||
override
|
||||
public string ToString()
|
||||
{
|
||||
Dictionary<string, string> dict = new Dictionary<string, string>();
|
||||
dict.Add("type", this.type.ToString());
|
||||
if (!string.IsNullOrWhiteSpace(this.intent))
|
||||
{
|
||||
dict.Add("intent", this.intent);
|
||||
}
|
||||
|
||||
if (entities != null && entities.Count > 0)
|
||||
{
|
||||
string entitiestr = "";
|
||||
foreach (NLUEntity e in entities)
|
||||
{
|
||||
entitiestr += e.GetEntityType() + ":" + e.GetEntityValue();
|
||||
entitiestr += ", ";
|
||||
}
|
||||
|
||||
dict.Add("entities", entitiestr);
|
||||
}
|
||||
|
||||
if (attributes != null && attributes.Count > 0)
|
||||
{
|
||||
string attrStr = "";
|
||||
|
||||
foreach(AttributePair attr in attributes)
|
||||
{
|
||||
attrStr += attr.attributeName + ": " + attr.attributeValue;
|
||||
attrStr += ", ";
|
||||
}
|
||||
dict.Add("attributes", attrStr);
|
||||
}
|
||||
|
||||
string result = JsonConvert.SerializeObject(dict);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data.KG;
|
||||
|
||||
namespace SmartKG.Common.Data
|
||||
{
|
||||
public class OptionItem
|
||||
{
|
||||
public int seqNo { get; set; }
|
||||
public Vertex vertex { get; set; }
|
||||
public string relationType { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SmartKG.Common.Data
|
||||
{
|
||||
public enum PersistanceType
|
||||
{
|
||||
File, MongoDB
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data.KG;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data
|
||||
{
|
||||
public enum VertexSortOrderType
|
||||
{
|
||||
ASC=0, DESC=1
|
||||
}
|
||||
|
||||
public class SortSetting
|
||||
{
|
||||
public string attributeName { get; set; }
|
||||
public VertexSortOrderType orderType { get; set; }
|
||||
}
|
||||
|
||||
public class ScenarioSetting
|
||||
{
|
||||
public string scenarioName { get; set; }
|
||||
public SortSetting sortSetting { get; set; }
|
||||
public int maxOptions { get; set; }
|
||||
|
||||
public List<DialogSlot> slots { get; set; }
|
||||
|
||||
public Vertex root { get; set; }
|
||||
|
||||
public ScenarioSetting(string scenarioName, Vertex root)
|
||||
{
|
||||
this.scenarioName = scenarioName;
|
||||
this.root = root;
|
||||
|
||||
this.sortSetting = null;
|
||||
this.maxOptions = -1;
|
||||
this.slots = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.Data.Visulization
|
||||
{
|
||||
[BsonIgnoreExtraElements]
|
||||
public class VisulizationConfig
|
||||
{
|
||||
public string scenario { get; set; }
|
||||
public List<ColorConfig> labelsOfVertexes { get; set; }
|
||||
public List<ColorConfig> relationTypesOfEdges { get; set; }
|
||||
}
|
||||
|
||||
[BsonIgnoreExtraElements]
|
||||
public class ColorConfig
|
||||
{
|
||||
public string itemLabel { get; set; }
|
||||
public string color { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.Visulization
|
||||
{
|
||||
public class VisulizedEdge
|
||||
{
|
||||
public string value { get; set; }
|
||||
public string sourceId { get; set; }
|
||||
public string targetId { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace SmartKG.Common.Data.Visulization
|
||||
{
|
||||
public class VisulizedVertex
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string name { get; set; }
|
||||
public string displayName { get; set; }
|
||||
public string label { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data;
|
||||
using SmartKG.Common.Data.Configuration;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using SmartKG.Common.DataPersistance;
|
||||
using SmartKG.Common.DataStoreMgmt;
|
||||
using SmartKG.Common.Logger;
|
||||
using SmartKG.Common.Parser.DataPersistance;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.DataPersistence
|
||||
{
|
||||
public class DataLoader
|
||||
{
|
||||
private ILogger log;
|
||||
|
||||
private IDataAccessor dataAccessor;
|
||||
private PersistanceType persistanceType;
|
||||
private FileUploadConfig uploadConfig;
|
||||
private FilePathConfig filePathConfig = null;
|
||||
private KGDisplayConfig kgDisplayConfig;
|
||||
|
||||
|
||||
public DataLoader(IConfiguration config)
|
||||
{
|
||||
this.log = Log.Logger.ForContext<DataLoader>();
|
||||
|
||||
uploadConfig = config.GetSection("FileUploadConfig").Get<FileUploadConfig>();
|
||||
persistanceType = (PersistanceType)Enum.Parse(typeof(PersistanceType), config.GetSection("PersistanceType").Value, true);
|
||||
|
||||
if (persistanceType == PersistanceType.File)
|
||||
{
|
||||
this.filePathConfig = config.GetSection("FileDataPath").Get<FilePathConfig>();
|
||||
this.dataAccessor = new FileDataAccessor(filePathConfig.RootPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string connectionString = config.GetConnectionString("MongoDbConnection");
|
||||
string mgmtDBName = config.GetConnectionString("DataStoreMgmtDatabaseName");
|
||||
|
||||
this.dataAccessor = new MongoDataAccessor(connectionString, mgmtDBName);
|
||||
}
|
||||
|
||||
kgDisplayConfig = config.GetSection("KGDisplayConfig").Get<KGDisplayConfig>();
|
||||
}
|
||||
|
||||
public List<DataStoreFrame> Load()
|
||||
{
|
||||
List<string> datastoreNames = dataAccessor.GetDataStoreList();
|
||||
|
||||
List<DataStoreFrame> datastores = new List<DataStoreFrame>();
|
||||
|
||||
foreach (string dsName in datastoreNames)
|
||||
{
|
||||
DataStoreFrame dsFrame = this.LoadDataStore(dsName);
|
||||
|
||||
if (dsFrame != null)
|
||||
{
|
||||
datastores.Add(dsFrame);
|
||||
}
|
||||
}
|
||||
|
||||
return datastores;
|
||||
}
|
||||
|
||||
|
||||
public DataStoreFrame LoadDataStore(string dsName)
|
||||
{
|
||||
List<Vertex> vList = null;
|
||||
List<Edge> eList = null;
|
||||
List<VisulizationConfig> vcList = null;
|
||||
|
||||
List<NLUIntentRule> iList = null;
|
||||
List<EntityData> enList = null;
|
||||
List<EntityAttributeData> eaList = null;
|
||||
|
||||
(vList, eList, vcList, iList, enList, eaList) = this.dataAccessor.Load(dsName);
|
||||
|
||||
if (vcList == null || vList == null || eList == null)
|
||||
{
|
||||
log.Here().Warning("No KG Data loaded from persistence");
|
||||
return null;
|
||||
}
|
||||
|
||||
DataPersistanceKGParser kgParser = new DataPersistanceKGParser();
|
||||
KnowledgeGraphDataFrame kgDF = kgParser.ParseKG(vList, eList);
|
||||
KGConfigFrame kgConfigFrame = kgParser.ParseKGConfig(vcList);
|
||||
|
||||
log.Information("Knowledge Graph is parsed.");
|
||||
Console.WriteLine("Knowledge Graph is parsed.");
|
||||
|
||||
NLUDataFrame nluDF = null;
|
||||
|
||||
if (iList == null || enList == null)
|
||||
{
|
||||
log.Here().Warning("No NLU Data loaded from persistence");
|
||||
}
|
||||
else
|
||||
{
|
||||
DataPersistanceNLUParser nluParser = new DataPersistanceNLUParser();
|
||||
nluDF = nluParser.Parse(iList, enList, eaList);
|
||||
|
||||
log.Information("NLU materials is parsed.");
|
||||
Console.WriteLine("NLU materials is parsed.");
|
||||
}
|
||||
|
||||
DataStoreFrame dsFrame = new DataStoreFrame(dsName, kgDF, kgConfigFrame, nluDF);
|
||||
|
||||
return dsFrame;
|
||||
}
|
||||
|
||||
public bool UpdateColorConfig(string user, string datastoreName, string scenarioName, List<ColorConfig> colorConfigs)
|
||||
{
|
||||
return this.dataAccessor.UpdateColorConfig(user, datastoreName, scenarioName, colorConfigs);
|
||||
}
|
||||
|
||||
public List<string> GetDataStoreList()
|
||||
{
|
||||
return this.dataAccessor.GetDataStoreList();
|
||||
}
|
||||
|
||||
public bool CreateDataStore(string user, string datastoreName)
|
||||
{
|
||||
return this.dataAccessor.AddDataStore(user, datastoreName);
|
||||
}
|
||||
|
||||
public bool DeleteDataStore(string user, string datastoreName)
|
||||
{
|
||||
return this.dataAccessor.DeleteDataStore(user, datastoreName);
|
||||
}
|
||||
|
||||
public PersistanceType GetPersistanceType()
|
||||
{
|
||||
return this.persistanceType;
|
||||
}
|
||||
|
||||
public FileUploadConfig GetUploadConfig()
|
||||
{
|
||||
return this.uploadConfig;
|
||||
}
|
||||
|
||||
public FilePathConfig GetFilePathConfig()
|
||||
{
|
||||
return this.filePathConfig;
|
||||
}
|
||||
|
||||
public int GetMaxDisplayedEntityNumber()
|
||||
{
|
||||
return this.kgDisplayConfig.MaxEntityNumOfScenarioToDisplay;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,271 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using SmartKG.Common.DataPersistence;
|
||||
using SmartKG.Common.Importer;
|
||||
using SmartKG.Common.Logger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace SmartKG.Common.DataPersistance
|
||||
{
|
||||
public class FileDataAccessor : IDataAccessor
|
||||
{
|
||||
private ILogger log;
|
||||
|
||||
private string rootPath;
|
||||
|
||||
|
||||
public FileDataAccessor(string rootPath)
|
||||
{
|
||||
this.rootPath = rootPath;
|
||||
this.log = Log.Logger.ForContext<FileDataAccessor>();
|
||||
}
|
||||
|
||||
public (List<Vertex>, List<Edge>) LoadKG(string dsName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dsName))
|
||||
{
|
||||
log.Here().Warning("The datastore: " + dsName + " doesn't exist.");
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
string kgPath = this.rootPath + Path.DirectorySeparatorChar + dsName + Path.DirectorySeparatorChar + "KG" + Path.DirectorySeparatorChar;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(kgPath) || !Directory.Exists(kgPath))
|
||||
{
|
||||
log.Here().Warning("The path of KGFilePath: " + kgPath + " doesn't exist.");
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
log.Here().Information("KGFilePath: " + kgPath);
|
||||
|
||||
KGDataImporter importer = new KGDataImporter(kgPath);
|
||||
|
||||
List<Vertex> vList = importer.ParseKGVertexes();
|
||||
List<Edge> eList = importer.ParseKGEdges();
|
||||
|
||||
|
||||
log.Here().Information("KG data has been parsed from Files.");
|
||||
|
||||
return (vList, eList);
|
||||
|
||||
}
|
||||
|
||||
public List<VisulizationConfig> LoadConfig(string dsName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dsName))
|
||||
{
|
||||
log.Here().Warning("The datastore: " + dsName + " doesn't exist.");
|
||||
return null;
|
||||
}
|
||||
|
||||
string vcDir = this.rootPath + Path.DirectorySeparatorChar + dsName + Path.DirectorySeparatorChar + "Visulization" + Path.DirectorySeparatorChar;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(vcDir) || !Directory.Exists(vcDir))
|
||||
{
|
||||
log.Here().Warning("The path of VCFilePath: " + vcDir + " doesn't exist.");
|
||||
return null;
|
||||
}
|
||||
|
||||
VisuliaztionImporter vImporter = new VisuliaztionImporter(vcDir);
|
||||
|
||||
List<VisulizationConfig> vcList = vImporter.GetVisuliaztionConfigs();
|
||||
|
||||
log.Here().Information("Visulization Config data has been parsed from Files.");
|
||||
|
||||
return vcList;
|
||||
}
|
||||
|
||||
public ( List<NLUIntentRule>, List<EntityData>, List<EntityAttributeData> ) LoadNLU(string dsName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dsName))
|
||||
{
|
||||
log.Here().Warning("The datastore: " + dsName + " doesn't exist.");
|
||||
return (null, null, null);
|
||||
}
|
||||
|
||||
string nluPath = this.rootPath + Path.DirectorySeparatorChar + dsName + Path.DirectorySeparatorChar + "NLU" + Path.DirectorySeparatorChar;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(nluPath) || !Directory.Exists(nluPath))
|
||||
{
|
||||
log.Here().Warning("The path of NLUFilePath: " + nluPath + " doesn't exist.");
|
||||
return (null, null, null);
|
||||
}
|
||||
|
||||
log.Here().Information("NLUFilePath: " + nluPath);
|
||||
|
||||
NLUDataImporter importer = new NLUDataImporter(nluPath);
|
||||
|
||||
List<NLUIntentRule> iList = importer.ParseIntentRules();
|
||||
List<EntityData> eList = importer.ParseEntityData();
|
||||
List<EntityAttributeData> eaList = importer.ParseEntityAttributeData();
|
||||
|
||||
return (iList, eList, eaList);
|
||||
}
|
||||
|
||||
public (List<Vertex>, List<Edge>, List<VisulizationConfig>, List<NLUIntentRule>, List<EntityData>, List<EntityAttributeData>) Load(string dsName)
|
||||
{
|
||||
(var vList, var eList) = LoadKG(dsName);
|
||||
|
||||
var vcList = this.LoadConfig(dsName);
|
||||
|
||||
(var iList, var enList, var eaList) = this.LoadNLU(dsName);
|
||||
|
||||
return (vList, eList, vcList, iList, enList, eaList);
|
||||
}
|
||||
|
||||
public List<string> GetDataStoreList()
|
||||
{
|
||||
List<string> list = new List<string>();
|
||||
string[] directories = Directory.GetDirectories(rootPath);
|
||||
|
||||
foreach(string dir in directories)
|
||||
{
|
||||
string subDir = dir.Replace(rootPath, "");
|
||||
subDir = subDir.Replace(Path.DirectorySeparatorChar.ToString(), "");
|
||||
|
||||
list.Add(subDir);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool AddDataStore(string user, string datastoreName)
|
||||
{
|
||||
string targetDir = this.rootPath + Path.DirectorySeparatorChar + datastoreName;
|
||||
|
||||
if (Directory.Exists(targetDir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
|
||||
string real_targetDir = this.rootPath + Path.DirectorySeparatorChar + user + Path.DirectorySeparatorChar + datastoreName;
|
||||
Directory.CreateDirectory(real_targetDir);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DeleteDataStore(string user, string datastoreName)
|
||||
{
|
||||
string targetDir = this.rootPath + Path.DirectorySeparatorChar + datastoreName;
|
||||
if (!Directory.Exists(targetDir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
string real_targetDir = this.rootPath + Path.DirectorySeparatorChar + user + Path.DirectorySeparatorChar + datastoreName;
|
||||
if (!Directory.Exists(real_targetDir))
|
||||
return false;
|
||||
else
|
||||
return DeleteDir(targetDir);
|
||||
}
|
||||
}
|
||||
|
||||
private bool DeleteDir(string targetDir)
|
||||
{
|
||||
System.IO.DirectoryInfo di = new DirectoryInfo(targetDir);
|
||||
|
||||
try
|
||||
{
|
||||
foreach (FileInfo file in di.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
foreach (DirectoryInfo dir in di.GetDirectories())
|
||||
{
|
||||
dir.Delete(true);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
log.Error(e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
Directory.Delete(targetDir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateColorConfig(string user, string dsName, string scenarioName, List<ColorConfig> colorConfigs)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dsName))
|
||||
{
|
||||
log.Here().Error("Error: The datastore: " + dsName + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
log.Here().Error("Error: The scenario: " + scenarioName + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
string vcDir = this.rootPath + Path.DirectorySeparatorChar + dsName + Path.DirectorySeparatorChar ;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(vcDir) || !Directory.Exists(vcDir))
|
||||
{
|
||||
log.Here().Warning("The path of VCFilePath: " + vcDir + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
string vcPath = vcDir + "Visulization" + Path.DirectorySeparatorChar + "VisulizationConfig_" + scenarioName + ".json";
|
||||
|
||||
//VisuliaztionImporter vImporter = new VisuliaztionImporter(vcPath);
|
||||
List<VisulizationConfig> vcList = new List<VisulizationConfig>();
|
||||
|
||||
if (File.Exists(vcPath))
|
||||
{
|
||||
string json = System.IO.File.ReadAllText(vcPath);
|
||||
vcList = JsonConvert.DeserializeObject<List<VisulizationConfig>>(json);
|
||||
}
|
||||
|
||||
bool replaced = false;
|
||||
foreach(VisulizationConfig config in vcList)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(config.scenario) || config.scenario != scenarioName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.labelsOfVertexes = colorConfigs;
|
||||
replaced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!replaced)
|
||||
{
|
||||
VisulizationConfig vc = new VisulizationConfig();
|
||||
vc.scenario = scenarioName;
|
||||
vc.labelsOfVertexes = colorConfigs;
|
||||
|
||||
vcList.Add(vc);
|
||||
}
|
||||
|
||||
using (StreamWriter file = File.CreateText(vcPath))
|
||||
{
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
|
||||
serializer.Serialize(file, vcList);
|
||||
}
|
||||
|
||||
log.Here().Information("Visulization Config data has been parsed from Files.");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace SmartKG.Common.DataPersistence
|
||||
{
|
||||
public interface IDataAccessor
|
||||
{
|
||||
(List<Vertex>, List<Edge>) LoadKG(string datastoreName);
|
||||
List<VisulizationConfig> LoadConfig(string datastoreName);
|
||||
(List<NLUIntentRule>, List<EntityData>, List<EntityAttributeData>) LoadNLU(string datastoreName);
|
||||
|
||||
(List<Vertex>, List<Edge>, List<VisulizationConfig>, List<NLUIntentRule>, List<EntityData>, List<EntityAttributeData>) Load(string location);
|
||||
|
||||
List<string> GetDataStoreList();
|
||||
|
||||
bool AddDataStore(string user, string dsName);
|
||||
|
||||
bool DeleteDataStore(string user, string dsName);
|
||||
|
||||
bool UpdateColorConfig(string user, string dsName, string scenarioName, List<ColorConfig> colorConfigs);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using SmartKG.Common.DataPersistence;
|
||||
using SmartKG.Common.Logger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace SmartKG.Common.DataPersistance
|
||||
{
|
||||
public class MongoDataAccessor : IDataAccessor
|
||||
{
|
||||
|
||||
private ILogger log;
|
||||
|
||||
private MongoClient client;
|
||||
|
||||
private string mgmtDatabaseName;
|
||||
|
||||
private string connectionString;
|
||||
|
||||
public MongoDataAccessor(string connectionString, string mgmtDatabaseName)
|
||||
{
|
||||
this.log = Log.Logger.ForContext<MongoDataAccessor>();
|
||||
|
||||
this.connectionString = connectionString;
|
||||
this.client = new MongoClient(new MongoUrl(this.connectionString));
|
||||
|
||||
this.mgmtDatabaseName = mgmtDatabaseName;
|
||||
}
|
||||
|
||||
public (List<Vertex>, List<Edge>) LoadKG(string dbName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dbName))
|
||||
{
|
||||
log.Here().Warning("The database: " + dbName + " doesn't exist.");
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
BsonDocument allFilter = new BsonDocument();
|
||||
|
||||
IMongoDatabase db = this.client.GetDatabase(dbName);
|
||||
|
||||
Console.WriteLine("Database Name: " + dbName);
|
||||
|
||||
IMongoCollection<Vertex> vCollection = db.GetCollection<Vertex>("Vertexes");
|
||||
|
||||
List<Vertex> vList = vCollection.Find(allFilter).ToList();
|
||||
|
||||
IMongoCollection<Edge> eCollection = db.GetCollection<Edge>("Edges");
|
||||
|
||||
List<Edge> eList = eCollection.Find(allFilter).ToList();
|
||||
|
||||
log.Here().Information("KG data has been parsed from MongoDB.");
|
||||
|
||||
return (vList, eList);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.Here().Warning("Fail to parse KG data.\n" + e.Message);
|
||||
return (null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public List<VisulizationConfig> LoadConfig(string dbName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dbName))
|
||||
{
|
||||
log.Here().Warning("The database: " + dbName + " doesn't exist.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IMongoDatabase db = this.client.GetDatabase(dbName);
|
||||
IMongoCollection<VisulizationConfig> vcCollection = db.GetCollection<VisulizationConfig>("VisulizationConfigs");
|
||||
BsonDocument allFilter = new BsonDocument();
|
||||
|
||||
List<VisulizationConfig> vcList = vcCollection.Find(allFilter).ToList();
|
||||
log.Here().Information("Visulization Config data has been parsed from MongoDB.");
|
||||
|
||||
return vcList;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.Here().Warning("Fail to parse Visulization Config data.\n" + e.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public (List<NLUIntentRule>, List<EntityData>, List<EntityAttributeData>) LoadNLU(string dbName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dbName))
|
||||
{
|
||||
log.Here().Warning("The database: " + dbName + " doesn't exist.");
|
||||
return (null, null, null);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
BsonDocument allFilter = new BsonDocument();
|
||||
IMongoDatabase db = client.GetDatabase(dbName);
|
||||
|
||||
IMongoCollection<NLUIntentRule> iCollection = db.GetCollection<NLUIntentRule>("IntentRules");
|
||||
List<NLUIntentRule> iList = iCollection.Find(allFilter).ToList();
|
||||
|
||||
IMongoCollection<EntityData> eCollection = db.GetCollection<EntityData>("Entities");
|
||||
List<EntityData> eList = eCollection.Find(allFilter).ToList();
|
||||
|
||||
IMongoCollection<EntityAttributeData> eaCollection = db.GetCollection<EntityAttributeData>("EntityAttributes");
|
||||
List<EntityAttributeData> eaList = eaCollection.Find(allFilter).ToList();
|
||||
|
||||
log.Here().Information("NLU Data has been parsed from MongoDB.");
|
||||
|
||||
if (iList != null && iList.Count == 0)
|
||||
iList = null;
|
||||
|
||||
if (eList != null && eList.Count == 0)
|
||||
eList = null;
|
||||
|
||||
if (eaList != null && eaList.Count == 0)
|
||||
eaList = null;
|
||||
|
||||
return (iList, eList, eaList);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.Here().Warning("Fail to parse NLU data.\n" + e.Message);
|
||||
return (null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public (List<Vertex>, List<Edge>, List<VisulizationConfig>, List<NLUIntentRule>, List<EntityData>, List<EntityAttributeData>) Load(string dbName)
|
||||
{
|
||||
(var vList, var eList) = this.LoadKG(dbName);
|
||||
|
||||
var vcList = this.LoadConfig(dbName);
|
||||
|
||||
(var iList, var enList, var eaList) = this.LoadNLU(dbName);
|
||||
|
||||
return (vList, eList, vcList, iList, enList, eaList);
|
||||
}
|
||||
|
||||
public List<string> GetDataStoreList()
|
||||
{
|
||||
BsonDocument allFilter = new BsonDocument();
|
||||
IMongoDatabase db = client.GetDatabase(this.mgmtDatabaseName);
|
||||
|
||||
IMongoCollection<DatastoreItem> collection = db.GetCollection<DatastoreItem>("DataStores");
|
||||
List<DatastoreItem> list = collection.Find(allFilter).ToList();
|
||||
|
||||
List<string> result = new List<string>();
|
||||
|
||||
foreach(DatastoreItem item in list)
|
||||
{
|
||||
result.Add(item.name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool IsDataStoreExist(string datastoreName)
|
||||
{
|
||||
IMongoDatabase db = client.GetDatabase(this.mgmtDatabaseName);
|
||||
IMongoCollection<DatastoreItem> collection = db.GetCollection<DatastoreItem>("DataStores");
|
||||
|
||||
var searchFilter = Builders<DatastoreItem>.Filter.Eq("name", datastoreName);
|
||||
|
||||
var results = collection.Find(searchFilter).ToList();
|
||||
|
||||
if (results.Count > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AddDataStore(string user, string datastoreName)
|
||||
{
|
||||
if (IsDataStoreExist(datastoreName))
|
||||
return false;
|
||||
|
||||
DatastoreItem item = new DatastoreItem();
|
||||
item.name = datastoreName;
|
||||
item.creator = user;
|
||||
|
||||
IMongoDatabase db = client.GetDatabase(this.mgmtDatabaseName);
|
||||
IMongoCollection<DatastoreItem> collection = db.GetCollection<DatastoreItem>("DataStores");
|
||||
|
||||
collection.InsertOne(item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsDataStoreCreatedByUser(string user, string datastoreName)
|
||||
{
|
||||
if (!IsDataStoreExist(datastoreName))
|
||||
return false;
|
||||
|
||||
IMongoDatabase db = client.GetDatabase(this.mgmtDatabaseName);
|
||||
IMongoCollection<DatastoreItem> collection = db.GetCollection<DatastoreItem>("DataStores");
|
||||
|
||||
var deleteFilter = Builders<DatastoreItem>.Filter.Eq("name", datastoreName);
|
||||
|
||||
var results = collection.Find(deleteFilter).ToList();
|
||||
|
||||
if (results.Count == 0)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(user))
|
||||
return true;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(results[0].creator))
|
||||
return true;
|
||||
|
||||
if (results[0].creator != user)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeleteDataStore(string user, string datastoreName)
|
||||
{
|
||||
if (!IsDataStoreCreatedByUser(user, datastoreName))
|
||||
return false;
|
||||
|
||||
var deleteFilter = Builders<DatastoreItem>.Filter.Eq("name", datastoreName);
|
||||
|
||||
IMongoDatabase db = client.GetDatabase(this.mgmtDatabaseName);
|
||||
IMongoCollection<DatastoreItem> collection = db.GetCollection<DatastoreItem>("DataStores");
|
||||
collection.DeleteOne(deleteFilter);
|
||||
client.DropDatabase(datastoreName);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateColorConfig(string user, string dsName, string scenarioName, List<ColorConfig> colorConfigs)
|
||||
{
|
||||
if (!IsDataStoreExist(dsName))
|
||||
return false;
|
||||
|
||||
IMongoDatabase db = client.GetDatabase(dsName);
|
||||
IMongoCollection<VisulizationConfig> collection = db.GetCollection<VisulizationConfig>("VisulizationConfigs");
|
||||
|
||||
var deleteFilter = Builders<VisulizationConfig>.Filter.Eq("scenario", scenarioName);
|
||||
collection.DeleteOne(deleteFilter);
|
||||
|
||||
VisulizationConfig vConfig = new VisulizationConfig();
|
||||
vConfig.scenario = scenarioName;
|
||||
vConfig.labelsOfVertexes = colorConfigs;
|
||||
|
||||
collection.InsertOne(vConfig);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SmartKG.Common.Logger;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data;
|
||||
|
||||
namespace SmartKG.Common.DataStoreMgmt
|
||||
{
|
||||
public class DataStoreFrame
|
||||
{
|
||||
private string datastoreName;
|
||||
private KnowledgeGraphDataFrame kgDF;
|
||||
private KGConfigFrame kgConfigFrame;
|
||||
private NLUDataFrame nluDF;
|
||||
|
||||
private ILogger log;
|
||||
|
||||
public DataStoreFrame(string datastoreName, KnowledgeGraphDataFrame kgDF, KGConfigFrame kgConfigFrame, NLUDataFrame nluDF)
|
||||
{
|
||||
log = Log.Logger.ForContext<DataStoreFrame>();
|
||||
this.datastoreName = datastoreName;
|
||||
this.kgDF = kgDF; //new KnowledgeGraphDataFrame();
|
||||
this.kgConfigFrame = kgConfigFrame;
|
||||
this.nluDF = nluDF; // new NLUDataFrame();
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return this.datastoreName;
|
||||
}
|
||||
|
||||
public KnowledgeGraphDataFrame GetKG()
|
||||
{
|
||||
return this.kgDF;
|
||||
}
|
||||
|
||||
public KGConfigFrame GetKGConfig()
|
||||
{
|
||||
return this.kgConfigFrame;
|
||||
}
|
||||
|
||||
public NLUDataFrame GetNLU()
|
||||
{
|
||||
return this.nluDF;
|
||||
}
|
||||
|
||||
public void LogInformation(ILogger log, string title, string content)
|
||||
{
|
||||
log.Information(title + " " + content);
|
||||
}
|
||||
|
||||
public void LogError(ILogger log, Exception e)
|
||||
{
|
||||
log.Error(e.Message, e);
|
||||
}
|
||||
|
||||
public int GetMaxOptions(string scenarioName)
|
||||
{
|
||||
|
||||
return this.nluDF.GetSetting(scenarioName).maxOptions;
|
||||
}
|
||||
|
||||
public SortSetting GetSortSetting(string scenarioName)
|
||||
{
|
||||
return this.nluDF.GetSetting(scenarioName).sortSetting;
|
||||
}
|
||||
|
||||
public List<DialogSlot> GetConfiguredSlots(string scenarioName)
|
||||
{
|
||||
if (this.nluDF.GetSetting(scenarioName) != null)
|
||||
return this.nluDF.GetSetting(scenarioName).slots;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Vertex> SearchGraphByLabel(string label, string scenarioName, List<AttributePair> attributes)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(label))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Vertex> vertexes = kgDF.GetVertexByLabel(label);
|
||||
return Filter(vertexes, scenarioName, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
public Vertex SearchGraph(string startVertexName, string scenarioName, List<AttributePair> attributes)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startVertexName) && string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(startVertexName) && !string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
Vertex root = nluDF.GetRoot(scenarioName);
|
||||
if (root != null)
|
||||
{
|
||||
startVertexName = root.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<Vertex> vertexes = kgDF.GetVertexByName(startVertexName);
|
||||
|
||||
List<Vertex> results = Filter(vertexes, scenarioName, attributes);
|
||||
|
||||
if (results != null && results.Count > 0)
|
||||
{
|
||||
return results[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Vertex> Filter(List<Vertex> vertexes, string scenarioName, List<AttributePair> attributes)
|
||||
{
|
||||
|
||||
if (vertexes != null)
|
||||
{
|
||||
List<Vertex> results = new List<Vertex>();
|
||||
foreach (Vertex vertex in vertexes)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(scenarioName) && (vertex.scenarios != null && !vertex.scenarios.Contains(scenarioName)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (IsSelected(vertex, attributes))
|
||||
{
|
||||
results.Add(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.Count > 0)
|
||||
{
|
||||
return results;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInformation(log.Here(), "Vertexes", "doesn't filtered with attributes: " + JsonConvert.SerializeObject(attributes));
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Dictionary<string, List<Vertex>> FilterGraph(string startVertexName, string scenarioName, HashSet<string> relationTypeSet, List<AttributePair> attributes)
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(startVertexName) && string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(startVertexName) && !string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
Vertex root = nluDF.GetRoot(scenarioName);
|
||||
if (root != null)
|
||||
{
|
||||
startVertexName = root.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Dictionary<string, List<Vertex>> results = new Dictionary<string, List<Vertex>>();
|
||||
|
||||
Vertex startVertex = SearchGraph(startVertexName, scenarioName, attributes);
|
||||
|
||||
if (startVertex == null)
|
||||
{
|
||||
LogInformation(log.Here(), startVertexName, "doesn't exist");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Vertex> tobeProcessedVertexes = new List<Vertex>();
|
||||
tobeProcessedVertexes.Add(startVertex);
|
||||
|
||||
int index = 0;
|
||||
|
||||
while (index < tobeProcessedVertexes.Count())
|
||||
{
|
||||
Vertex vertex = tobeProcessedVertexes[index];
|
||||
|
||||
|
||||
Dictionary<string, HashSet<string>> childrenIds = new Dictionary<string, HashSet<string>>();
|
||||
|
||||
if (relationTypeSet == null)
|
||||
{
|
||||
childrenIds = kgDF.GetChildrenIds(vertex.id, null, scenarioName);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string relationType in relationTypeSet)
|
||||
{
|
||||
Dictionary<string, HashSet<string>> cIds = kgDF.GetChildrenIds(vertex.id, relationType, scenarioName);
|
||||
if (cIds != null && cIds.Count > 0)
|
||||
{
|
||||
childrenIds.Add(relationType, cIds[relationType]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (childrenIds == null)
|
||||
continue;
|
||||
|
||||
foreach (string relationType in childrenIds.Keys)
|
||||
{
|
||||
foreach (string childId in childrenIds[relationType])
|
||||
{
|
||||
Vertex child = kgDF.GetVertexById(childId);
|
||||
if (child != null)
|
||||
{
|
||||
if (child.isLeaf())
|
||||
{
|
||||
if (IsSelected(child, attributes))
|
||||
{
|
||||
if (results.ContainsKey(relationType))
|
||||
{
|
||||
results[relationType].Add(child);
|
||||
}
|
||||
else
|
||||
{
|
||||
results.Add(relationType, new List<Vertex> { vertex });
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tobeProcessedVertexes.Add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private bool IsSelected(Vertex vertex, List<AttributePair> attributes)
|
||||
{
|
||||
|
||||
bool isSelected = true;
|
||||
|
||||
if (attributes == null || attributes.Count() == 0)
|
||||
return true;
|
||||
|
||||
foreach (AttributePair attribute in attributes)
|
||||
{
|
||||
string attributeValue = attribute.attributeValue;
|
||||
try
|
||||
{
|
||||
string value = vertex.GetPropertyValue(attribute.attributeName);
|
||||
if ((value != null) && (value != "ALL") && (attributeValue != "ALL") && (attributeValue != value))
|
||||
{
|
||||
isSelected = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogError(log.Here(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
public Dictionary<string, List<Vertex>> GetChildren(Vertex vertex, HashSet<string> relationTypeSet, List<AttributePair> attributes, string scenarioName)
|
||||
{
|
||||
if (vertex.isLeaf())
|
||||
{
|
||||
LogInformation(log.Here(), vertex.name, "is a leaf");
|
||||
return null;
|
||||
}
|
||||
|
||||
string id = vertex.id;
|
||||
|
||||
Dictionary<string, HashSet<string>> childrenIds = new Dictionary<string, HashSet<string>>();
|
||||
|
||||
if (relationTypeSet != null)
|
||||
{
|
||||
foreach (string relationType in relationTypeSet)
|
||||
{
|
||||
Dictionary<string, HashSet<string>> cIds = kgDF.GetChildrenIds(vertex.id, relationType, scenarioName);//allTypeChildrenIds.SelectMany(x => x.Value).ToList();
|
||||
if (cIds != null && cIds.Count > 0)
|
||||
{
|
||||
|
||||
childrenIds.Add(relationType, cIds[relationType]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
childrenIds = kgDF.GetChildrenIds(vertex.id, null, scenarioName);
|
||||
}
|
||||
|
||||
|
||||
if (childrenIds == null || childrenIds.Count == 0)
|
||||
{
|
||||
LogInformation(log.Here(), vertex.name, "has no child");
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<string, List<Vertex>> results = new Dictionary<string, List<Vertex>>();
|
||||
foreach (string relationType in childrenIds.Keys)
|
||||
{
|
||||
List<Vertex> vertexes = new List<Vertex>();
|
||||
|
||||
foreach (string cId in childrenIds[relationType])
|
||||
{
|
||||
Vertex child = kgDF.GetVertexById(cId);
|
||||
if (child != null && IsSelected(child, attributes))
|
||||
vertexes.Add(child);
|
||||
}
|
||||
|
||||
if (vertexes.Count > 0)
|
||||
{
|
||||
results.Add(relationType, vertexes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MongoDB.Bson.Serialization.IdGenerators;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data;
|
||||
using SmartKG.Common.Data.Configuration;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using SmartKG.Common.DataPersistence;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace SmartKG.Common.DataStoreMgmt
|
||||
{
|
||||
public class DataStoreManager
|
||||
{
|
||||
private static DataStoreManager uniqueInstance;
|
||||
|
||||
private Dictionary<string, DataStoreFrame> datastoreDict;
|
||||
|
||||
private ILogger log;
|
||||
|
||||
private DataLoader dataLoader;
|
||||
|
||||
private DataStoreManager(IConfiguration config)
|
||||
{
|
||||
log = Log.Logger.ForContext<DataStoreManager>();
|
||||
this.datastoreDict = new Dictionary<string, DataStoreFrame>();
|
||||
|
||||
this.dataLoader = new DataLoader(config);
|
||||
}
|
||||
|
||||
public static DataStoreManager initInstance(IConfiguration config)
|
||||
{
|
||||
if (uniqueInstance == null)
|
||||
{
|
||||
uniqueInstance = new DataStoreManager(config);
|
||||
}
|
||||
return uniqueInstance;
|
||||
}
|
||||
|
||||
public static DataStoreManager GetInstance()
|
||||
{
|
||||
return uniqueInstance;
|
||||
}
|
||||
|
||||
public bool CreateDataStore(string user, string dsName)
|
||||
{
|
||||
return this.dataLoader.CreateDataStore(user, dsName);
|
||||
}
|
||||
|
||||
public bool DeleteDataStore(string user, string dsName)
|
||||
{
|
||||
bool success = this.dataLoader.DeleteDataStore(user, dsName);
|
||||
|
||||
if (success)
|
||||
{
|
||||
this.datastoreDict.Remove(dsName);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public List<string> GetDataStoreList()
|
||||
{
|
||||
return this.dataLoader.GetDataStoreList();
|
||||
}
|
||||
|
||||
public void LoadDataStores()
|
||||
{
|
||||
List<DataStoreFrame> datastores = this.dataLoader.Load();
|
||||
|
||||
int count = 0;
|
||||
foreach(DataStoreFrame dsFrame in datastores)
|
||||
{
|
||||
bool success;
|
||||
|
||||
(success, _)= this.SaveDataStoreInDict(dsFrame);
|
||||
|
||||
if (success)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
log.Information("Totally " + count + " datastores have been loaded.");
|
||||
}
|
||||
|
||||
public (bool, string) LoadDataStore(string dsName)
|
||||
{
|
||||
DataStoreFrame dsFrame = this.dataLoader.LoadDataStore(dsName);
|
||||
return this.SaveDataStoreInDict(dsFrame);
|
||||
}
|
||||
|
||||
private (bool, string) SaveDataStoreInDict(DataStoreFrame dsFrame)
|
||||
{
|
||||
if (dsFrame == null)
|
||||
{
|
||||
log.Error("Error: DataStoreFrame doesn't exist.");
|
||||
return (false, "DataStoreFrame doesn't exist.");
|
||||
}
|
||||
|
||||
string dsName = dsFrame.GetName();
|
||||
|
||||
if (dsFrame.GetKG().GetAllVertexes().Count == 0)
|
||||
{
|
||||
log.Error("Error: DataStoreFrame " + dsName + " is empty.");
|
||||
return (false, "DataStoreFrame " + dsName + " is empty.");
|
||||
}
|
||||
|
||||
if (this.datastoreDict.ContainsKey(dsName))
|
||||
{
|
||||
log.Warning("Warning: DataStore Name cannot be duplicated. The " + dsName + " has existed.");
|
||||
this.datastoreDict[dsName] = dsFrame;
|
||||
log.Information("The " + dsName + " has been reloaded.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.datastoreDict.Add(dsName, dsFrame);
|
||||
log.Information("The " + dsName + " has been loaded now.");
|
||||
}
|
||||
|
||||
return (true, "The " + dsName + " has been loaded.");
|
||||
}
|
||||
|
||||
public DataStoreFrame GetDataStore(string dsName)
|
||||
{
|
||||
if (this.datastoreDict.ContainsKey(dsName))
|
||||
{
|
||||
return this.datastoreDict[dsName];
|
||||
}
|
||||
|
||||
log.Error("The " + dsName + " doesn't existed.");
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetUploadedFileSaveDir()
|
||||
{
|
||||
FileUploadConfig uploadConfig = this.dataLoader.GetUploadConfig();
|
||||
string excelDir = uploadConfig.ExcelDir;
|
||||
|
||||
return excelDir;
|
||||
}
|
||||
|
||||
public PersistanceType GetPersistanceType()
|
||||
{
|
||||
return this.dataLoader.GetPersistanceType();
|
||||
}
|
||||
|
||||
public string GetSavedExcelFilePath(string savedFileName)
|
||||
{
|
||||
FileUploadConfig uploadConfig = this.dataLoader.GetUploadConfig();
|
||||
|
||||
string excelDir = uploadConfig.ExcelDir;
|
||||
|
||||
|
||||
string savedExcelFilePath = excelDir + Path.DirectorySeparatorChar + savedFileName ;
|
||||
|
||||
return savedExcelFilePath;
|
||||
}
|
||||
|
||||
public (string, string) GetTargetDirPath(string datastoreName)
|
||||
{
|
||||
FileUploadConfig uploadConfig = this.dataLoader.GetUploadConfig();
|
||||
PersistanceType persistanceType = this.dataLoader.GetPersistanceType();
|
||||
FilePathConfig filePathConfig = this.dataLoader.GetFilePathConfig();
|
||||
|
||||
string configPath = uploadConfig.ColorConfigPath;
|
||||
|
||||
string targetDir = null;
|
||||
|
||||
if (persistanceType == PersistanceType.File && filePathConfig != null)
|
||||
{
|
||||
targetDir = filePathConfig.RootPath + Path.DirectorySeparatorChar + datastoreName;
|
||||
}
|
||||
else
|
||||
{
|
||||
string excelDir = uploadConfig.ExcelDir;
|
||||
targetDir = excelDir + Path.DirectorySeparatorChar + DateTime.Now.ToString("MMddyyyyHHmmss");
|
||||
}
|
||||
|
||||
return (configPath, targetDir);
|
||||
}
|
||||
|
||||
|
||||
public (FileUploadConfig, string, string) GenerateConvertDirs(string datastoreName, string savedFileName, string scenario)
|
||||
{
|
||||
FileUploadConfig uploadConfig = this.dataLoader.GetUploadConfig();
|
||||
PersistanceType persistanceType = this.dataLoader.GetPersistanceType();
|
||||
FilePathConfig filePathConfig = this.dataLoader.GetFilePathConfig();
|
||||
|
||||
string excelDir = uploadConfig.ExcelDir;
|
||||
|
||||
string pythonArgs = "--configPath \"" + uploadConfig.ColorConfigPath + "\" ";
|
||||
|
||||
pythonArgs += " --srcPaths ";
|
||||
|
||||
pythonArgs += "\"" + excelDir + Path.DirectorySeparatorChar + savedFileName + "\" ";
|
||||
|
||||
|
||||
pythonArgs += " --scenarios ";
|
||||
|
||||
|
||||
pythonArgs += "\"" + scenario + "\" ";
|
||||
|
||||
string targetDir = null;
|
||||
|
||||
if (persistanceType == PersistanceType.File && filePathConfig != null)
|
||||
{
|
||||
targetDir = filePathConfig.RootPath + Path.DirectorySeparatorChar + datastoreName;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetDir = excelDir + Path.DirectorySeparatorChar + DateTime.Now.ToString("MMddyyyyHHmmss");
|
||||
}
|
||||
|
||||
pythonArgs += " --destPath \"" + targetDir + "\" ";
|
||||
|
||||
return (uploadConfig, pythonArgs, targetDir);
|
||||
}
|
||||
|
||||
public bool UpdateColorConfig(string user, string dsName, string scenarioName, List<ColorConfig> colorConfigs)
|
||||
{
|
||||
return this.dataLoader.UpdateColorConfig(user, dsName, scenarioName, colorConfigs);
|
||||
}
|
||||
|
||||
public int GetMaxDisplayedEntityNumber()
|
||||
{
|
||||
return this.dataLoader.GetMaxDisplayedEntityNumber();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SmartKG.Common.DataStoreMgmt
|
||||
{
|
||||
public class KGConfigFrame
|
||||
{
|
||||
private Dictionary<string, List<ColorConfig>> vertexLabelColorMap { get; set; }
|
||||
private ILogger log;
|
||||
public KGConfigFrame()
|
||||
{
|
||||
log = Log.Logger.ForContext<KGConfigFrame>();
|
||||
this.Clean();
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
this.vertexLabelColorMap = new Dictionary<string, List<ColorConfig>>();
|
||||
}
|
||||
|
||||
public void SetVertexLabelColorMap(Dictionary<string, List<ColorConfig>> map)
|
||||
{
|
||||
this.vertexLabelColorMap = map;
|
||||
}
|
||||
|
||||
/*public Dictionary<string, List<ColorConfig>> GetVertexLabelColorMap()
|
||||
{
|
||||
return this.vertexLabelColorMap;
|
||||
}*/
|
||||
|
||||
public (bool, List<ColorConfig>) GetColorConfigForScenario(string scenarioName)
|
||||
{
|
||||
if (this.vertexLabelColorMap == null || this.vertexLabelColorMap.Count == 0)
|
||||
{
|
||||
return (false, null);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(scenarioName))
|
||||
{
|
||||
List<ColorConfig> configs = new List<ColorConfig>();
|
||||
foreach (string scenario in this.vertexLabelColorMap.Keys)
|
||||
{
|
||||
configs.AddRange(this.vertexLabelColorMap[scenario]);
|
||||
}
|
||||
|
||||
return (true, configs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.vertexLabelColorMap.ContainsKey(scenarioName))
|
||||
{
|
||||
return (false, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (true, this.vertexLabelColorMap[scenarioName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public (bool, string) UpdateVertexLabelColorMapForScenario(string scenarioName, List<ColorConfig> colorConfigs)
|
||||
{
|
||||
if (this.vertexLabelColorMap == null || this.vertexLabelColorMap.Count == 0)
|
||||
{
|
||||
return (false, "The scenario " + scenarioName + " doesn't exist.");
|
||||
}
|
||||
|
||||
if (colorConfigs == null || colorConfigs.Count == 0)
|
||||
{
|
||||
return (false, "The color config of cannot be null.");
|
||||
}
|
||||
|
||||
if (this.vertexLabelColorMap == null)
|
||||
{
|
||||
this.vertexLabelColorMap = new Dictionary<string, List<ColorConfig>>();
|
||||
}
|
||||
|
||||
if (!this.vertexLabelColorMap.ContainsKey(scenarioName))
|
||||
{
|
||||
this.vertexLabelColorMap.Add(scenarioName, colorConfigs);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vertexLabelColorMap[scenarioName] = colorConfigs;
|
||||
}
|
||||
|
||||
return (true, "The scenario " + scenarioName + " color configs are updated successfully.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SmartKG.Common.DataStoreMgmt
|
||||
{
|
||||
public class KnowledgeGraphDataFrame
|
||||
{
|
||||
private Dictionary<string, List<Vertex>> vertexNameCache { get; set; }
|
||||
private Dictionary<string, Vertex> vertexIdCache { get; set; }
|
||||
private Dictionary<string, Dictionary<RelationLink, List<string>>> outRelationDict { get; set; }
|
||||
private Dictionary<string, Dictionary<RelationLink, List<string>>> inRelationDict { get; set; }
|
||||
|
||||
private Dictionary<string, List<Edge>> scenarioEdgesDict { get; set; }
|
||||
|
||||
//private Dictionary<string, List<ColorConfig>> vertexLabelColorMap { get; set; }
|
||||
|
||||
private List<Vertex> rootVertexes { get; set; }
|
||||
|
||||
private HashSet<string> scenarioNames { get; set; }
|
||||
|
||||
private ILogger log;
|
||||
|
||||
public KnowledgeGraphDataFrame()
|
||||
{
|
||||
log = Log.Logger.ForContext<KnowledgeGraphDataFrame>();
|
||||
this.Clean();
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
this.vertexNameCache = new Dictionary<string, List<Vertex>>();
|
||||
|
||||
this.vertexIdCache = new Dictionary<string, Vertex>();
|
||||
|
||||
this.outRelationDict = new Dictionary<string, Dictionary<RelationLink, List<string>>>();
|
||||
|
||||
this.inRelationDict = new Dictionary<string, Dictionary<RelationLink, List<string>>>();
|
||||
|
||||
this.scenarioEdgesDict = new Dictionary<string, List<Edge>>();
|
||||
|
||||
//this.vertexLabelColorMap = new Dictionary<string, List<ColorConfig>>();
|
||||
|
||||
this.rootVertexes = new List<Vertex>();
|
||||
|
||||
this.scenarioNames = new HashSet<string>();
|
||||
}
|
||||
|
||||
public void SetRootVertexes(List<Vertex> roots)
|
||||
{
|
||||
this.rootVertexes = roots;
|
||||
}
|
||||
|
||||
public List<Vertex> GetRootVertexes()
|
||||
{
|
||||
return this.rootVertexes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public HashSet<string> GetScenarioNames()
|
||||
{
|
||||
return this.scenarioNames;
|
||||
}
|
||||
|
||||
public void SetScenarioNames(HashSet<string> scenarios)
|
||||
{
|
||||
this.scenarioNames = scenarios;
|
||||
}
|
||||
|
||||
public void SetVertexNameCache(Dictionary<string, List<Vertex>> vertexNameCache)
|
||||
{
|
||||
this.vertexNameCache = vertexNameCache;
|
||||
}
|
||||
|
||||
public void SetVertexIdCache(Dictionary<string, Vertex> vertexIdCache)
|
||||
{
|
||||
this.vertexIdCache = vertexIdCache;
|
||||
}
|
||||
|
||||
public void SetOutRelationDict(Dictionary<string, Dictionary<RelationLink, List<string>>> outRelationDict)
|
||||
{
|
||||
this.outRelationDict = outRelationDict;
|
||||
}
|
||||
|
||||
public void SetInRelationDict(Dictionary<string, Dictionary<RelationLink, List<string>>> inRelationDict)
|
||||
{
|
||||
this.inRelationDict = inRelationDict;
|
||||
}
|
||||
|
||||
public List<Vertex> GetVertexByLabel(string label)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(label))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<Vertex> results = new List<Vertex>();
|
||||
|
||||
foreach (List<Vertex> vertexes in this.vertexNameCache.Values)
|
||||
{
|
||||
foreach (Vertex vertex in vertexes)
|
||||
{
|
||||
if (vertex.label.Contains(label))
|
||||
{
|
||||
results.Add(vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Vertex> GetVertexByName(string vertexName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(vertexName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.vertexNameCache.Keys.Contains(vertexName))
|
||||
{
|
||||
log.Information(vertexName, "doesn't exist");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.vertexNameCache[vertexName];
|
||||
}
|
||||
}
|
||||
|
||||
public List<Vertex> GetVertexByKeyword(string scenarioName, string keyword)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(keyword))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<string> vNames = this.vertexNameCache.Keys.ToList();
|
||||
|
||||
HashSet<string> matchedNames = new HashSet<string>();
|
||||
|
||||
foreach (string vName in vNames)
|
||||
{
|
||||
if (vName.Contains(keyword))
|
||||
{
|
||||
if (scenarioName != null)
|
||||
{
|
||||
foreach(Vertex v in this.vertexNameCache[vName])
|
||||
{
|
||||
if (v.scenarios.Contains(scenarioName))
|
||||
{
|
||||
matchedNames.Add(vName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
matchedNames.Add(vName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Vertex> results = new List<Vertex>();
|
||||
|
||||
foreach (string mV in matchedNames)
|
||||
{
|
||||
List<Vertex> mR = GetVertexByName(mV);
|
||||
if (mR != null && mR.Count > 0)
|
||||
{
|
||||
results.AddRange(mR);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
public (bool, List<Vertex>) GetVertexesByScenarios(List<string> scenarios)
|
||||
{
|
||||
List<Vertex> allVertexes = this.vertexIdCache.Values.ToList();
|
||||
|
||||
if (scenarios == null || scenarios.Count == 0)
|
||||
{
|
||||
return (true, allVertexes);
|
||||
}
|
||||
|
||||
bool isScenarioExist = false;
|
||||
|
||||
List<Vertex> catchedVertexes = new List<Vertex>();
|
||||
|
||||
foreach (Vertex vertex in allVertexes)
|
||||
{
|
||||
if (vertex.scenarios == null || vertex.scenarios.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string scenario in scenarios)
|
||||
{
|
||||
if (vertex.scenarios.Contains(scenario))
|
||||
{
|
||||
isScenarioExist = true;
|
||||
catchedVertexes.Add(vertex);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (isScenarioExist, catchedVertexes);
|
||||
}
|
||||
|
||||
public List<Edge> GetRelationsByScenarios(List<string> scenarios)
|
||||
{
|
||||
List<Edge> results = new List<Edge>();
|
||||
|
||||
if (scenarios == null || scenarios.Count == 0)
|
||||
{
|
||||
foreach (string key in this.scenarioEdgesDict.Keys)
|
||||
{
|
||||
results.AddRange(this.scenarioEdgesDict[key]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string scenario in scenarios)
|
||||
{
|
||||
if (this.scenarioEdgesDict.ContainsKey(scenario))
|
||||
{
|
||||
results.AddRange(this.scenarioEdgesDict[scenario]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public void SetScenarioEdgesDict(Dictionary<string, List<Edge>> scenarioEdgesDict)
|
||||
{
|
||||
this.scenarioEdgesDict = scenarioEdgesDict;
|
||||
}
|
||||
|
||||
public List<Vertex> GetAllVertexes()
|
||||
{
|
||||
return this.vertexIdCache.Values.ToList();
|
||||
}
|
||||
|
||||
public Vertex GetVertexById(string vertexId)
|
||||
{
|
||||
if (!this.vertexIdCache.Keys.Contains(vertexId))
|
||||
{
|
||||
log.Information(vertexId, "doesn't exist");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.vertexIdCache[vertexId];
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<RelationLink, List<string>> GetChildrenLinkDict(string vertexId)
|
||||
{
|
||||
if (vertexId != null && this.outRelationDict.ContainsKey(vertexId))
|
||||
{
|
||||
return this.outRelationDict[vertexId];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<RelationLink, List<string>> GetParentLinkDict(string vertexId)
|
||||
{
|
||||
if (vertexId != null && this.inRelationDict.ContainsKey(vertexId))
|
||||
{
|
||||
return this.inRelationDict[vertexId];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<string, HashSet<string>> GetChildrenIds(string vertexId, string relationType, string scenarioName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(vertexId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
RelationLink targetLink = new RelationLink(relationType, scenarioName);
|
||||
|
||||
Dictionary<string, HashSet<string>> childrenIds = new Dictionary<string, HashSet<string>>();
|
||||
|
||||
if (outRelationDict.ContainsKey(vertexId))
|
||||
{
|
||||
foreach (RelationLink link in outRelationDict[vertexId].Keys)
|
||||
{
|
||||
if (targetLink.IsCompatible(link))
|
||||
{
|
||||
string linkRelationType = link.relationType;
|
||||
|
||||
if (!childrenIds.ContainsKey(linkRelationType))
|
||||
{
|
||||
HashSet<string> cIds = new HashSet<string>();
|
||||
childrenIds.Add(linkRelationType, cIds);
|
||||
}
|
||||
|
||||
List<string> conncectedIds = outRelationDict[vertexId][link];
|
||||
foreach (string cid in conncectedIds)
|
||||
{
|
||||
childrenIds[linkRelationType].Add(cid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return childrenIds;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Serilog;
|
||||
|
||||
namespace SmartKG.Common.DataStoreMgmt
|
||||
{
|
||||
public class NLUDataFrame
|
||||
{
|
||||
private Dictionary<string, Dictionary<string, List<NLUEntity>>> standValueMap;
|
||||
|
||||
private Dictionary<string, Dictionary<string, Dictionary<string, NLUEntity>>> entityMap;
|
||||
private Dictionary<string, Dictionary<string, List<AttributePair>>> attributeMap;
|
||||
|
||||
private List<NLUIntentRule> intentPositiveDetermineRules;
|
||||
private Dictionary<string, List<NLUIntentRule>> intentNegativeDeterminRules;
|
||||
|
||||
private Dictionary<string, ScenarioSetting> sceanrioCache;
|
||||
private ILogger log;
|
||||
|
||||
public NLUDataFrame()
|
||||
{
|
||||
log = Log.Logger.ForContext<NLUDataFrame>();
|
||||
this.Clean();
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
this.standValueMap = new Dictionary<string, Dictionary<string, List<NLUEntity>>>();
|
||||
this.attributeMap = new Dictionary<string, Dictionary<string, List<AttributePair>>>();
|
||||
|
||||
this.entityMap = new Dictionary<string, Dictionary<string, Dictionary<string, NLUEntity>>>();
|
||||
this.intentPositiveDetermineRules = new List<NLUIntentRule>();
|
||||
this.intentNegativeDeterminRules = new Dictionary<string, List<NLUIntentRule>>();
|
||||
this.sceanrioCache = new Dictionary<string, ScenarioSetting>();
|
||||
}
|
||||
public NLUEntity AddEntity(string intentName, string entityValue, string entityType)
|
||||
{
|
||||
Dictionary<string, Dictionary<string, NLUEntity>> typeEntities;
|
||||
if (!this.entityMap.Keys.Contains(intentName))
|
||||
{
|
||||
typeEntities = new Dictionary<string, Dictionary<string, NLUEntity>>();
|
||||
this.entityMap.Add(intentName, typeEntities);
|
||||
}
|
||||
|
||||
typeEntities = this.entityMap[intentName];
|
||||
|
||||
|
||||
Dictionary<string, NLUEntity> entities;
|
||||
|
||||
|
||||
if (!typeEntities.Keys.Contains(entityType))
|
||||
{
|
||||
entities = new Dictionary<string, NLUEntity>();
|
||||
typeEntities.Add(entityType, entities);
|
||||
|
||||
}
|
||||
|
||||
entities = typeEntities[entityType];
|
||||
|
||||
|
||||
if (!entities.Keys.Contains(entityValue))
|
||||
{
|
||||
NLUEntity entity = new NLUEntity(entityValue, entityType);
|
||||
|
||||
entities.Add(entityValue, entity);
|
||||
return entity;
|
||||
}
|
||||
else
|
||||
{
|
||||
return entities[entityValue];
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSimilarWord(string intentName, string similarWord, NLUEntity entity)
|
||||
{
|
||||
if (!this.standValueMap.Keys.Contains(intentName))
|
||||
{
|
||||
Dictionary<string, List<NLUEntity>> wordToEntity = new Dictionary<string, List<NLUEntity>>();
|
||||
this.standValueMap.Add(intentName, wordToEntity);
|
||||
}
|
||||
|
||||
if (this.standValueMap[intentName].Keys.Contains(similarWord))
|
||||
{
|
||||
this.standValueMap[intentName][similarWord].Add(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.standValueMap[intentName].Add(similarWord, new List<NLUEntity>() { entity });
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAttribute(string intentName, NLUEntity entity, AttributePair attribute)
|
||||
{
|
||||
if (!this.attributeMap.Keys.Contains(intentName))
|
||||
{
|
||||
Dictionary<string, List<AttributePair>> wordToAttribute = new Dictionary<string, List<AttributePair>>();
|
||||
this.attributeMap.Add(intentName, wordToAttribute);
|
||||
}
|
||||
|
||||
string key = entity.GetIdentity();
|
||||
|
||||
if (!this.attributeMap[intentName].Keys.Contains(key))
|
||||
{
|
||||
this.attributeMap[intentName].Add(key, new List<AttributePair>());
|
||||
}
|
||||
|
||||
this.attributeMap[intentName][key].Add(attribute);
|
||||
}
|
||||
|
||||
public List<NLUEntity> DetectEntities(string intentName, string query)
|
||||
{
|
||||
List<NLUEntity> resultList = new List<NLUEntity>();
|
||||
|
||||
if (!this.standValueMap.Keys.Contains(intentName))
|
||||
{
|
||||
return resultList;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SortedDictionary<int, List<NLUEntity>> results = new SortedDictionary<int, List<NLUEntity>>();
|
||||
|
||||
Dictionary<string, List<NLUEntity>> wordToEntity = this.standValueMap[intentName];
|
||||
|
||||
List<string> similarWords = wordToEntity.Keys.ToList<string>();
|
||||
|
||||
foreach (string word in similarWords)
|
||||
{
|
||||
string lowerWord = null;
|
||||
if (word != null)
|
||||
lowerWord = word.ToLower();
|
||||
|
||||
if (query.Contains(lowerWord))
|
||||
{
|
||||
int pos = query.IndexOf(lowerWord);
|
||||
|
||||
List<NLUEntity> entities = wordToEntity[word];
|
||||
|
||||
//int key = word.Length;
|
||||
|
||||
if (results.ContainsKey(pos))
|
||||
{
|
||||
results[pos].AddRange(entities.Select(item => item.Clone()).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
results.Add(pos, entities.Select(item => item.Clone()).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in results)//.Reverse())
|
||||
{
|
||||
resultList.AddRange(pair.Value);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("Parse entities error.", e);
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public List<AttributePair> ParseAttributes(string intentName, List<NLUEntity> entities)
|
||||
{
|
||||
if (entities == null || entities.Count() == 0)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
List<AttributePair> pairs = new List<AttributePair>();
|
||||
|
||||
Dictionary<string, List<AttributePair>> map = this.attributeMap[intentName];
|
||||
|
||||
foreach (NLUEntity entity in entities)
|
||||
{
|
||||
string identity = entity.GetIdentity();
|
||||
if (map.Keys.Contains(identity))
|
||||
{
|
||||
pairs.AddRange(map[identity]);
|
||||
}
|
||||
}
|
||||
|
||||
if (pairs.Count() > 0)
|
||||
{
|
||||
return pairs;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch { return null; }
|
||||
|
||||
}
|
||||
|
||||
public void AddIntentRule(NLUIntentRule intentRule)
|
||||
{
|
||||
if (intentRule.type == IntentRuleType.POSITIVE)
|
||||
this.intentPositiveDetermineRules.Add(intentRule);
|
||||
else if (intentRule.type == IntentRuleType.NEGATIVE)
|
||||
{
|
||||
string intentName = intentRule.intentName;
|
||||
|
||||
if (!this.intentNegativeDeterminRules.Keys.Contains(intentName))
|
||||
{
|
||||
this.intentNegativeDeterminRules.Add(intentName, new List<NLUIntentRule>());
|
||||
}
|
||||
|
||||
this.intentNegativeDeterminRules[intentName].Add(intentRule);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsMatched(List<string> ruleSecs, string query)
|
||||
{
|
||||
bool matched = true;
|
||||
foreach (string ruleSec in ruleSecs)
|
||||
{
|
||||
Regex regex = new Regex(ruleSec.ToLower());
|
||||
Match match = regex.Match(query);
|
||||
if (!match.Success)
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
private TempData MatchPositiveRules(string query, int startIndex)
|
||||
{
|
||||
TempData result = new TempData();
|
||||
|
||||
int index = startIndex;
|
||||
|
||||
while (index < this.intentPositiveDetermineRules.Count())
|
||||
{
|
||||
NLUIntentRule rule = this.intentPositiveDetermineRules[index];
|
||||
|
||||
bool matched = IsMatched(rule.ruleSecs, query);
|
||||
|
||||
if (matched)
|
||||
{
|
||||
result.intentName = rule.intentName;
|
||||
result.positionInPosRules = index;
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsNegative(string query, string intentName)
|
||||
{
|
||||
if (!this.intentNegativeDeterminRules.Keys.Contains(intentName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (NLUIntentRule rule in this.intentNegativeDeterminRules[intentName])
|
||||
{
|
||||
bool matched = IsMatched(rule.ruleSecs, query);
|
||||
|
||||
if (matched)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string DetectIntent(string query)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
while (index < this.intentPositiveDetermineRules.Count())
|
||||
{
|
||||
TempData temp = MatchPositiveRules(query, index);
|
||||
|
||||
if (temp == null)
|
||||
{
|
||||
index += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsNegative(query, temp.intentName))
|
||||
{
|
||||
index = temp.positionInPosRules + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return temp.intentName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetSceanrioCache(Dictionary<string, ScenarioSetting> sceanrioCache)
|
||||
{
|
||||
this.sceanrioCache = sceanrioCache;
|
||||
}
|
||||
|
||||
public ScenarioSetting GetSetting(string scenarioName)
|
||||
{
|
||||
if (!this.sceanrioCache.Keys.Contains(scenarioName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this.sceanrioCache[scenarioName];
|
||||
}
|
||||
|
||||
public Vertex GetRoot(string scenarioName)
|
||||
{
|
||||
if (this.sceanrioCache.ContainsKey(scenarioName))
|
||||
{
|
||||
return this.sceanrioCache[scenarioName].root;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TempData
|
||||
{
|
||||
public string intentName { get; set; }
|
||||
public int positionInPosRules { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace SmartKG.Common.Importer
|
||||
{
|
||||
public class KGDataImporter
|
||||
{
|
||||
private string rootPath;
|
||||
private List<string> vertexFileNames = new List<string>();
|
||||
private List<string> edgeFileNames = new List<string>();
|
||||
|
||||
private HashSet<string> vertexIds = new HashSet<string>();
|
||||
private HashSet<string> edgeIds = new HashSet<string>();
|
||||
|
||||
private ILogger log;
|
||||
|
||||
public KGDataImporter(string rootPath)
|
||||
{
|
||||
log = Log.Logger.ForContext<KGDataImporter>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rootPath))
|
||||
{
|
||||
throw new Exception("Rootpath of KG files are invalid.");
|
||||
}
|
||||
|
||||
this.rootPath = PathUtility.CompletePath(rootPath);
|
||||
|
||||
string[] files = Directory.GetFiles(rootPath, "*.json").Select(Path.GetFileName).ToArray();
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (file.Contains("Edge"))
|
||||
{
|
||||
this.edgeFileNames.Add(file);
|
||||
}
|
||||
else if (file.Contains("Vertex"))
|
||||
{
|
||||
this.vertexFileNames.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<Edge> ParseKGEdges()
|
||||
{
|
||||
List<Edge> edges = new List<Edge>();
|
||||
|
||||
foreach(string file in this.edgeFileNames)
|
||||
{
|
||||
edges.AddRange(ParseKGEdges(file));
|
||||
}
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
private List<Edge> ParseKGEdges(string filename)
|
||||
{
|
||||
List<Edge> output = new List<Edge>();
|
||||
|
||||
string fileName = rootPath + filename;
|
||||
string content = File.ReadAllText(fileName);
|
||||
|
||||
List<Edge> edges = JsonConvert.DeserializeObject<List<Edge>>(content);
|
||||
|
||||
foreach (Edge edge in edges)
|
||||
{
|
||||
output.Add(edge);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public List<Vertex> ParseKGVertexes()
|
||||
{
|
||||
List<Vertex> vertexes = new List<Vertex>();
|
||||
foreach(string file in this.vertexFileNames)
|
||||
{
|
||||
vertexes.AddRange(this.ParseKGVertexes(file));
|
||||
}
|
||||
return vertexes;
|
||||
}
|
||||
|
||||
private List<Vertex> ParseKGVertexes(string filename)
|
||||
{
|
||||
List<Vertex> output = new List<Vertex>();
|
||||
|
||||
string fileName = rootPath + filename;
|
||||
string content = File.ReadAllText(fileName);
|
||||
|
||||
List<Vertex> vertexes = JsonConvert.DeserializeObject<List<Vertex>>(content);
|
||||
|
||||
foreach (Vertex vertex in vertexes)
|
||||
{
|
||||
if (vertexIds.Contains(vertex.id))
|
||||
{
|
||||
Console.WriteLine(vertex.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexIds.Add(vertex.id);
|
||||
}
|
||||
|
||||
output.Add(vertex);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace SmartKG.Common.Importer
|
||||
{
|
||||
public class NLUDataImporter
|
||||
{
|
||||
private string rootPath;
|
||||
private ILogger log;
|
||||
|
||||
public NLUDataImporter(string rootPath)
|
||||
{
|
||||
log = Log.Logger.ForContext<NLUDataImporter>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rootPath))
|
||||
{
|
||||
throw new Exception("Rootpath of NLU files are invalid.");
|
||||
}
|
||||
|
||||
this.rootPath = PathUtility.CompletePath(rootPath);
|
||||
}
|
||||
|
||||
public List<NLUIntentRule> ParseIntentRules()
|
||||
{
|
||||
List<NLUIntentRule> list = new List<NLUIntentRule>();
|
||||
|
||||
string[] fileNamess = Directory.GetFiles(rootPath, "intentrules*.json").Select(Path.GetFileName).ToArray();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(this.rootPath + fileName);
|
||||
list.AddRange(JsonConvert.DeserializeObject<List<NLUIntentRule>>(content));
|
||||
}
|
||||
|
||||
/*List<string> lines = new List<string>();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(rootPath + fileName);
|
||||
lines.AddRange(content.Split('\n').ToList<string>());
|
||||
}
|
||||
|
||||
int seqNo = 1;
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
string theLine = line.Trim();
|
||||
|
||||
string[] tmps = theLine.Split('\t');
|
||||
|
||||
if (tmps.Count() != 3)
|
||||
{
|
||||
throw new Exception("invalid line in intentrules.tsv");
|
||||
}
|
||||
else
|
||||
{
|
||||
NLUIntentRule rule = new NLUIntentRule();
|
||||
rule.intentName = tmps[0].Trim();
|
||||
|
||||
string typeStr = tmps[1].Trim();
|
||||
|
||||
IntentRuleType type = IntentRuleType.POSITIVE;
|
||||
|
||||
if (typeStr == "NEGATIVE")
|
||||
{
|
||||
type = IntentRuleType.NEGATIVE;
|
||||
}
|
||||
|
||||
rule.type = type;
|
||||
|
||||
List<string> ruleSecs = tmps[2].Trim().Split(';').ToList();
|
||||
|
||||
rule.ruleSecs = ruleSecs;
|
||||
|
||||
rule.id = rule.intentName + "-" + seqNo.ToString();
|
||||
|
||||
seqNo += 1;
|
||||
|
||||
list.Add(rule);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<EntityData> ParseEntityData()
|
||||
{
|
||||
List<EntityData> list = new List<EntityData>();
|
||||
|
||||
string[] fileNamess = Directory.GetFiles(rootPath, "entitymap*.json").Select(Path.GetFileName).ToArray();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(this.rootPath + fileName);
|
||||
list.AddRange(JsonConvert.DeserializeObject<List<EntityData>>(content));
|
||||
}
|
||||
|
||||
/*List<string> lines = new List<string>();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(rootPath + fileName);
|
||||
lines.AddRange(content.Split('\n').ToList<string>());
|
||||
}
|
||||
|
||||
int seqNo = 1;
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
|
||||
string theLine = line.Trim();
|
||||
|
||||
string[] tmps = theLine.Split('\t');
|
||||
|
||||
if (tmps.Count() != 4)
|
||||
{
|
||||
throw new Exception("invalid line in entitymap.tsv");
|
||||
}
|
||||
else
|
||||
{
|
||||
string intentName = tmps[0].Trim();
|
||||
string similarWord = tmps[1].Trim();
|
||||
|
||||
string entityValue = tmps[2].Trim();
|
||||
string entityType = tmps[3].Trim();
|
||||
|
||||
EntityData entity = new EntityData();
|
||||
|
||||
entity.id = intentName + "-" + seqNo.ToString();
|
||||
entity.intentName = intentName;
|
||||
entity.similarWord = similarWord;
|
||||
entity.entityValue = entityValue;
|
||||
entity.entityType = entityType;
|
||||
|
||||
list.Add(entity);
|
||||
seqNo += 1;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<EntityAttributeData> ParseEntityAttributeData()
|
||||
{
|
||||
List<EntityAttributeData> list = new List<EntityAttributeData>();
|
||||
|
||||
string[] fileNamess = Directory.GetFiles(rootPath, "entityAttributeMap*.json").Select(Path.GetFileName).ToArray();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(this.rootPath + fileName);
|
||||
list.AddRange(JsonConvert.DeserializeObject<List<EntityAttributeData>>(content));
|
||||
}
|
||||
|
||||
|
||||
/*List<string> lines = new List<string>();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(rootPath + fileName);
|
||||
lines.AddRange(content.Split('\n').ToList<string>());
|
||||
}
|
||||
|
||||
int seqNo = 1;
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
string theLine = line.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(theLine))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] tmps = theLine.Split('\t');
|
||||
|
||||
if (tmps.Count() != 5)
|
||||
{
|
||||
throw new Exception("invalid line in entityAttributeMap.tsv");
|
||||
}
|
||||
else
|
||||
{
|
||||
string intentName = tmps[0];
|
||||
string entityValue = tmps[1];
|
||||
string entityType = tmps[2];
|
||||
string attributeName = tmps[3];
|
||||
string attributeValue = tmps[4];
|
||||
|
||||
EntityAttributeData ea = new EntityAttributeData();
|
||||
ea.id = intentName + "-" + entityValue + "-" + seqNo.ToString();
|
||||
ea.intentName = intentName;
|
||||
ea.entityValue = entityValue;
|
||||
ea.entityType = entityType;
|
||||
ea.attributeName = attributeName;
|
||||
ea.attributeValue = attributeValue;
|
||||
|
||||
list.Add(ea);
|
||||
seqNo += 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using SmartKG.Common.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace SmartKG.Common.Importer
|
||||
{
|
||||
public class VisuliaztionImporter
|
||||
{
|
||||
private string rootPath;
|
||||
private List<VisulizationConfig> vConfig;
|
||||
private ILogger log;
|
||||
|
||||
public VisuliaztionImporter(string rootPath)
|
||||
{
|
||||
log = Log.Logger.ForContext<VisuliaztionImporter>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rootPath))
|
||||
{
|
||||
throw new Exception("Rootpath of VisulizationConfig files are invalid.");
|
||||
}
|
||||
|
||||
this.rootPath = PathUtility.CompletePath(rootPath);
|
||||
|
||||
string[] fileNamess = Directory.GetFiles(this.rootPath, "VisulizationConfig*.json").Select(Path.GetFileName).ToArray();
|
||||
|
||||
this.vConfig = new List<VisulizationConfig>();
|
||||
|
||||
foreach (string fileName in fileNamess)
|
||||
{
|
||||
string content = File.ReadAllText(this.rootPath + fileName);
|
||||
this.vConfig.AddRange(JsonConvert.DeserializeObject<List<VisulizationConfig>>(content));
|
||||
}
|
||||
}
|
||||
|
||||
public List<VisulizationConfig> GetVisuliaztionConfigs()
|
||||
{
|
||||
return this.vConfig;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace SmartKG.Common.Logger
|
||||
{
|
||||
public interface KGBotLogHandler
|
||||
{
|
||||
void LogInformation(Serilog.ILogger log, string title, string content);
|
||||
|
||||
void LogError(Serilog.ILogger log, Exception e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Serilog;
|
||||
|
||||
namespace SmartKG.Common.Logger
|
||||
{
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
public static ILogger Here(this ILogger logger,
|
||||
[ContextStatic] string sourceContext = "",
|
||||
[CallerMemberName] string memberName = "",
|
||||
[CallerFilePath] string sourceFilePath = "",
|
||||
[CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
return logger.ForContext("MemberName", memberName)
|
||||
.ForContext("FilePath", sourceFilePath)
|
||||
.ForContext("LineNumber", sourceLineNumber);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
using SmartKG.Common.DataStoreMgmt;
|
||||
|
||||
namespace SmartKG.Common.Parser.DataPersistance
|
||||
{
|
||||
public class DataPersistanceKGParser
|
||||
{
|
||||
public static string defaultRelationType = "contains";
|
||||
private ILogger log;
|
||||
|
||||
public DataPersistanceKGParser()
|
||||
{
|
||||
log = Log.Logger.ForContext<DataPersistanceKGParser>();
|
||||
}
|
||||
|
||||
private (Dictionary<string, HashSet<string>>, Dictionary<string, Dictionary<RelationLink, List<string>>>, Dictionary<string, Dictionary<RelationLink, List<string>>>, Dictionary<string, List<Edge>>) GenerateRelationship(List<Vertex> vertexes, List<Edge> edges)
|
||||
{
|
||||
Dictionary<string, string> vertexIdNameMap = new Dictionary<string, string>();
|
||||
Dictionary<string, HashSet<string>> vertexNameIdsMap = new Dictionary<string, HashSet<string>>();
|
||||
foreach (Vertex vertex in vertexes)
|
||||
{
|
||||
vertexIdNameMap.Add(vertex.id, vertex.name);
|
||||
|
||||
if (vertexNameIdsMap.ContainsKey(vertex.name))
|
||||
{
|
||||
vertexNameIdsMap[vertex.name].Add(vertex.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
HashSet<string> idSet = new HashSet<string>();
|
||||
idSet.Add(vertex.id);
|
||||
|
||||
vertexNameIdsMap.Add(vertex.name, idSet);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, Dictionary<RelationLink, List<string>>> outRelationMap = new Dictionary<string, Dictionary<RelationLink, List<string>>>();
|
||||
Dictionary<string, Dictionary<RelationLink, List<string>>> inRelationMap = new Dictionary<string, Dictionary<RelationLink, List<string>>>();
|
||||
|
||||
|
||||
Dictionary<string, List<Edge>> scenarioEdgesMap = new Dictionary<string, List<Edge>>();
|
||||
|
||||
foreach (Edge edge in edges)
|
||||
{
|
||||
if (edge.scenarios != null && edge.scenarios.Count > 0)
|
||||
{
|
||||
foreach(string scenario in edge.scenarios)
|
||||
{
|
||||
if (!scenarioEdgesMap.ContainsKey(scenario))
|
||||
{
|
||||
List<Edge> edgesForScenario = new List<Edge>();
|
||||
scenarioEdgesMap.Add(scenario, edgesForScenario);
|
||||
}
|
||||
scenarioEdgesMap[scenario].Add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
string headVertexId = edge.headVertexId;
|
||||
string tailVertexId = edge.tailVertexId;
|
||||
string relationType = edge.relationType;
|
||||
|
||||
if (!vertexIdNameMap.ContainsKey(headVertexId) || !vertexIdNameMap.ContainsKey(tailVertexId))
|
||||
{
|
||||
log.Warning("VertexId is invalid: " + headVertexId + "; " + tailVertexId);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (relationType == null)
|
||||
{
|
||||
log.Warning("relationType is empty in Edge from " + headVertexId + " to " + tailVertexId + ".\nIf you have no dedicated scenarios, please set the default value of relationType as \"contains\"");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (edge.scenarios == null || edge.scenarios.Count == 0)
|
||||
{
|
||||
log.Warning("scenarios is empty in Edge from " + headVertexId + " to " + tailVertexId + ".\nIf you have no dedicated scenarios, please set the default value of secanrios as [\"Default\"]");
|
||||
continue;
|
||||
}
|
||||
|
||||
List<RelationLink> links = new List<RelationLink>();
|
||||
|
||||
foreach (string scenarioName in edge.scenarios)
|
||||
{
|
||||
links.Add(new RelationLink(relationType, scenarioName));
|
||||
}
|
||||
|
||||
|
||||
foreach (RelationLink link in links)
|
||||
{
|
||||
// --- Create outRelationDict
|
||||
|
||||
string vertexId = headVertexId;
|
||||
string childrenId = tailVertexId;
|
||||
|
||||
Dictionary<RelationLink, List<string>> outLinkDict;
|
||||
|
||||
if (!outRelationMap.ContainsKey(vertexId))
|
||||
{
|
||||
outLinkDict = new Dictionary<RelationLink, List<string>>();
|
||||
outLinkDict.Add(link, new List<string> { childrenId });
|
||||
|
||||
outRelationMap.Add(vertexId, outLinkDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
outLinkDict = outRelationMap[vertexId];
|
||||
bool inserted = false;
|
||||
foreach(RelationLink savedLink in outLinkDict.Keys)
|
||||
{
|
||||
if (savedLink.Equals(link))
|
||||
{
|
||||
outLinkDict[savedLink].Add(childrenId);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
{
|
||||
outLinkDict.Add(link, new List<string> { childrenId });
|
||||
}
|
||||
}
|
||||
|
||||
// --- Create inRelationDict
|
||||
|
||||
vertexId = tailVertexId;
|
||||
string parentId = headVertexId;
|
||||
|
||||
Dictionary<RelationLink, List<string>> inLinkDict;
|
||||
|
||||
if (!inRelationMap.ContainsKey(vertexId))
|
||||
{
|
||||
inLinkDict = new Dictionary<RelationLink, List<string>>();
|
||||
inLinkDict.Add(link, new List<string> { parentId });
|
||||
|
||||
inRelationMap.Add(vertexId, inLinkDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
inLinkDict = inRelationMap[vertexId];
|
||||
bool inserted = false;
|
||||
foreach (RelationLink savedLink in inLinkDict.Keys)
|
||||
{
|
||||
if (savedLink.Equals(link))
|
||||
{
|
||||
inLinkDict[savedLink].Add(parentId);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
{
|
||||
inLinkDict.Add(link, new List<string> { parentId });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (vertexNameIdsMap, outRelationMap, inRelationMap, scenarioEdgesMap);
|
||||
}
|
||||
|
||||
public KGConfigFrame ParseKGConfig(List<VisulizationConfig> vcList)
|
||||
{
|
||||
KGConfigFrame kgConfigFrame = new KGConfigFrame();
|
||||
|
||||
Dictionary<string, List<ColorConfig>> vertexLabelsMap = new Dictionary<string, List<ColorConfig>>();
|
||||
|
||||
foreach (VisulizationConfig vc in vcList)
|
||||
{
|
||||
string scenarioName = vc.scenario;
|
||||
List<ColorConfig> cc = vc.labelsOfVertexes;
|
||||
|
||||
vertexLabelsMap.Add(scenarioName, cc);
|
||||
}
|
||||
|
||||
kgConfigFrame.SetVertexLabelColorMap(vertexLabelsMap);
|
||||
|
||||
return kgConfigFrame;
|
||||
}
|
||||
|
||||
public KnowledgeGraphDataFrame ParseKG(List<Vertex> vertexes, List<Edge> edges)
|
||||
{
|
||||
(Dictionary<string, HashSet<string>> nameIdMap, Dictionary<string, Dictionary<RelationLink, List<string>>> outRelationDict, Dictionary<string, Dictionary<RelationLink, List<string>>> inRelationDict, Dictionary<string, List<Edge>> scenarioEdgesMap) = this.GenerateRelationship(vertexes, edges);
|
||||
|
||||
Dictionary<string, List<Vertex>> vNameCache = new Dictionary<string, List<Vertex>>();
|
||||
Dictionary<string, Vertex> vIdCache = new Dictionary<string, Vertex>();
|
||||
List<Vertex> roots = new List<Vertex>();
|
||||
|
||||
HashSet<string> scenarioNames = new HashSet<string>();
|
||||
|
||||
foreach (Vertex vertex in vertexes)
|
||||
{
|
||||
scenarioNames.UnionWith(vertex.scenarios);
|
||||
|
||||
if (vertex.nodeType == "ROOT")
|
||||
{
|
||||
roots.Add(vertex);
|
||||
}
|
||||
|
||||
if (vNameCache.ContainsKey(vertex.name))
|
||||
{
|
||||
vNameCache[vertex.name].Add(vertex);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Vertex> vertexesGroupedByName = new List<Vertex>();
|
||||
vertexesGroupedByName.Add(vertex);
|
||||
vNameCache.Add(vertex.name, vertexesGroupedByName);
|
||||
}
|
||||
vIdCache.Add(vertex.id, vertex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
KnowledgeGraphDataFrame kgDF = new KnowledgeGraphDataFrame();
|
||||
|
||||
kgDF.SetRootVertexes(roots);
|
||||
kgDF.SetVertexIdCache(vIdCache);
|
||||
kgDF.SetVertexNameCache(vNameCache);
|
||||
kgDF.SetOutRelationDict(outRelationDict);
|
||||
kgDF.SetInRelationDict(inRelationDict);
|
||||
kgDF.SetScenarioEdgesDict(scenarioEdgesMap);
|
||||
kgDF.SetScenarioNames(scenarioNames);
|
||||
|
||||
return kgDF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SmartKG.Common.Data;
|
||||
using System;
|
||||
using Serilog;
|
||||
using SmartKG.Common.Data.LU;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using SmartKG.Common.DataStoreMgmt;
|
||||
|
||||
namespace SmartKG.Common.DataPersistance
|
||||
{
|
||||
public class DataPersistanceNLUParser
|
||||
{
|
||||
private ILogger log;
|
||||
|
||||
public DataPersistanceNLUParser()
|
||||
{
|
||||
log = Log.Logger.ForContext<DataPersistanceNLUParser>();
|
||||
}
|
||||
|
||||
public NLUDataFrame Parse(List<NLUIntentRule> iList, List<EntityData> eList, List<EntityAttributeData> eaList)
|
||||
{
|
||||
NLUDataFrame nluDF = new NLUDataFrame();
|
||||
|
||||
if (iList == null || iList.Count == 0)
|
||||
{
|
||||
//throw new Exception("No Intent is defined.");
|
||||
log.Warning("No Intent is defined.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (NLUIntentRule intentRule in iList)
|
||||
{
|
||||
nluDF.AddIntentRule(intentRule);
|
||||
}
|
||||
}
|
||||
|
||||
if (eList == null || eList.Count == 0)
|
||||
{
|
||||
//throw new Exception("No Entity is defined.");
|
||||
log.Warning("No Entity is defined.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (EntityData entity in eList)
|
||||
{
|
||||
NLUEntity nluEntity = nluDF.AddEntity(entity.intentName, entity.entityValue, entity.entityType);
|
||||
nluDF.AddSimilarWord(entity.intentName, entity.similarWord, nluEntity);
|
||||
}
|
||||
}
|
||||
|
||||
if (eaList == null || eaList.Count == 0)
|
||||
{
|
||||
Log.Information("There is not any entity attribute defined.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (EntityAttributeData ea in eaList)
|
||||
{
|
||||
nluDF.AddAttribute(ea.intentName, new NLUEntity(ea.entityValue, ea.entityType), new AttributePair(ea.attributeName, ea.attributeValue));
|
||||
}
|
||||
}
|
||||
|
||||
return nluDF;
|
||||
}
|
||||
|
||||
public void ParseScenarioSettings(NLUDataFrame nluDF, List<ScenarioSetting> kgSettings, List<Vertex> rootVertexes)
|
||||
{
|
||||
|
||||
Dictionary<string, ScenarioSetting> scenarioCache = new Dictionary<string, ScenarioSetting>();
|
||||
if (kgSettings != null && kgSettings.Count > 0)
|
||||
{
|
||||
foreach (ScenarioSetting setting in kgSettings)
|
||||
{
|
||||
scenarioCache.Add(setting.scenarioName, setting);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Vertex vertex in rootVertexes)
|
||||
{
|
||||
|
||||
if (vertex.nodeType == "ROOT" && vertex.scenarios != null)
|
||||
{
|
||||
foreach(string scenarioName in vertex.scenarios)
|
||||
{
|
||||
|
||||
if (scenarioCache.ContainsKey(scenarioName))
|
||||
{
|
||||
scenarioCache[scenarioName].root = vertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScenarioSetting defaultSetting = new ScenarioSetting(scenarioName, vertex);
|
||||
scenarioCache.Add(scenarioName, defaultSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nluDF.SetSceanrioCache(scenarioCache);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using OfficeOpenXml;
|
||||
using SmartKG.Common.Data.KG;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace SmartKG.Common.Parser
|
||||
{
|
||||
|
||||
public class ExcelParser
|
||||
{
|
||||
|
||||
public (List<Vertex>, List<Edge>) ParserExcel(string path, string scenario)
|
||||
{
|
||||
var fi = new FileInfo(path);
|
||||
|
||||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||||
|
||||
Dictionary<string, Vertex> vRows = new Dictionary<string, Vertex>();
|
||||
Dictionary<string, Edge> eRows = new Dictionary<string, Edge>();
|
||||
|
||||
using (ExcelPackage package = new ExcelPackage(fi))
|
||||
{
|
||||
//get the first worksheet in the workbook
|
||||
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
|
||||
|
||||
int colCount = worksheet.Dimension.End.Column; //get Column Count
|
||||
int rowCount = worksheet.Dimension.End.Row; //get row count
|
||||
|
||||
for (int row = 2; row <= rowCount; row++)
|
||||
{
|
||||
Vertex aVertex = new Vertex();
|
||||
aVertex.properties = new List<VertexProperty>();
|
||||
aVertex.scenarios = new List<string>() { scenario};
|
||||
|
||||
VertexProperty p = null;
|
||||
|
||||
for (int col = 1; col <= colCount; col++)
|
||||
{
|
||||
string cellStr = worksheet.Cells[row, col].Value?.ToString().Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(cellStr))
|
||||
{
|
||||
switch (col)
|
||||
{
|
||||
case 1:
|
||||
|
||||
aVertex.id = cellStr + "_" + scenario;
|
||||
break;
|
||||
case 2:
|
||||
aVertex.name = cellStr;
|
||||
break;
|
||||
case 3:
|
||||
aVertex.label = cellStr;
|
||||
break;
|
||||
case 4:
|
||||
aVertex.leadSentence = cellStr;
|
||||
break;
|
||||
default:
|
||||
if (col % 2 == 1)
|
||||
{
|
||||
p = new VertexProperty();
|
||||
p.name = cellStr;
|
||||
|
||||
col += 1;
|
||||
cellStr = worksheet.Cells[row, col].Value?.ToString().Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(cellStr))
|
||||
{
|
||||
p.value = cellStr;
|
||||
aVertex.properties.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(aVertex.id) && !string.IsNullOrWhiteSpace(aVertex.name) && !string.IsNullOrWhiteSpace(aVertex.label))
|
||||
{
|
||||
if (!vRows.ContainsKey(aVertex.id))
|
||||
{
|
||||
vRows.Add(aVertex.id, aVertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
worksheet = package.Workbook.Worksheets[1];
|
||||
|
||||
colCount = worksheet.Dimension.End.Column; //get Column Count
|
||||
rowCount = worksheet.Dimension.End.Row; //get row count
|
||||
for (int row = 2; row <= rowCount; row++)
|
||||
{
|
||||
Edge aEdge = new Edge();
|
||||
aEdge.scenarios = new List<string>() { scenario };
|
||||
|
||||
for (int col = 1; col <= colCount; col++)
|
||||
{
|
||||
string cellStr = worksheet.Cells[row, col].Value?.ToString().Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(cellStr))
|
||||
{
|
||||
switch (col)
|
||||
{
|
||||
case 1:
|
||||
|
||||
aEdge.relationType = cellStr;
|
||||
break;
|
||||
case 2:
|
||||
aEdge.headVertexId = cellStr + "_" + scenario;
|
||||
break;
|
||||
case 3:
|
||||
aEdge.tailVertexId = cellStr + "_" + scenario;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(aEdge.relationType) && !string.IsNullOrWhiteSpace(aEdge.headVertexId) && !string.IsNullOrWhiteSpace(aEdge.tailVertexId))
|
||||
{
|
||||
if (vRows.ContainsKey(aEdge.headVertexId) && vRows.ContainsKey(aEdge.tailVertexId))
|
||||
{
|
||||
string key = aEdge.relationType + aEdge.headVertexId + aEdge.tailVertexId;
|
||||
|
||||
if (!eRows.ContainsKey(key))
|
||||
{
|
||||
eRows.Add(key, aEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (vRows.Values.ToList<Vertex>(), eRows.Values.ToList<Edge>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1.16</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EPPlus" Version="5.5.3" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.9.2" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using SmartKG.Common.Data.Visulization;
|
||||
|
||||
namespace SmartKG.Common.Utils
|
||||
{
|
||||
public class KGUtility
|
||||
{
|
||||
private static string GenerateIdForProperty(string name, string value)
|
||||
{
|
||||
string propertyId = name + ":" + value;
|
||||
return propertyId;
|
||||
}
|
||||
|
||||
public static VisulizedVertex GeneratePropertyVVertex(string vertexLabel, string pName, string pValue)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(vertexLabel))
|
||||
vertexLabel = "";
|
||||
else
|
||||
vertexLabel = "_" + vertexLabel;
|
||||
|
||||
VisulizedVertex propertyVV = new VisulizedVertex();
|
||||
propertyVV.name = pValue;
|
||||
propertyVV.displayName = pName;
|
||||
propertyVV.label = vertexLabel + "属性";
|
||||
propertyVV.id = GenerateIdForProperty(pName, pValue);
|
||||
|
||||
return propertyVV;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue