Skip to content

OpenSPG 开发教程 ​

目录 ​


1. 项目简介 ​

1.1 什么是OpenSPG? ​

OpenSPG (Open Semantic-enhanced Programmable Graph) 是蚂蚁集团与OpenKG联合推出的开源知识图谱引擎,基于SPG框架研发。它结合了多年金融领域知识图谱构建与应用的业务经验。

1.2 核心特性 ​

  • 语义增强的属性图:融合LPG结构性与RDF语义性
  • 知识构建框架:支持结构化和非结构化数据的知识转换
  • 逻辑规则推理:提供KGDSL(知识图谱领域专用语言)
  • 可编程框架KNext:组件化、流程化的图谱能力
  • 云适配层Cloudext:可插拔的图存储、搜索引擎等基础设施

1.3 应用场景 ​

  • 企业供应链知识图谱
  • 风险挖掘与反欺诈
  • 医疗知识图谱
  • 知识增强生成(KAG)与大语言模型结合

1.4 技术栈 ​

技术类别技术选型
开发语言Java 8, Scala 2.11.12
构建工具Maven 3+
Web框架Spring Boot 2.7.8, SOFABoot 3.17.0
数据访问MyBatis 3.5.2
图数据库Neo4j 4.4.7, TuGraph 1.4.1
搜索引擎Elasticsearch, Neo4j
缓存Redis
对象存储MinIO, Aliyun OSS
DSL解析ANTLR4 4.8

2. 系统架构 ​

2.1 整体架构 ​

┌─────────────────────────────────────────────────────────────┐
│                     OpenSPG Engine                          │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │  Schema  │  │ Builder  │  │ Reasoner │  │  KNext   │   │
│  │  模型定义  │  │ 知识构建  │  │ 逻辑推理  │  │ 可编程框架│   │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘   │
├─────────────────────────────────────────────────────────────┤
│                   Cloud Adaptation Layer                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │ GraphStore│  │  Search  │  │  Cache   │  │ Storage  │   │
│  │ 图存储适配 │  │ 搜索适配  │  │ 缓存适配  │  │ 对象存储  │   │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘   │
├─────────────────────────────────────────────────────────────┤
│                    Infrastructure                           │
│     Neo4j / TuGraph | Elasticsearch | Redis | MinIO        │
└─────────────────────────────────────────────────────────────┘

2.2 模块结构 ​

openspg/
├── server/              # REST API服务层
│   ├── api/            # HTTP接口定义
│   ├── biz/            # 业务逻辑层
│   ├── core/           # 核心服务
│   ├── common/         # 公共模块
│   ├── infra/          # 基础设施(数据访问)
│   └── arks/           # 应用启动
├── reasoner/           # 推理引擎
│   ├── lube-api/       # 抽象接口
│   ├── lube-logical/   # 逻辑查询计划
│   ├── lube-physical/  # 物理执行计划
│   ├── kgdsl-parser/   # KGDSL解析器
│   ├── runner/         # 执行器
│   ├── warehouse/      # 图仓库
│   └── catalog/        # Schema目录
├── builder/            # 知识构建框架
│   ├── core/           # 核心执行引擎
│   ├── model/          # 数据模型
│   └── runner/         # 本地执行器
├── cloudext/           # 云适配层
│   ├── interface/      # 抽象接口
│   └── impl/           # 具体实现
└── common/             # 公共工具类

2.3 核心概念 ​

SPG类型体系 ​

SPGType (所有类型的基类)
├── EntityType      # 实体类型(如:人物、组织)
├── ConceptType     # 概念类型(如:行业分类)
├── EventType       # 事件类型(如:交易事件)
├── StandardType    # 标准类型(如:实体归一化)
└── BasicType       # 基础类型(如:Text、Integer)

谓词(Predicate) ​

  • Property(属性):实体的属性,如人物的年龄、姓名
  • Relation(关系):实体之间的关系,如人物-工作于-组织

3. 环境搭建 ​

3.1 前置要求 ​

  • Java: JDK 1.8+
  • Maven: 3.0+
  • MySQL: 5.7+(用于元数据存储)
  • Neo4j: 4.4.7或TuGraph 1.4.1(图数据库)
  • Python: 3.10+(可选,用于NLP处理)

3.2 快速启动 ​

步骤1:克隆代码 ​

bash
git clone https://github.com/OpenSPG/openspg.git
cd openspg

步骤2:配置数据库 ​

创建MySQL数据库:

sql
CREATE DATABASE openspg CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

步骤3:配置应用 ​

编辑配置文件 server/arks/sofaboot/src/main/resources/config/application-default.properties:

properties
# 服务器配置
server.port=8887

# MySQL配置
server.repository.impl.jdbc.host=127.0.0.1
server.repository.impl.jdbc.port=3306
server.repository.impl.jdbc.username=root
server.repository.impl.jdbc.password=your_password

# 图数据库配置(Neo4j)
cloudext.graphstore.url=neo4j://localhost:7687?user=neo4j&password=your_neo4j_password&database=neo4j

# 搜索引擎配置
cloudext.searchengine.url=neo4j://localhost:7687?user=neo4j&password=your_neo4j_password&database=neo4j

# Python配置(可选)
python.exec=/usr/bin/python3
python.paths=/usr/lib/python3.10/site-packages/

步骤4:构建项目 ​

bash
mvn clean install -DskipTests

步骤5:启动服务 ​

bash
cd server/arks/sofaboot
mvn spring-boot:run

服务启动后,访问 http://localhost:8887 验证服务是否正常运行。

3.3 Docker部署(推荐) ​

使用Docker Compose快速部署完整环境:

bash
# 启动所有服务(MySQL、Neo4j、OpenSPG)
docker-compose up -d

4. 核心模块详解 ​

4.1 Schema模块(语义建模) ​

Schema模块负责定义知识图谱的语义结构。

主要功能 ​

  • 定义SPG类型(实体、概念、事件等)
  • 定义属性和关系
  • Schema版本管理和演化
  • 语义约束和规则定义

核心类 ​

  • BaseSPGType: 所有SPG类型的基类
  • EntityType: 实体类型定义
  • Property: 属性定义
  • Relation: 关系定义
  • SchemaDraft: Schema草稿(用于批量修改)

代码示例 ​

java
// 创建一个实体类型
EntityType personType = new EntityType(
    new BasicInfo(
        new SPGTypeIdentifier("default", "Person"),
        "人物",
        "表示现实中的人物"
    ),
    ParentTypeInfo.THING,
    properties,  // 属性列表
    relations,   // 关系列表
    null
);

// 添加属性
Property nameProperty = new Property(
    new BasicInfo(
        new PredicateIdentifier("name"),
        "姓名",
        "人物的姓名"
    ),
    null,
    new SPGTypeRef(BasicType.TEXT),
    false,  // 是否多值
    new PropertyAdvancedConfig()
        .setIndexType(IndexTypeEnum.TEXT)
);

4.2 Builder模块(知识构建) ​

Builder模块负责从数据源构建知识图谱。

架构 ​

数据源 → 读取器 → 处理器 → 写入器 → 图存储
 ↓        ↓         ↓         ↓        ↓
CSV     Source   Python   Sink     Neo4j
JSON    Reader  Processor Writer  TuGraph
DB

核心组件 ​

  • SourceReader: 数据源读取器

    • CSVReader
    • JSONReader
    • DatabaseReader
  • Processor: 数据处理器

    • EntityLinkingProcessor(实体链接)
    • ConceptNormalizationProcessor(概念标准化)
    • EntityNormalizationProcessor(实体归一化)
    • PythonProcessor(Python自定义处理)
  • SinkWriter: 数据写入器

    • GraphStoreWriter
    • Neo4jWriter

工作流程 ​

  1. 定义Schema: 先定义知识图谱的Schema
  2. 配置数据源: 配置CSV、JSON或数据库连接
  3. 定义处理流程: 配置ETL处理器链
  4. 执行构建: 提交构建任务
  5. 监控进度: 查看构建状态和日志

4.3 Reasoner模块(逻辑推理) ​

Reasoner模块提供基于逻辑规则的推理能力。

三层架构 ​

  1. KGDSL层: 知识图谱领域专用语言

    • 解析DSL语句
    • 语义验证
  2. 逻辑层: 逻辑查询计划

    • PatternScan(模式扫描)
    • LinkedExpand(链接扩展)
    • Filter(过滤)
    • Project(投影)
    • Aggregate(聚合)
  3. 物理层: 物理执行计划

    • Unfold/Fold(展开/折叠)
    • Join(连接)
    • 与图存储交互

KGDSL示例 ​

kgdsl
// 查询:找出在某公司工作的所有员工
Define (s:Person)-[p:workAt]->(o:Company)/o.name='阿里巴巴'
Rule: employees = s

// 查询:通过多跳关系推理
Define (p1:Person)-[:friendOf]->(p2:Person)-[:friendOf]->(p3:Person)
Rule: potentialFriends = (p1, p3)

4.4 Cloudext模块(云适配层) ​

Cloudext提供可插拔的基础设施适配。

抽象接口 ​

java
// 图存储接口
public interface LPGDataQueryService {
    List<LPGRecord> queryRecord(BaseLPGRecordQuery query);
}

public interface LPGDataManipulationService {
    void insert(LPGRecordStruct record);
    void update(LPGRecordStruct record);
    void delete(LPGRecordQuery query);
}

实现适配器 ​

功能接口实现
图存储LPGGraphStoreNeo4jAdapter, TuGraphAdapter
搜索引擎SearchEngineElasticsearchAdapter, Neo4jAdapter
缓存CacheRedisAdapter
对象存储ObjectStorageMinIOAdapter, OSSAdapter

5. API接口说明 ​

5.1 Schema管理接口 ​

5.1.1 创建/修改Schema ​

接口: POST /public/v1/schema/alterSchema

请求参数:

json
{
  "projectId": 1,
  "schemaDraft": {
    "alterSpgTypes": [
      {
        "name": "Person",
        "nameZh": "人物",
        "spgTypeEnum": "ENTITY_TYPE",
        "alterOperation": "CREATE",
        "properties": [
          {
            "name": "name",
            "nameZh": "姓名",
            "objectTypeRef": {
              "name": "Text"
            },
            "alterOperation": "CREATE"
          }
        ],
        "relations": [
          {
            "name": "workAt",
            "nameZh": "工作于",
            "objectTypeRef": {
              "name": "Company"
            },
            "alterOperation": "CREATE"
          }
        ]
      }
    ]
  }
}

响应:

json
{
  "success": true,
  "data": true
}

5.1.2 查询项目Schema ​

接口: GET /public/v1/schema/queryProjectSchema?projectId=1

响应:

json
{
  "success": true,
  "data": {
    "projectId": 1,
    "spgTypes": [
      {
        "name": "Person",
        "nameZh": "人物",
        "properties": [...],
        "relations": [...]
      }
    ]
  }
}

5.1.3 查询SPG类型 ​

接口: GET /public/v1/schema/querySpgType?name=Person

5.2 查询接口 ​

5.2.1 查询SPG类型实例 ​

接口: POST /public/v1/query/spgType

请求参数:

json
{
  "projectId": 1,
  "spgTypeName": "Person",
  "conditions": [
    {
      "property": "name",
      "operator": "EQUALS",
      "value": "张三"
    }
  ],
  "limit": 10
}

响应:

json
{
  "success": true,
  "data": [
    {
      "id": "Person_001",
      "type": "Person",
      "properties": {
        "name": "张三",
        "age": 30
      },
      "relations": [...]
    }
  ]
}

5.3 知识构建接口 ​

5.3.1 提交构建任务 ​

接口: POST /public/v1/builder/kag/submit

请求参数:

json
{
  "projectId": 1,
  "workerNum": 1,
  "command": "python build_script.py",
  "userNumber": "user123"
}

响应:

json
{
  "success": true,
  "data": {
    "id": 100,
    "jobName": "KAG_COMMAND_user123_2025_01_15_10_30_00",
    "status": "RUNNING",
    "taskId": 1001
  }
}

5.3.2 查询构建任务状态 ​

接口: GET /public/v1/builder/getById?id=100

响应:

json
{
  "success": true,
  "data": {
    "id": 100,
    "jobName": "KAG_COMMAND_user123_2025_01_15_10_30_00",
    "status": "SUCCESS",
    "startTime": "2025-01-15 10:30:00",
    "endTime": "2025-01-15 10:35:00"
  }
}

5.3.3 搜索构建任务 ​

接口: POST /public/v1/builder/search

5.4 推理接口 ​

接口: POST /public/v1/reason/execute

请求参数:

json
{
  "projectId": 1,
  "kgdsl": "Define (s:Person)-[p:friendOf]->(o:Person) Rule: result = s",
  "parameters": {}
}

5.5 搜索接口 ​

5.5.1 实体搜索 ​

接口: POST /public/v1/search/entity

请求参数:

json
{
  "projectId": 1,
  "keyword": "张三",
  "spgTypeNames": ["Person"],
  "limit": 10
}

5.5.2 图搜索 ​

接口: POST /public/v1/search/graph


6. 使用示例 ​

6.1 完整示例:构建企业知识图谱 ​

步骤1:定义Schema ​

java
// 1. 定义Company实体类型
EntityType companyType = new EntityType(
    new BasicInfo(
        new SPGTypeIdentifier("enterprise", "Company"),
        "公司",
        "企业组织"
    ),
    ParentTypeInfo.THING,
    Arrays.asList(
        createProperty("name", "公司名称", BasicType.TEXT, IndexTypeEnum.TEXT),
        createProperty("establishDate", "成立日期", BasicType.TEXT, IndexTypeEnum.TEXT),
        createProperty("industry", "所属行业", BasicType.TEXT, IndexTypeEnum.TEXT)
    ),
    null,
    null
);

// 2. 定义Person实体类型
EntityType personType = new EntityType(
    new BasicInfo(
        new SPGTypeIdentifier("enterprise", "Person"),
        "人物",
        "自然人"
    ),
    ParentTypeInfo.THING,
    Arrays.asList(
        createProperty("name", "姓名", BasicType.TEXT, IndexTypeEnum.TEXT),
        createProperty("age", "年龄", BasicType.INTEGER, IndexTypeEnum.EXACT)
    ),
    Arrays.asList(
        createRelation("workAt", "工作于", companyType.toRef())
    ),
    null
);

// 3. 提交Schema
SchemaAlterRequest request = new SchemaAlterRequest();
request.setProjectId(1L);
SchemaDraft draft = new SchemaDraft();
draft.setAlterSpgTypes(Arrays.asList(companyType, personType));
request.setSchemaDraft(draft);

schemaManager.alterSchema(request);

步骤2:准备数据 ​

创建CSV文件 companies.csv:

csv
id,name,establishDate,industry
C001,阿里巴巴,1999-09-09,互联网
C002,腾讯,1998-11-11,互联网

创建CSV文件 persons.csv:

csv
id,name,age,companyId
P001,张三,30,C001
P002,李四,28,C002

步骤3:构建知识 ​

python
# build_script.py
from knext.builder import KnowledgeBuilder

# 初始化构建器
builder = KnowledgeBuilder(project_id=1)

# 加载公司数据
builder.load_csv('companies.csv', 'Company', {
    'id': 'id',
    'name': 'name',
    'establishDate': 'establishDate',
    'industry': 'industry'
})

# 加载人员数据
builder.load_csv('persons.csv', 'Person', {
    'id': 'id',
    'name': 'name',
    'age': 'age'
})

# 构建关系
builder.create_relation('Person', 'workAt', 'Company', {
    'from_id_field': 'id',
    'to_id_field': 'companyId'
})

# 执行构建
builder.execute()

步骤4:查询知识 ​

java
// 查询在阿里巴巴工作的员工
SPGTypeQueryRequest queryRequest = new SPGTypeQueryRequest();
queryRequest.setProjectId(1L);
queryRequest.setSpgTypeName("Person");
queryRequest.setConditions(Arrays.asList(
    new QueryCondition("workAt.name", "EQUALS", "阿里巴巴")
));

List<SPGTypeInstance> result = queryManager.query(queryRequest);

6.2 示例:使用KGDSL推理 ​

java
// 推理:找出可能认识的人(通过共同朋友)
String kgdsl = """
    Define (p1:Person)-[:friendOf]->(mutual:Person)-[:friendOf]->(p2:Person)
    Constraint {
        p1.id != p2.id
    }
    Rule: potentialFriend = (p1, p2, mutual)
""";

ReasoningRequest request = new ReasoningRequest();
request.setProjectId(1L);
request.setKgdsl(kgdsl);

ReasoningResult result = reasonerManager.reason(request);

6.3 示例:实体搜索 ​

java
// 全文搜索人物
SearchRequest searchRequest = new SearchRequest();
searchRequest.setProjectId(1L);
searchRequest.setKeyword("张三");
searchRequest.setSpgTypeNames(Arrays.asList("Person"));
searchRequest.setLimit(10);

SearchResponse response = searchManager.search(searchRequest);

7. 开发指南 ​

7.1 扩展自定义数据源 ​

实现SourceReader接口 ​

java
public class CustomSourceReader implements SourceReader {

    @Override
    public void init(Map<String, Object> config) {
        // 初始化配置
    }

    @Override
    public List<Record> read() {
        // 读取数据并返回记录列表
        List<Record> records = new ArrayList<>();
        // ... 实现数据读取逻辑
        return records;
    }

    @Override
    public void close() {
        // 关闭资源
    }
}

注册自定义Reader ​

java
@Component
public class CustomReaderFactory implements SourceReaderFactory {

    @Override
    public String getType() {
        return "CUSTOM";
    }

    @Override
    public SourceReader create(Map<String, Object> config) {
        return new CustomSourceReader();
    }
}

7.2 扩展自定义图存储 ​

实现GraphStore接口 ​

java
public class CustomGraphStoreAdapter implements LPGGraphStore {

    @Override
    public void init(String connectionUrl) {
        // 初始化连接
    }

    @Override
    public List<LPGRecord> query(BaseLPGRecordQuery query) {
        // 实现查询逻辑
        return null;
    }

    @Override
    public void insert(LPGRecordStruct record) {
        // 实现插入逻辑
    }

    @Override
    public void update(LPGRecordStruct record) {
        // 实现更新逻辑
    }

    @Override
    public void delete(LPGRecordQuery query) {
        // 实现删除逻辑
    }
}

注册适配器 ​

在 application.properties 中配置:

properties
cloudext.graphstore.driver=com.yourcompany.CustomGraphStoreAdapter
cloudext.graphstore.url=custom://localhost:1234?param=value

7.3 开发自定义Processor ​

python
# custom_processor.py
from knext.builder.processor import BaseProcessor

class CustomEntityProcessor(BaseProcessor):

    def process(self, record):
        """
        处理单条记录

        Args:
            record: 输入记录

        Returns:
            处理后的记录
        """
        # 实现自定义处理逻辑
        # 例如:实体链接、NLP处理等

        entity_name = record.get('name')
        # 调用NLP模型进行处理
        processed_name = self.normalize_entity(entity_name)

        record['normalized_name'] = processed_name
        return record

    def normalize_entity(self, name):
        # 实现实体归一化逻辑
        return name.strip().upper()

7.4 项目结构最佳实践 ​

your-kg-project/
├── schema/                 # Schema定义
│   ├── entity_types/
│   │   ├── person.json
│   │   └── company.json
│   └── schema_draft.json
├── data/                   # 数据文件
│   ├── raw/               # 原始数据
│   ├── processed/         # 处理后数据
│   └── mappings/          # 映射配置
├── builders/              # 构建脚本
│   ├── extract.py
│   ├── transform.py
│   └── load.py
├── reasoners/             # 推理规则
│   └── rules.kgdsl
├── processors/            # 自定义处理器
│   └── custom_processor.py
└── config/                # 配置文件
    └── builder_config.json

8. 常见问题 ​

8.1 部署相关 ​

Q: 如何切换图数据库从Neo4j到TuGraph?

A: 修改配置文件中的 cloudext.graphstore.url:

properties
# Neo4j
cloudext.graphstore.url=neo4j://host:7687?user=neo4j&password=pwd&database=neo4j

# TuGraph
cloudext.graphstore.url=tugraph://host:7687?user=admin&password=pwd&database=default

Q: 如何配置分布式部署?

A: OpenSPG支持通过调度器进行分布式任务调度:

properties
# 使用外部调度器(如Kubernetes)
scheduler.handler.type=k8s
scheduler.metadata.store.type=mysql

8.2 性能相关 ​

Q: 如何优化大规模数据的构建性能?

A:

  1. 增加并行度:workerNum 参数设置更大值
  2. 使用批量写入:配置 batchSize
  3. 启用缓存:配置Redis缓存
  4. 分片处理:将大文件拆分成多个小文件
json
{
  "workerNum": 10,
  "batchSize": 1000,
  "enableCache": true
}

Q: 查询性能慢怎么办?

A:

  1. 为常用属性添加索引
  2. 使用合适的IndexType(EXACT, TEXT, VECTOR等)
  3. 优化KGDSL查询语句
  4. 启用查询缓存

8.3 Schema相关 ​

Q: 如何修改已有的Schema?

A: 使用 AlterOperation:

java
Property property = existingProperty;
property.setAlterOperation(AlterOperationEnum.UPDATE);

EntityType entityType = existingEntityType;
entityType.setAlterOperation(AlterOperationEnum.UPDATE);

Q: 支持哪些AlterOperation?

A:

  • CREATE: 创建新的类型/属性/关系
  • UPDATE: 更新已有的
  • DELETE: 删除已有的

8.4 数据构建相关 ​

Q: 支持哪些数据源格式?

A:

  • CSV文件
  • JSON文件
  • 关系数据库(MySQL, PostgreSQL等)
  • Hive表
  • ODPS(阿里云MaxCompute)
  • 自定义数据源(通过扩展接口)

Q: 如何处理脏数据?

A: 在Processor中实现数据清洗逻辑:

python
class DataCleanProcessor(BaseProcessor):
    def process(self, record):
        # 过滤空值
        if not record.get('name'):
            return None

        # 数据标准化
        record['name'] = record['name'].strip()

        return record

8.5 推理相关 ​

Q: KGDSL语法在哪里查看?

A: 参考文档:

Q: 如何调试推理规则?

A:

  1. 使用推理规则解释功能
  2. 查看执行计划
  3. 启用详细日志
properties
logging.level.com.antgroup.openspg.reasoner=DEBUG

8.6 集成相关 ​

Q: 如何与大语言模型(LLM)集成?

A: OpenSPG提供KAG(Knowledge Augmented Generation)能力:

python
from knext.kag import KAGEngine

# 初始化KAG引擎
kag = KAGEngine(project_id=1, llm_config={
    'model': 'gpt-4',
    'api_key': 'your-api-key'
})

# 知识增强查询
result = kag.query("阿里巴巴的创始人是谁?")

Q: 支持哪些向量数据库?

A: 通过IndexType.VECTOR支持:

  • Neo4j Vector Index
  • Elasticsearch Vector Search
  • 自定义向量数据库(通过扩展接口)

附录 ​

A. 参考资源 ​

B. 示例项目 ​

C. 社区支持 ​

D. 贡献指南 ​

查看贡献指南:https://openspg.yuque.com/ndx6g9/docs/yv8rahc3dewb1gy8

E. 引用 ​

如果您在研究中使用OpenSPG,请引用:

bibtex
@article{liang2024kag,
  title={KAG: Boosting LLMs in Professional Domains via Knowledge Augmented Generation},
  author={Liang, Lei and Sun, Mengshu and Gui, Zhengke and Zhu, Zhongshu and Jiang, Zhouyu and Zhong, Ling and Zhao, Peilong and Bo, Zhongpu and Yang, Jin and others},
  journal={arXiv preprint arXiv:2409.13731},
  year={2024}
}

版本信息 ​

  • 文档版本: 1.0
  • OpenSPG版本: 0.8
  • 最后更新: 2025-12-13

许可证 ​

本项目采用 Apache License 2.0 开源协议。