首页
/ graphify 导出与基准测试参考指南:从知识图谱到 Neo4j、FalkorDB、MCP 与 Token 压缩实测

graphify 导出与基准测试参考指南:从知识图谱到 Neo4j、FalkorDB、MCP 与 Token 压缩实测

2026-09-07 15:43:21作者:尤辰城Agatha

本文基于 graphify 仓库中 Kiro 等编码 Agent 的 skill reference 文档《graphify reference: extra exports and benchmark》编写。该文档定义的是 graphify 在图构建完成之后的「附加导出与基准测试」环节:当构建命令带有 --wiki--neo4j--neo4j-push--falkordb--falkordb-push--svg--graphml--mcp 任一标志,或语料规模大到值得做 token 压缩评测时,逐个执行相应导出步骤。读完本文,你将掌握每种导出格式的触发条件、命令形态、输出产物与底层实现,能把一个已生成的 graph.json 自如地转成 Obsidian Wiki、Cypher 文件或直接推送进图数据库、静态 SVG/GraphML,甚至以 MCP 服务的形式开放给其他 Agent 实时查询。

一、导出子命令的触发条件与整体编排

在 graphify 的 skill 编排流程中,导出并不是 graphify build 的默认行为,而是逐标志独立触发的附加步骤。每个 export 步骤只在自己的 flag 出现时运行("Each step runs only for its own flag")。从 CLI 实现看,所有附加导出统一收敛到 graphify export <format> 这一条子命令树,支持的格式为 htmlcallflow-htmlobsidianwikisvggraphmlneo4jfalkordb,见 cli.py 的 export 分支

export 系列默认从 graphify-out/ 读取构建产物:

  • 图本体:graphify-out/graph.json
  • 社区标签(人工或 LLM 策展的可读命名):graphify-out/.graphify_labels.json
  • 社区划分与凝聚度分析:graphify-out/.graphify_analysis.json
  • 语料规模探测:graphify-out/.graphify_detect.json

共用参数 --graph PATH--labels PATH 允许改指向其它目录的产物;若显式给出 --graph,标签文件默认跟着图所在目录走(labels_path = graph_out_dir / ".graphify_labels.json")。因此只要 graph.json 存在,以下命令基本都可独立回放,不一定需要重新做一次全量构建。

下面按 reference 文档的 Step 编号依次展开。

二、Step 6b:Wiki 导出(--wiki

Wiki 导出只在构建命令显式携带 --wiki 时运行,并且必须在 Step 9 清理之前执行——因为它在运行期仍需要 .graphify_labels.json 里的策展社区命名。

graphify export wiki

对应实现位于 export.py 的 wiki 分发逻辑,真正的写入函数为 graphify.wiki.to_wiki。它把图谱渲染成一组面向 Agent 的 Markdown 文章,输出到 <输出目录>/wiki/

  • 每个社区生成一篇概览文章;
  • 生成 wiki/index.md 作为 Agent 入口页(CLI 会明确打印 index.md -> agent entry point)。

两点易踩坑的前提条件:

  1. 必须有社区分析数据。若 .graphify_analysis.json 缺失或为空,CLI 会拒绝导出并提示"refusing to export wiki to prevent data loss",要求先运行 graphify extract .graphify cluster-only . 重新生成社区数据。
  2. 必须在清理前运行。Skill 编排里 wiki 属于 Step 6b(早于 Step 9 cleanup),就是为了保住 .graphify_labels.json;一旦该文件被清掉,社区文章将退化回 Community N 这种默认编号名,丢失策展语义。

三、Step 7:Neo4j 导出(--neo4j / --neo4j-push

Neo4j 有两个行为完全不同的分支:生成可移植 Cypher 文件,或直推运行中的实例

3.1 生成 Cypher 文件(--neo4j

graphify export neo4j

此命令不连接任何数据库,仅调用 to_cypher 把图谱序列化为 graphify-out/cypher.txt,供你之后用 Neo4j 官方批量导入工具加载:

cypher-shell < graphify-out/cypher.txt

从源码可以看清其生成策略:

  • 每个节点产出一条 MERGE (n:FileType {id: '...', label: '...'});——用 MERGE 而非 CREATE重复执行不会产生重复节点
  • 每条边产出 MATCH (a {id}), (b {id}) MERGE (a)-[:REL {confidence: '...'}]->(b);,边上的 confidence(EXTRACTED / INFERRED / AMBIGUOUS)会作为关系属性原样保留;
  • 节点类型取自节点的 file_type,例如 PythonMarkdown;关系类型由 relation 大写化而来,兜底为 RELATES_TO

值得强调的是其安全设计(见 _cypher_escape / _cypher_label):节点 label、id 等字面量位置的内容会做引号与换行的转义,而标签名、关系类型这类标识符位置的值无法在 Cypher 中安全转义,因此采用白名单式清洗(仅保留 [A-Za-z0-9_]、必须以字母开头,否则回退到安全常量),从根上避免把语料里不可信内容注入成可执行的 MATCH/DELETE 语句。这一点与 graphify 一贯的"来源内容即潜在攻击面"安全基线是一致的。

3.2 直推运行中的实例(--neo4j-push <uri>

graphify export neo4j --push bolt://localhost:7687 --user neo4j --password PASSWORD

当同时提供 --push URI 时,走的是 push_to_neo4j,它通过官方 neo4j Python driver 建立会话、逐节点逐边 upsert:

  • 默认 URIbolt://localhost:7687
  • 默认用户名neo4j
  • 全程使用参数化 MERGE ... SET n += $props,幂等安全;
  • 返回并打印实际写入的 nodes / edges 计数。

关于密码的工程化细节:CLI 解析器为 push 类连接准备了 --push / --user / --password,并优先从环境变量 NEO4J_PASSWORD 读取密码——这是为了不让口令出现在 argv(进而暴露在 ps 输出与 shell history 里);显式的 --password 仍可覆盖环境变量。reference 文档也提醒:凭据未提供时应先向用户询问

四、Step 7a:FalkorDB 导出(--falkordb / --falkordb-push

FalkorDB 分支刻意与 Neo4j 区分对待,因为它虽然是 OpenCypher 兼容,执行模型却不同。

4.1 生成 Cypher 文件(--falkordb

graphify export falkordb

同样产出 cypher.txt。reference 文档明确警告了一个实操误区:FalkorDB 的 GRAPH.QUERY 一次只执行一条语句,没有类似 cypher-shell 的整脚本批量导入;因此当你真正想装载一个图时,cypher.txt 只是"便携产物",优先用 --push 直推

4.2 直推运行中的实例(--falkordb-push <uri>

graphify export falkordb --push falkordb://localhost:6379

对应的 push_to_falkordb 与 Neo4j 路径共享同一套 MERGE/SET upsert 语义,但差异明显:

  • 连接方式:用 FalkorDB(host, port, ...) SDK 而非 bolt driver;URI 只解析 host/port,scheme 是信息性的——falkordb://localhost:6379redis://localhost:6379 甚至裸的 localhost:6379 三者等价,默认端口 6379;
  • 命名图:通过 db.select_graph(graph_name) 选择图,目标图默认名为 graphify
  • 鉴权可选:FalkorDB 默认无凭据即可运行,因此 user/password 可缺省;仅在实例确实要求认证时才向用户询问。实现上只有当提供了 password 时才会带上 username,避免把 Neo4j 风格的默认用户误传给 FalkorDB 而被当成未知 ACL 用户拒绝(URI 中内嵌凭据优先级最高);
  • 无 session 对象:每条查询直接 graph.query(cypher, params)

密钥同样支持环境变量 FALKORDB_PASSWORD,且与 NEO4J_PASSWORD 按子命令分流,互不串扰。

五、Step 7b:SVG 导出(--svg

graphify export svg

生成 graphify-out/graph.svg。底层 to_svg 使用 matplotlib(Agg 后端)+ spring layout(seed=42 固定随机性)渲染静态矢量图,主要特征:

  • 体积轻、零依赖 JS:可直接嵌入 Obsidian 笔记、Notion、GitHub README 等任意 Markdown 渲染器;
  • 节点大小随度(degree)缩放,节点越多关系越多的枢纽符号越大;
  • 节点颜色与 HTML 导出一致(复用 COMMUNITY_COLORS),便于两套产物对照阅读;
  • 边按置信度区分线型EXTRACTED 画实线,非 EXTRACTED 画虚线且降低透明度,让"确定性事实"与"推断关系"在视觉上一目了然;
  • 若带社区标签则自动渲染图例(标注每个社区名及其成员数)。

前置条件是本机装有 matplotlib(pip install matplotlib),缺失时会抛出明确的 ImportError 提示。若读者使用 skill 化流程,只需保证生成 graph.svg 的源图存在——CLI 会自动从 graph.json 及随附的社区属性重建社区划分,因此即使 .graphify_analysis.json 被清理,SVG/GraphML 等导出仍能工作(这部分回退逻辑见 cli.py 的社区重建分支)。

六、Step 7c:GraphML 导出(--graphml

graphify export graphml

生成 graphify-out/graph.graphml,面向 Gephi、yEd 等桌面图分析/可视化工具。实现 to_graphml 的几个关键点:

  • 社区 ID 写成节点属性 community,这样 Gephi 可直接按社区着色;
  • 把边的 confidence(EXTRACTED/INFERRED/AMBIGUOUS)保留为边属性
  • 会剔除下划线开头的内部标记(如 AST 来源 _origin、方向标记 _src/_tgt),不让持久化/运行期细节泄漏进产物;
  • 对属性值做三层归一化:None -> ""dict/list -> JSON 字符串(GraphML 不支持非标量,见 #1831)、字符串再做 XML 1.0 非法字符清洗——否则一个标签里混入的 ANSI 转义序列会让整次导出在 nx.write_graphml 处崩溃;
  • 采用临时文件 + 原子替换写入,防止序列化中途出错留下 0 字节的伪完成文件。

七、Step 7d:MCP 服务器(--mcp

这是把图谱从"静态文件"升级为"可被其它 Agent 实时查询的活服务"的关键一步:

$(cat graphify-out/.graphify_python) -m graphify.serve graphify-out/graph.json

命令里的 $(cat graphify-out/.graphify_python) 会把构建时记录的 Python 解释器绝对路径展开出来,再以 python -m graphify.serve <graph.json> 方式启动一个 stdio MCP 服务器。其工具清单在 serve.py 的 MCP 注册处 可完整看到:

工具 作用
query_graph 面向自然语言问题检索子图并返回带引用的文本摘要
get_node 按 label 解析单个节点(多义时给出歧义说明)
get_neighbors 返回某节点的邻居及关系
get_community 查看节点所属社区
god_nodes 返回跨社区枢纽节点(god node)
graph_stats 图规模统计
shortest_path 两节点间最短路径

你可以把该服务挂到 Claude Desktop 或任意兼容 MCP 的 Agent 编排器上,让其它 Agent 以工具方式实时查询构建好的代码图谱。

Claude Desktop 配置的坑位说明

claude_desktop_config.json 中配置时要注意:Claude Desktop 无法执行 $(...) 命令替换,而且在 uv tool install 方式安装后,系统的 python3 通常无法 import graphify。因此配置里 command 必须填 .graphify_python 输出的绝对解释器路径

{
  "mcpServers": {
    "graphify": {
      "command": "<absolute path from: cat graphify-out/.graphify_python>",
      "args": ["-m", "graphify.serve", "/absolute/path/to/graphify-out/graph.json"]
    }
  }
}

即:先用 cat graphify-out/.graphify_python 拿到解释器绝对路径填进 command,再把 graph.json 也用绝对路径写进 args,才能避开 Claude Desktop 对相对路径与命令替换的限制。

八、Step 8:Token 削减基准测试(语料 > 5000 词时)

这一步不是导出,而是成本论证:当语料大到值得用图谱结构替代"整库塞进上下文"时,量化 graphify 的查询能省多少 token。

触发条件读取自 graphify-out/.graphify_detect.jsontotal_words 字段:

  • total_words > 5000,执行:
graphify benchmark

并把输出原样打印在对话中,向用户呈现量化的压缩收益;

  • total_words <= 5000静默跳过——reference 文档给出的理由很精辟:小语料下图谱的价值在于结构清晰而非 token 压缩,没必要跑基准。

运行 graphify benchmark 时,CLI 会尝试从 .graphify_detect.json 读取 corpus_words 供评测使用(见 benchmark 分发逻辑)。核心实现 run_benchmark 的做法是:

  1. 语料词数换算 token:corpus_tokens = words * 100 / 75(约按 100 词 ≈ 133 token);
  2. 用一组预置的示例问题,对每道问题在图上走查询管线,得到实际消耗的 query_tokens
  3. 汇总输出 corpus_words、语料 token 估算、图的节点/边数、每问题平均查询 token总削减倍数 reduction_ratio,以及逐问题的削减明细。

最终控制台报告的形态(print_benchmark)大致是:Corpus: N words -> ~M tokens (naive)Graph: X nodes, Y edgesAvg query cost: ~Z tokensReduction: Rx fewer tokens per query,下面再逐行列出每个示例问题对应的削减倍数——这组数字可以直接作为"为什么代码库要先建成图再喂给 LLM"的实证论据。若图尚未构建导致示例问题匹配不到任何节点,则会返回明确错误 No matching nodes found for sample questions. Build the graph first.

九、把导出串起来的几个注意事项

  • 产物默认落在 graphify-out/cypher.txtgraph.svggraph.graphmlwiki/ 均与 graph.json 同目录,除非用 --graph 指到其它位置;
  • 图数据库两种形态分工:文件型导出(neo4j / falkordb 不带 --push)给出可审查、可版本化的 cypher.txt,适合交付或留档;push 型适合直接装载进正在运行的实例。Neo4j 可用 cypher-shell 批量导入脚本,FalkorDB 没有等价物,故 reference 明确建议其用 --push
  • 安全性是导出层的一等公民:Cypher 字面量转义 + 标识符白名单、GraphML 的 XML 清洗与原子写、Neo4j/FalkorDB 统一的参数化 upsert、以及密码优先走环境变量,共同保证"语料里不可信的内容"不会通过导出环节变成注入向量或让整次导出静默失败;
  • 与 skill 编排的关系:本文所讲解的每一步(Step 6b/7/7a/7b/7c/7d/8)实际是 agent skill 在用户给出对应 flag 时执行的参考动作,同一个 reference 文档被同步复制到各 Agent 平台的 skill 目录中(例如 kiro 版本),保证 Claude、Kiro、Kilo 等不同前端跑出的行为一致;
  • 何时评估:真正的建图、聚类、HTML/Obsidian 导出以及最后的清理属于其它 Step,不在本文范围;你只需记住:图一旦建好,graphify export 全家族可以随时重放,MCP 服务可以让图谱在 Agent 生态里"活"起来。

如需深入这些命令背后的完整实现,推荐直接阅读 export.pyexporters/graphdb.pyserve.pybenchmark.py,其中每一处导出都带有详实的工程决策注释(从文件系统非法字符、Windows MAX_PATH 到 Cypher/XML 注入防御),是理解"生产级图导出"的上佳样本。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389