关键字
namespace
EntityType, ConceptType, EventType, ->, STD.*, Text, Float, Integer
desc, constraint, value, properties, relations, rule, hypernymPredicatem, autoRelate, spreadable, regular
NotNull, MultiValue, Enum, Regular
-> 用于表达类型的继承关系,A -> B
STD.*表示以STD.开头的都是预留关键字,作标准类型名称
基础句法
类似YAML,以缩进作为作用域的表示。缩进建议使用4个空格(Tab符会被当做两个空格)
- A(B): C
- A为类型/属性的英文名
- B为类型/属性的中文名称
- C为取值
- A(B)->P
- A为类型的英文名
- B为类型的中文名称
- P为要继承自的父类型
- namespace A
- A表示项目前缀,在Schema文件的第一行必须出现。项目前缀会在Schema提交的时候自动拼接到实体类型名称的前面
- [[...]]
- 规则脚本的定界符,仅用于rule的定义,类似于Python的"""用法
声明式Schema脚本采用逐行解析的方式,定义上要遵循顺序原则,即父类型要在子类型之前定义、属性上使用的类型也需要在其所属类型定义之前先定义好。
语法结构
总共分类6层缩进,按缩进的多少依次为:
- 第一层(无缩进):定义类型、命名空间
- 第二层:定义类型的元信息,比如描述、属性、关系等
- 第三层:定义属性/关系的名称和类型
- 第四层:定义属性/关系的元信息,比如约束、子属性、逻辑规则等
- 第五层:定义子属性的名称和类型
- 第六层:定义子属性的元信息,比如描述、约束
namespace DEFAULT
TypeA(实体类型A): EntityType
desc: 实体类型描述
properties:
property1(属性1): STD.ChinaMobile
desc: 属性1的描述
constraint: NotNull, MultiValue
properties:
property2(属性1的子属性): Text
desc: 属性1的子属性,枚举约束
constraint: NotNull, Enum="A,B,C"
property3(属性1的子属性): Text
desc: 属性1的子属性,正则约束
constraint: Regular="^abc[0-9]+$"
property4(属性4): Text
rule: [[
Define property4...
]]
relations:
relation1(关系1): TypeA
desc: 关系1的描述
properties:
confidence(置信度): Float
rule: [[
Define relation1...
]]
TypeB(实体类型B) -> TypeA:
desc: 这是实体类型A的子类型
定义实体类型
# 以下定义一个公司的实体类型
Company(公司): EntityType
# 以下是定义一个继承自公司的实体类型
ListedCompany(上市公司) -> Company:
定义属性和关系
Company(公司): EntityType
# 这里是公司的描述
desc: 公司的描述
properties:
# 这里定义属性
address(地址): Text
# 这里定义地址属性为非空约束,除此还可以定义MultiValue(多值,英文逗号分割)、Enum(枚举)和Regular(正则)
constraint: NotNull
industry(行业): Industry
# 每个类型会默认创建id、name和description属性,都是Text类型
# id(主键): Text
# name(名称): Text
# description(描述): Text
relations:
# 这里定义关系
subCompany(子公司): Company
定义子属性
Company(公司): EntityType
desc: 公司的描述
properties:
address(地址): Text
# 这里定义地址的子属性置信度
confidence(置信度): Float
industry(行业): Industry
定义谓词逻辑
Company(公司): EntityType
desc: 公司的描述
relations:
risk(风险关联): Company
# 这里定义关系的谓词逻辑,使用 [[ 和 ]] 作为逻辑规则的定界符
rule: [[
Define (s:Comapny)-[p:risk]->(o:Company) {
... ...
}
]]
如果是定义从实体类型到同个概念类型下的不同概念实例的逻辑,请在同个rule关键字里写多段Define的脚本。
定义概念类型
Industry(公司行业分类): ConceptType
# 这里定义概念的上下位关系谓词,默认为isA,可以指定isA和locateAt
hypernymPredicate: isA
概念类型的关系只允许创建在7大类里定义的谓词,这里可以通过autoRelate一键创建7大类的所有关系:
Industry(公司行业分类): ConceptType
autoRelate: Industry
定义事件类型
CompanyRiskEvent(公司风险事件): EventType
properties:
# 这里定义事件类型的主体为公司,事件类型必须定义主体subject
subject: Company
建模示例
namespace Medical
Symptom(症状): EntityType
Drug(药品): EntityType
Indicator(医学指征): EntityType
BodyPart(人体部位): ConceptType
hypernymPredicate: isA
HospitalDepartment(医院科室): ConceptType
hypernymPredicate: isA
Disease(疾病): EntityType
properties:
complication(并发症): Disease
constraint: MultiValue
commonSymptom(常见症状): Symptom
constraint: MultiValue
applicableDrug(适用药品): Drug
constraint: MultiValue
department(就诊科室): HospitalDepartment
constraint: MultiValue
diseaseSite(发病部位): BodyPart
constraint: MultiValue
relations:
abnormal(异常指征): Indicator
properties:
range(指标范围): Text
color(颜色): Text
shape(性状): Text
建模最佳实践
为了方便大家更好地理解和应用OpenSPG构建知识图谱,我们从SPGSchema建模的最佳实践中总结出了7个原则,每个原则都搭配了相关示例进行说明。期望通过这些原则能解决大家在建模时的疑惑,能充分发挥OpenSPG高效且强大的知识表达能力。
-
- 类型选择原则
原则1:复杂多元结构用实体类型或事件类型
解释:当一个事物需要丰富的属性来进行描述,比如某个“公司”,不光是只用一个名称,还要借助经营范围、企业证件号码、注册地址等信息来描述,就适合使用实体类型进行建模。
原则2:扁平化的分类标签用概念类型
解释:当目标建模对象仅仅是语言或文本意义上的分类标签,重点表达标签之间的上位、包含、因果等关系时,适合使用概念类型来进行建模,比如“矿石开采”、“矿石冶炼”这类表达对产业分类的标签。概念和实体、事件的区别是:
- 多元结构 vs 一元结构: 如公司类型,有所在行政区域、所属行业、经营产品类目等多元属性定义,每个属性关联一个具体的概念类型。 而行政区域、行业类目、产品类目都是一元结构的概念分类,重点表达的是类目之间的上下位关系。
- 同名建模冲突处理机制:比如杭州市,若描述其特产、人口、区号等信息时应使用实体类型进行建模,但同时杭州市也可以作为一个行政区划的角度来使用,主要说明杭州市位于浙江省,浙江省又位于中国,此时杭州市、浙江省、中国都属于行政区划的一个实例,它们重点表达相互间的地理上的位于关系。 这个时候,建议创建一个实体类型的同时又再创建一个概念类型,杭州市作为这两种类型的实例分别导入。
以如下Schema为例:
namespace CKG
AdministractiveArea(行政区划): ConceptType
hypernymPredicate: locateAt
... ...
City(城市): EntityType
properties:
localProducts(特产): Product
constraint: MultiValue
population(人口数量): Integer
areaCode(区号): Text
region(行政区划): AdministractiveArea
数据示例:
“City(城市)”的实体:
{
"id": "hz",
"name": "杭州市",
"areaCode": "0571",
"region": "中国-浙江省-杭州市"
}
“AdministractiveArea(行政区划)”的概念:
中国 <-locateAt- 浙江省 <-locateAt- 杭州市
原则3:实体/事件多类型使用动态分类原则
解释:客观世界对同一个事物会有多种分类,比如表示商铺的分类有:超市、便利店、加油站、洗车店等,如果按照这些不同分类视角分别进行实体类型建模,会造成图谱的类型爆炸,在数据构建和推理应用上会变得非常麻烦。SPG使用类型定义 + 分类概念的方式实现多分类来解决这个问题。
以商铺为例子。建模时先创建一个“商铺”的实体类型,然后再为这个实体类型创建一个“商铺分类”的概念类型用于分类。注意定义上要把概念类型放到实体类型的前面:
namespace World
TaxonomyOfShop(商铺分类): ConceptType
hypernymPredicate: isA
Shop(商铺): EntityType
desc: 诸如便利店和加油站等
properties:
locateArea(所在区域): AdministractiveArea
address(地址): Text
contactPhone(联系电话): STD.ChinaTelCode
IND#belongTo(属于): TaxonomyOfShop
然后准备“商铺分类”的概念数据作导入用:
csv:
超市
便利店
加油站
洗车店
导入“Shop(商铺)”的实例数据的时候,如下所示:
id,name,locateArea,address,contactPhone,belongTo
1,罗森便利店,杭州市,浙江省杭州市西湖区西溪路588号1层,0571-85801525,便利店
2,中国石化(杭州古荡加油站),杭州市,浙江省杭州市西湖区天目山路331号,0571-85220839,加油站
通过belongTo属性的值会自动产生从实例到概念的边,实现对实体的分类。
在查询时,我们可以直接用概念类型“TaxonomyOfShop”指代类型“Shop”,实现按概念召回对应的实体。实现跟使用类型分别建模的效果,但是大幅简化数据的查询和维护。
MATCH (s:`TaxonomyOfShop`/`便利店`) RETURN s
# 返回id为1的"罗森便利店"实体
MATCH (s:`TaxonomyOfShop`/`加油站`) RETURN s
# 返回id为1的"中国石化(杭州古荡加油站)"实体
另外,SPGSchema也支持以规则作为概念挂载依据,即通过规则对实体的属性进行运算得出要挂载的概念名称。
比如我们可以通过定义如下的概念规则,根据实体的名称里的关键词自动分类:
Define (s:Shop)-[p:belongTo]->(o:`TaxonomyOfShop`/`便利店`) {
Structure {
(s)
}
Constraint {
R1("是便利店"): s.name like "%便利店%"
}
}
Define (s:Shop)-[p:belongTo]->(o:`TaxonomyOfShop`/`加油站`) {
Structure {
(s)
}
Constraint {
R1("是加油站"): s.name like "%加油站%"
}
}
导入“Shop(商铺)”的实例数据的时候,不再导入belongTo属性:
id,name,city,address,contactPhone
1,罗森便利店,杭州市,浙江省杭州市西湖区西溪路588号1层,0571-85801525
2,中国石化(杭州古荡加油站),杭州市,浙江省杭州市西湖区天目山路331号,0571-85220839
数据导入完成后,查询可得到belongTo属性的值和关系:
MATCH (s:Shop WHERE id="1")-[p:belongTo]-(o) RETURN s,p,o
注意:
如果概念定义了归纳规则,但在数据导入时又导入了belongTo属性值,会以规则运算结果优先。
原则4:概念类型不继承
解释:概念类型的父类有且只有Thing,不能继承其他的类型。因为概念本身默认会有上下位关系,就隐含继承的语义。如果概念类型再继承,在语义上就会有冲突。
2、属性/关系的选择原则
原则5:关系的指向遵守由动到静原则,反之被禁止
解释:事件类型可指向任意类型,实体类型不可指向事件类型,概念类型只能指向概念类型,反之被禁止。
- 事件允许指向任意类型: 事件都是独立发生的行为动作,实体/概念/标准类型是被动跟发生的事件关联,所以是事件类型指向任意类型,反之禁止。
- 实体禁止指向事件类型:实体都是多元要素的复杂对象,它可以和其他实体主动产生关联,但概念类型、标准类型只能做为实体的属性类型。因为实体本身不自动产生事件,所以实体禁止直接建立和事件的关系。
- 概念禁止指向多元类型:概念是扁平化的分类标签,它抽象描述一类共同特征的实体集合,所以它只能被事件或实体用作属性类型的定义,反之禁止。
原则6:概念类型之间只允许系统指定的7大类语义关系
- HYP: 上位关系(Hypernym),是指一种更广泛或更一般的概念包含或包括另一种更具体或更特定的概念的关系。目前可用的谓词为isA、locateAt等。
- SYNANT: 同义反义关系(Synonymy/Antonymy),表达概念之间是同义还是反义的关系。目前可用的谓词有synonym、antonym等。
- CAU: 因果关系(Causal),表示指一个事件或行为(原因)导致另一个事件或行为(结果)发生的一类关系。目前可用的谓词有leadTo等。
- SEQ: 顺承关系(Sequential),是连续发生的事情或动作,这些事情或动作有先后顺序。目前可用的谓词有happenedBefore等。
- IND: 归纳关系(Induction),是指从一类有共同特征的实体中得出对这些实体概括性的概念,这种个体和概念之间的关系就是归纳关系。目前可用的谓词有belongTo等。
- INC: 包含关系(Inclusion),表达部分与整体的关系。目前可用的谓词有isPartOf等。
- USE: 用途关系(Usage),表达作用/用途的关系。
原则7:属性尽量标准化(推荐但不强制约束)
解释:尽可能的使用概念类型、标准类型和实体类型对属性进行标准化。因为SPGSchema会自动根据属性生成等价的关系,简化关系的创建和数据维护。尤其在变更实体的属性值后,关系实例会自动根据属性值同步,让属性等价的关系始终保持跟属性值的描述一致。SPGSchema建议尽量使用属性来替代关系的创建,只有确实需要在关系上配置属性,或者定义逻辑关系的时候再使用关系的创建。
概念关系语义分类
概念之间只允许定义以下7大类的语义谓词(属性和关系),具体定义形式为:分类简写#谓词,比如HYP#isA
HYP: 上位关系(Hypernym)
是指一种更广泛或更一般的概念包含或包括另一种更具体或更特定的概念的关系。
- isA
是...一种
- locateAt
位于
- mannerOf
A 是 B 的一种特定实现方式。类似于 "IsA",但用于动词。比如 “拍卖” → “销售”
SYNANT: 同义反义关系(Synonymy/Antonymy)
表达概念之间是同义还是反义的关系。
- synonym
表达同义词
- antonym
表达反义词
- symbolOf
A 象征性地代表了 B。比如:“红色” → “热情”
- distinctFrom
A 和 B 是一个集合中不同的成员,是 A 的东西绝对不是 B。比如:“八月”→ “九月”
- definedAs
A 和 B 在意义上有相当大的重叠,但 B 是 A 的更具解释性的版本。比如:“和平”→ “没有战争”
- locatedNear
A 和 B 通常会被发现靠近彼此。比如:“椅子” → “桌子”
- similarTo
A 和 B 相似。比如:“搅拌器” → “食物处理器”
- etymologicallyRelatedTo
A和B有共同的来源。比如:“folkmusiikki” → “folk music”
CAU: 因果关系(Causal)
表示指一个事件或行为(原因)导致另一个事件或行为(结果)发生的一类关系。
- leadTo
表达事件通过逻辑规则实现传递,比如A事件实例会在满足指定规则的前提下生成一个B事件实例。此谓词在系统上会被识别为实例生成的意图,用于实现事件的实例传递。
- causes
表达恒定的因果关系,没有条件约束
- obstructedBy
A 是一个可能被 B 阻止的目标,B 是阻碍 A 实现的障碍。比如:“睡觉” → “噪音”
- causesDesire
A使人想要B,其中A的状态或事件激发了对B的欲望或需求。比如:“没吃的”→“去商店”
- createdBy
B 是一个创造 A 的过程或者动因。比如:“蛋糕”→“烘焙”
SEQ: 顺承关系(Sequential)
是连续发生的事情或动作,这些事情或动作有先后顺序。
- happendedBefore
A先于B发生
- hasSubevent
A和B是事件,B作为A的子事件发生。比如:“吃” → “咀嚼”
- hasFirstSubevent
A 是一个以子事件 B 开始的事件。比如:“睡觉” → “闭眼”
- hasLastSubevent
A 是一个以子事件 B 结束的事件。比如:“烹饪” → “收拾厨房”
- hasPrerequisite
为了让 A 发生,需要发生 B;B 是 A 的前提条件。比如:“做梦” → “睡觉”
IND: 归纳关系(Induction)
是指从一类有共同特征的实体中得出对这些实体概括性的概念,这种个体和概念之间的关系就是归纳关系。
- belongTo
该关系一般在SPG里用于实体类型到概念类型的分类关系描述,比如“公司事件” → “公司事件分类”
INC: 包含组成关系(Inclusion)
表达部分与整体的关系。
- isPartOf
A是B的一个部分
- hasA
B 属于 A,作为固有部分或由于占有的社会构造。HasA 往往是 PartOf 的反向关系。比如:“鸟”→“翅膀”
- madeOf
A是由B组成的。比如:“瓶子”→“塑料”
- derivedFrom
A衍生/源自于B,用于表达组合概念
- hasContext
A 是在 B 上下文中使用的一个词,B 可以是一个主题领域、技术领域或区域方言。比如:“astern”→“ship”
USE: 用途关系(Usage)
表达作用/用途的关系。
- usedFor
A 被用于 B,A 的目的是 B。比如:“桥”→“通过水域”
- capableOf
A 通常能做的事是 B。比如:“刀”→“切割”
- receivesAction
B可以对A做的动作。比如:“按钮”→“按”
- motivatedByGoal
某人做 A 是因为他们想要结果 B;A 是实现目标 B 的一个步骤。比如:“竞争”→“赢”