mloda-ai/open-kgo
GitHub: mloda-ai/open-kgo
为 mloda 框架提供统一的知识图谱连接器与本体语义发现引擎,支持九大类图数据源的声明式查询及基于电路模型的实体评分与多跳路径排序。
Stars: 9 | Forks: 3
[](LICENSE)
[](https://github.com/mloda-ai/mloda)
[](https://www.python.org/)
# open-kgo
用于 [mloda](https://github.com/mloda-ai/mloda) 的开放知识图谱和本体插件:包含九大连接器家族,涵盖从 SPARQL 端点到 SBOM 再到 Agent 记忆的整个知识图谱领域,所有这些都隐藏在一个声明式的 `Feature` 接口背后。每个连接器和演示都通过内存库或已提交的测试数据离线运行。无需 Docker,无需网络。
## 概览
| 章节 | 你将看到的内容 |
|---|---|
| [快速开始](#quickstart) | 在一分钟内对内置的示例文件运行 SPARQL 查询 |
| [九大连接器家族](#the-nine-connector-families) | 本仓库的核心:包含 9 大类知识图谱连接器的分类法,每类包含两个插件 |
| [语义场 — 第 2 层](#semantic-fields--layer-2) | 通过直流电路模型进行连续的、基于 schema 的实体评分 |
| [DiscoveryEngine — 第 3 层](#discoveryengine--layer-3) | 在电磁场上进行 Beam Search — 排序的类型化路径,无需调用 LLM |
| [演示](#demos) | Marimo notebooks 和评估工具,全部离线运行 |
| [数据与致谢](#data-and-acknowledgments) | 示例数据的来源 |
| [开发环境设置](#development-setup) | uv, tox 以及各项单独的检查 |
| [相关仓库与文档](#related-repositories-and-documentation) | mloda 核心、插件注册表和开发指南 |
## 快速开始
从 PyPI 安装连接器,并对一个小型 Turtle 文件运行 SPARQL 查询:
```
pip install "open-kgo[kg-all]"
```
(如果是通过克隆仓库来操作?请使用 `uv sync --extra kg-all`,参见[开发环境设置](#development-setup)。)
```
from pathlib import Path
from mloda.user import DataAccessCollection, Feature, Options, mloda
# 导入插件模块会注册 rdflib_sparql 特性组。
import open_kgo.feature_groups.kg.rdf.rdflib_sparql # noqa: F401
from open_kgo.feature_groups.kg.base import PythonDictFramework
# 指向任意 RDF 文件。此处:一个即时编写的三重三元组示例。
ttl = Path("sample.ttl")
ttl.write_text(
"@prefix foaf: .\n"
"@prefix ex: .\n"
"ex:alice foaf:knows ex:bob .\n"
"ex:bob foaf:knows ex:carol .\n"
)
feature = Feature(
"rdflib_sparql__knows",
options=Options(context={
"query_text": "PREFIX foaf: "
"SELECT ?s ?o WHERE { ?s foaf:knows ?o }",
}),
)
partitions = mloda.run_all(
[feature],
compute_frameworks={PythonDictFramework},
data_access_collection=DataAccessCollection(
credentials=[{"rdflib_sparql": {"locator": str(ttl), "result_limit": 100}}],
),
)
for partition in partitions:
for row in partition.get(feature.name, []):
print(row)
```
将 `rdflib_sparql` 替换为以下九大连接器家族中的任何一个:对 `mloda.run_all` 使用相同的 `Feature` 形状,只需更换读取器。
## 九大连接器家族
`open_kgo/feature_groups/kg/` 提供了一个源自 103 个系统调研的连接器分类法。每个家族都包含一个共享的读取器和 feature-group 基类,以及在内存库或本地文件数据上运行的 **两个** 具体插件:
| 家族 | 连接对象 | 具体插件 |
|---|---|---|
| `network_pg` | 带有供应商查询语言的属性图数据库(Neo4j, Memgraph, Neptune 等) | `KuzuCypherReader`, `GrandCypherReader` |
| `rdf` | 通过 SPARQL 查询的 RDF 三元组存储 | `RdfLibSparqlReader`, `OxigraphSparqlReader` |
| `embedded` | 没有网络端点的进程内图库 | `NetworkxEmbeddedReader`, `IGraphEmbeddedReader` |
| `rest_public` | 公共 REST(非 SPARQL)知识图谱 API(OpenAlex, ConceptNet, STRING 等) | `FileFixtureRestReader`, `FileFixturePagedRestReader` |
| `lineage` | 元数据和数据血缘图(dbt, OpenLineage, DataHub 等) | `DbtManifestReader`, `OpenLineageReader` |
| `code_build` | 代码、构建和 SBOM 依赖图(CycloneDX, SPDX 等) | `CycloneDxSbomReader`, `SpdxSbomReader` |
| `saas_authz` | SaaS 和授权元组存储(OpenFGA, SpiceDB, Microsoft Graph 等) | `InProcessTupleStoreReader`, `PaginatedTupleStoreReader` |
| `agent_memory` | LLM Agent 记忆和 GraphRAG 图(Letta, Zep, Mem0 等) | `NetworkxMemoryReader`, `GraphWalkMemoryReader` |
| `citation_rest` | 引用和科学 REST API(Reactome, OpenAlex citations 等) | `FileFixtureCitationReader`, `PaginatedCitationReader` |
请参阅 [`open_kgo/feature_groups/kg/README.md`](open_kgo/feature_groups/kg/README.md) 以获取完整的家族映射、插件结构解析以及该原型验证和不验证的内容。
使用以下命令安装所有 KG 扩展:`pip install "open-kgo[kg-all]"`(通过克隆仓库:`uv sync --extra kg-all`)。
## 语义场 — 第 2 层
连接器家族(第 1 层验证)回答的问题是:*“此遍历是否有效?”* — 二元的“是/否”。
**SemanticField**(第 2 层)回答的是:*“此实体与我的查询有多大相关性?”* — 一个基于直流电路理论的连续评分。
知识图谱被建模为电阻网络。本体中声明的关系权重被转换为电导。一个查询由两个锚点节点表示 — 一个 **源**(高压)和一个 **汇**(低压,接地)。求解器通过基于电导加权的图拉普拉斯算子找到每个实体的电势,然后根据实体在源和汇之间承载的电流对其进行评分。
**为什么用电流?** 电流只会流经连接 *两个* 锚点的实体。仅连接到一侧的实体会浮动到该侧的极值电压 — 零电势差,零电流,自动被排除。无需进行关系类型过滤;电路拓扑结构强制执行了逻辑“与”(AND)的约束。
```
from open_kgo.feature_groups.kg.ontology import SemanticField
# AND 查询:Nolan 执导的 Sci-Fi 电影
scores = SemanticField.compute_and(
namespace="metaqa",
edges=subgraph_edges, # 2-hop neighbourhood of both anchors
source={"Nolan": 1.0}, # high-voltage anchor
sink={"Sci-Fi": 0.0}, # ground
)
# → {"Interstellar": 0.394, "Inception": 0.312, "Dark Knight": 0.0, ...}
```
关系权重在本体 YAML 中声明,并直接作为电导流入求解器:
```
relationships:
directed_by: { domain: Movie, range: Person, weight: 0.9 }
has_genre: { domain: Movie, range: Genre, weight: 0.7 }
has_tags: { domain: Movie, range: Tag, weight: 0.2 }
```
求解器是纯 Python(不依赖 numpy)实现的,并带有一个可选的 numba JIT 内核,可在约 5,000 个节点的子图中提供 **70 倍的加速**;当缺少 numba 时,它会自动静默回退。
| 层级 | 功能 | 状态 |
|---|---|---|
| L1 — OntologyRegistry | 二元有效/无效边检查,由 YAML 声明 | 已构建 |
| L2 — SemanticField | 通过直流电路模型进行连续实体评分 | 已构建 |
| L3 — Discovery Engine | 通过场强度引导多跳遍历 | 已构建 |
安装:`pip install "open-kgo[kg-semantic-field]"`(通过克隆仓库:`uv sync --extra kg-semantic-field`)
完整的可视化讲解:[`demo/semantic_field_explainer.html`](demo/semantic_field_explainer.html) — 在任意浏览器中打开,无需服务器。
## DiscoveryEngine — 第 3 层
**DiscoveryEngine**(第 3 层)回答的是:*“在图中从源到目标的最佳路径是什么?”* — 排序的类型化路径,由第 2 层的电磁场梯度引导。无需 LLM 调用,无需预言机评分,无需采样。
第 2 层已经解决了最困难的问题:它计算出了每个实体的电压。相邻节点 `i` 和 `j` 之间的边电流为 `G(i,j) × |V(i) - V(j)|`。该电流 **即是 Beam Search 的启发式函数** — 承载源和汇之间最多信号的边会被优先扩展。死胡同分支承载的电流为零,永远不会进入 Beam。
路径评分使用 **瓶颈电流** — 路径上的最小边电流。只有当路径中的每一跳都具有强导电性时,该路径才会获得高分,这使得评分具有可解释性:它就是导电链条中最薄弱的环节。
```
from open_kgo.feature_groups.kg.ontology import DiscoveryEngine
# 排名路径:哪些电影将 Nolan 与 Sci-Fi 连接起来?
paths = DiscoveryEngine.find_paths(
namespace="movie",
edges=subgraph_edges,
source={"Christopher Nolan": 1.0}, # high-voltage anchor
sink={"Science Fiction": 0.0}, # ground
beam_width=5,
max_depth=4,
)
# → [
# DiscoveredPath(nodes=("Christopher Nolan", "Inception", "Science Fiction"),
# relations=("directed_by", "has_genre"), score=0.301),
# ...
# ]
# 最小 current-carrying 子图 — 解释电路
circuit_edges = DiscoveryEngine.extract_circuit(
namespace="movie",
edges=subgraph_edges,
source={"Christopher Nolan": 1.0},
sink={"Science Fiction": 0.0},
current_threshold=0.01,
)
# → 116 条边中的 25 条 — 不包含死胡同演员和无关类型
```
### 它的应用场景
**无需 LLM(纯图分析):**
- **多跳路径查找** — 找出两个实体之间所有按语义强度排序的类型化路径,而不仅仅是最短跳数。
- **影响分析** — 提取连接源和目标的最小子图。自动修剪死胡同分支(零电势差 = 零电流)。
- **瓶颈检测** — 最佳路径上电流最小的边是最薄弱的语义链接。将其标记出来以进行数据策展或本体权重调优。
- **子图提取** — `extract_circuit` 通过一次操作返回一个紧凑的、针对特定查询的子图。比社区检测成本更低、目标更明确。
**结合 LLM(上下文与循环工程):**
- **上下文工程** — 将 `extract_circuit` 的输出交给 LLM,而不是一堆扁平的三元组或静态的 GraphRAG 社区。该电路已经为 *这个* 查询过滤出了活跃的边。上下文窗口更小,精确度更高。
- **循环工程** — 在 Agent 迭代之间,使用更新后的锚点重新求解电磁场,并再次调用 `find_paths`。上一步的路径成为下一步的锚点候选者。电磁场携带了累积的相关性信号并向前传递。
- **GraphRAG 替代方案** — GraphRAG 会在整个图上预计算社区摘要,并在查询时提供最近的社区。而电磁场是根据每个查询重新求解的:源和汇锚点对电磁场进行参数化,因此每次调用都会获得针对特定问题调优的子图,而不是最近的预计算分区。
- **Think-on-Graph 改进** — Think-on-Graph 通过在每一跳询问 LLM(每探索一条边进行一次 LLM 调用)来对候选扩展进行排序。`find_paths` 使用预计算的边电流替代了这一点:在遍历过程中实现了零 LLM 调用,同时获得了相同的排序结果。
| 层级 | 功能 | 状态 |
|---|---|---|
| L1 — OntologyRegistry | 二元有效/无效边检查,由 YAML 声明 | 已构建 |
| L2 — SemanticField | 通过直流电路模型进行连续实体评分 | 已构建 |
| L3 — DiscoveryEngine | 在电磁场上进行 Beam Search,排序的类型化路径 | 已构建 |
安装:`uv sync --extra kg-semantic-field`
交互式演示:`marimo edit demo/demo_discovery.py`
## 演示
三个 Marimo notebooks 和两个评估工具位于 `demo/` 目录下:
- `demo/demo_kg_connectors.py`:针对内置测试数据,对全部 9 个家族的表层导览。
- `demo/demo_kg_build_repo.py`:基于此仓库构建 RDF 图(文件系统 `repo:contains` + Python `repo:imports`),序列化为 Turtle 格式,并通过 `mloda.run_all` 在 `RdfLibSparqlReader` 上运行五个 SPARQL 查询。
- `demo/demo_kg_ontology.py`:端到端演示本体层。
- `demo/demo_semantic_field.py`:SemanticField 第 2 层 — 针对基于 MetaQA 的交互式导演与流派查询,支持实时评分。
- `demo/demo_discovery.py`:DiscoveryEngine 第 3 层 — 在电磁场上进行 Beam Search,针对示例图执行 find_paths 和 extract_circuit。
- `demo/semantic_field_explainer.html`:SemanticField 的完整可视化讲解 — 电路图、层级堆栈、为什么使用电磁场、单跳/双跳/多跳示例、测试结果。可在任意浏览器中打开。
- `demo/eval_arch1_vs_arch2.py` 和 `demo/eval_qa_accuracy.py`:用于比较普通遍历与本体引导遍历的评估工具。
安装演示扩展并打开任意 notebook:
```
uv sync --extra demo
marimo edit demo/demo_kg_connectors.py
```
每个演示都针对小型且已提交的示例图离线运行:无需下载,
无需网络,无需外部服务。
## 数据与致谢
本体演示和两个评估工具都是针对一份小型的、手工编写的公开电影事实样本(`demo/data/sample_kb.txt`)运行的,这些样本采用 MetaQA 数据集(Zhang, Yuyu 等人,"Variational
Reasoning for Question Answering with Knowledge Graph", AAAI 2018,
https://github.com/yuyuz/MetaQA)的三元组格式编写。该样本已提交至此仓库,并非
衍生自 MetaQA 数据集文件。这些 notebook 在启动时调用
`demo.data.ensure_data()`,它会离线构建样本子图。
若要针对完整的 MetaQA 基准测试运行(其授权协议为
[CC BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode),此处未
重新分发),请参阅 [`demo/data/README.md`](demo/data/README.md)。
## 开发环境设置
**安装 uv**(如果尚未安装):
```
curl -LsSf https://astral.sh/uv/install.sh | sh
```
**创建虚拟环境并安装依赖:**
```
uv venv
source .venv/bin/activate
uv sync --all-extras
```
**使用 tox 运行所有检查:**
```
uv tool install tox --with tox-uv
tox
```
### 运行各项单独检查
```
pytest
ruff format --check --line-length 120 .
ruff check .
mypy --strict --ignore-missing-imports .
bandit -c pyproject.toml -r -q .
```
## 相关仓库与文档
- **[mloda](https://github.com/mloda-ai/mloda)**: 用于开放数据访问的核心库。声明式地定义你需要什么数据,而不是如何获取它。参见 [mloda.ai](https://mloda.ai) 了解概览和业务背景,参见 [文档](https://mloda-ai.github.io/mloda/) 获取详细指南。
- **[mloda-registry](https://github.com/mloda-ai/mloda-registry)**: 用于发现和共享 mloda 插的核心枢纽。
- **[插件开发指南](https://github.com/mloda-ai/mloda-registry/tree/main/docs/guides/)**: 了解如何构建 FeatureGroups, ComputeFrameworks 和 Extenders。
- **[Claude Code skills](https://github.com/mloda-ai/mloda-registry/tree/main/.claude/skills/)**: 为 Claude Code 用户提供辅助插件开发。
标签:Python, Terrascan, 插件, 无后门, 本体, 特权检测, 自动化治理, 语义网, 逆向工具