graphify 导出流水线全解:Wiki、Neo4j、FalkorDB、SVG、GraphML 与 MCP 服务的源码级实操
graphify 在完成本地 AST 抽取后,真正决定知识图谱“能走向多远”的,是它的导出层。本文以 Kilo 技能包中的 references/exports.md 参考文档为主线,完整覆盖 --wiki、--neo4j/--neo4j-push、--falkordb/--falkordb-push、--svg、--graphml、--mcp 六个导出标志对应的命令、默认值与凭据处理方式,并逐条对照 graphify/cli.py、graphify/exporters/graphdb.py 等源码,说明每种导出的底层实现与可验证的测试依据。读完你可以独立完成从生成 Wiki 到把图推送到图数据库、再到让其他 Agent 通过 MCP 实时查询图谱的全套操作。
导出步骤的调度规则:每个 Step 只服务于自己的 Flag
参考文档(graphify/skills/kilo/references/exports.md)的开篇就定下了一条调度原则:该参考文档只在用户传了某个导出标志时才加载,且每个 Step 只在其对应标志存在时执行。这与主技能文档 graphify/skill-kilo.md 中的标志清单一一对应:
/graphify <path> --svg # also export graph.svg
/graphify <path> --graphml # export graph.graphml
/graphify <path> --neo4j # generate graphify-out/cypher.txt
/graphify <path> --neo4j-push bolt://localhost:7687 # push directly to Neo4j
/graphify <path> --falkordb # generate graphify-out/cypher.txt
/graphify <path> --falkordb-push falkordb://localhost:6379 # push directly to FalkorDB
/graphify <path> --mcp # start MCP stdio server
/graphify <path> --wiki # agent-crawlable wiki
skill 文档中也有同样的说明:这些步骤“only when their flag is present … or, for the token-reduction benchmark, when total_words exceeds 5,000. A default run with no export flags skips all of them”(见 graphify/skill-kilo.md)。也就是说,一次不带任何标志的默认运行不会触发下面任何导出动作,全部六个 Step 加上 benchmark 都是按需触发的。
在 CLI 层面,这些标志最终都收敛到 graphify export <format> 子命令,由 graphify/cli.py 中的 subcmd not in ("html", "callflow-html", "obsidian", "wiki", "svg", "graphml", "neo4j", "falkordb") 分支统一分发;所有导出默认从 graphify-out/graph.json 读取图,从同目录的 .graphify_labels.json 与 .graphify_analysis.json 读取社区标签与社区划分,并可用 --graph PATH / --labels PATH 显式覆盖。
Step 6b:Wiki 导出(仅当 --wiki)
文档给出的命令与执行时机约束:
graphify export wiki
只有在原始命令显式带了
--wiki时才运行本步骤,并且必须在 Step 9(清理)之前执行,确保.graphify_labels.json仍然可用。
“先导出、后清理”不是随意的顺序要求。从源码看,CLI 的 wiki 分支(graphify/cli.py)会读取 .graphify_analysis.json 中的 communities、cohesion 与 gods,并在 graphify-out/wiki/ 目录下调用 graphify/wiki.py 的 to_wiki 生成文章。这里有两条值得注意的防护逻辑:
- 缺失社区数据时拒绝导出:如果
.graphify_analysis.json缺失或为空,CLI 会直接报错退出——“refusing to export wiki to prevent data loss”,并提示先运行graphify extract .(或graphify cluster-only .)重新生成社区数据。 - 输出结构:生成成功后打印
Wiki: {n} articles written to .../wiki/,并指出wiki/index.md是 agent 的入口。graphify/wiki.py 的模块注释说明了产物形态:Wikipedia 风格的 Markdown 文章,包含index.md+ 每个社区一篇文章 + god node 文章,且刻意做成 agent 可爬取——文章间用原始相对链接(而非 Obsidian 的[[wiki link]])互链,非 ASCII 字符(CJK、西里尔等)在 slug 中不被剥离,链接目标与磁盘文件名逐字一致(_safe_filename与_md_link的共同设计,见 graphify/wiki.py)。
Wiki 导出的行为有专门的测试覆盖,见 tests/test_wiki.py。
Step 7:Neo4j 导出(仅当 --neo4j 或 --neo4j-push)
文档区分了两种形态:
形态一:--neo4j——生成 Cypher 文件供手工导入
graphify export neo4j
形态二:--neo4j-push <uri>——直推运行中的 Neo4j 实例(未提供凭据时向用户索取):
graphify export neo4j --push bolt://localhost:7687 --user neo4j --password PASSWORD
默认 URI 为 bolt://localhost:7687,默认用户为 neo4j;使用 MERGE 语义,重复执行不会产生重复节点,可安全重跑。
源码层面这两条路径的分工很清晰(graphify/cli.py):
- 不带
--push时调用 graphify/export.py 的to_cypher,在graphify-out/cypher.txt中为每个节点生成MERGE (n:{Filetype} {id, label})、为每条边生成MATCH (a), (b) MERGE (a)-[:REL {confidence}]->(b)。Cypher 字符串经过_cypher_escape转义(反引号、引号、换行、CR、控制字节),节点 label 与关系类型这两个无法在 Cypher 中安全转义的标识符位置则做[A-Za-z0-9_]白名单清洗,非法时回退为Entity/RELATES_TO(见 graphify/export.py)。CLI 提示的导入方式是cypher-shell < graphify-out/cypher.txt。 - 带
--push时调用 graphify/exporters/graphdb.py 的push_to_neo4j,通过官方 Python 驱动直连。前置依赖是pip install neo4j(缺失时抛出带安装提示的 ImportError)。推送时只携带标量属性并剔除下划线开头的内部属性,节点会额外写入所属community编号;节点与关系均使用MERGE ... SET ... +=参数化查询,与文档“safe to re-run”的描述一致。函数返回{"nodes": N, "edges": M},CLI 打印Pushed to Neo4j: N nodes, M edges。
两个安全细节值得实操时留意:
- 密码不留在 argv 上:CLI 优先读取环境变量
NEO4J_PASSWORD,显式--password可覆盖(F-031,见 graphify/cli.py);且--push场景下若拿不到密码会直接报错退出。 - 凭据清洗:label 清洗在 graphify/exporters/graphdb.py 中标注为“prevent Cypher injection”,把任意 label 压回
[A-Za-z0-9_]。
Step 7a:FalkorDB 导出(仅当 --falkordb 或 --falkordb-push)
文档对 --falkordb 的告诫非常具体:
生成的语句是 OpenCypher,但 FalkorDB 的
GRAPH.QUERY一次只执行一条语句(没有 Neo4jcypher-shell那样的批量脚本导入),所以加载图应优先使用--falkordb-push;仅当你想要可移植的cypher.txt产物时才用文件导出。
# 生成可移植的 OpenCypher 文件
graphify export falkordb
# 直推运行中的 FalkorDB 实例;凭据可选,仅当实例要求鉴权时才向用户索取
graphify export falkordb --push falkordb://localhost:6379
默认 URI 为 falkordb://localhost:6379,文档特别指出 scheme 只是信息性的——redis:// 或直接 host:port 都等价;鉴权可选;目标图名默认 graphify;同样使用 MERGE,可安全重跑。
实现上,push_to_falkordb(graphify/exporters/graphdb.py)的 docstring 把与 Neo4j 路径的差异逐条列出,与文档描述完全吻合:
- 前置依赖
pip install falkordb,通过FalkorDB(host, port, username, password)连接,只从 URI 解析 host/port(默认端口 6379),因此三种 URI 写法等价; - 通过
db.select_graph(graph_name)选择命名图(默认"graphify"),同一实例内按图名隔离; - 查询经
graph.query(cypher, params)执行,没有 session 对象; - 鉴权可选:FalkorDB 默认无凭据运行。代码里有一个细节——只有提供了
password才会发送用户名,否则匿名连接并忽略 bolt 风格默认用户名(如neo4j),因为 FalkorDB 会把未知 ACL 用户拒绝(见 graphify/exporters/graphdb.py); - MERGE 语义与 Neo4j 路径一致,返回
{"nodes": N, "edges": M}。
不带 --push 时 CLI 复用 to_cypher 写出 cypher.txt,但会额外打印一段提示:由于 GRAPH.QUERY 逐条执行、没有批量脚本导入,应改用 graphify export falkordb --push falkordb://localhost:6379 加载(graphify/cli.py)。密码同样支持环境变量 FALKORDB_PASSWORD 替代 --password(graphify/cli.py)。该路径的集成测试见 tests/test_falkordb_integration.py。
Step 7b 与 7c:SVG 和 GraphML 导出
这两个是最轻量的静态产物,文档各给出一条命令:
# Step 7b - 仅当 --svg
graphify export svg
# Step 7c - 仅当 --graphml
graphify export graphml
从 CLI 实现看(graphify/cli.py):
svg分支调用 graphify/export.py 的to_svg,输出graphify-out/graph.svg,成功时提示 “graph.svg written - embeds in Obsidian, Notion, GitHub READMEs”;graphml分支调用to_graphml,输出graphify-out/graph.graphml,提示 “open in Gephi, yEd, or any GraphML tool”。
两者都接受 --graph / --labels 参数(svg 支持 --labels,graphml 仅 --graph,见 CLI 用法说明 graphify/cli.py)。GraphML 路径在写盘前会用 _strip_xml_illegal 剔除 XML 1.0 无法承载的控制字符(如终端 ANSI 转义、某些源码里的表单进符),避免单个标签毁掉整个导出(graphify/export.py)。
Step 7d:MCP Server(仅当 --mcp)
文档给出的启动命令:
$(cat graphify-out/.graphify_python) -m graphify.serve graphify-out/graph.json
这启动一个 stdio MCP server,把知识图谱暴露成七个工具供 Claude Desktop 或任何 MCP 兼容的 Agent 编排器实时查询:query_graph、get_node、get_neighbors、get_community、god_nodes、graph_stats、shortest_path。这七个工具名与 graphify/serve.py 中 list_tools 注册的 name 完全一致,可以逐一对上。
文档同时指出了在 Claude Desktop 中配置的三个坑,配置方式如下(claude_desktop_config.json):
{
"mcpServers": {
"graphify": {
"command": "<absolute path from: cat graphify-out/.graphify_python>",
"args": ["-m", "graphify.serve", "/absolute/path/to/graphify-out/graph.json"]
}
}
}
三个坑分别是:Claude Desktop 不会执行 $(...) 命令替换;在 uv tool install 场景下系统 python3 无法导入 graphify 包;因此必须把 command 写成 cat graphify-out/.graphify_python 打印出的绝对解释器路径,而不是 shell 动态展开。服务端自身还有若干与文档互补的运行细节(graphify/serve.py):图文件必须是 .json 且存在、受大小上限检查保护,并支持 GRAPHIFY_MAX_CONTEXTS 环境变量控制多项目上下文的 LRU 容量(默认 8)。查询工具 query_graph 的实现在 _query_graph_text 一带,shortest_path 则通过 NetworkX 的 nx.shortest_path 在有向/无向图上求路径(graphify/serve.py)。
Step 8:Token 缩减基准测试(仅当 total_words > 5000)
文档的触发条件与行为:
如果
graphify-out/.graphify_detect.json中的total_words大于 5,000,则运行:graphify benchmark把输出直接打印在聊天里。若
total_words <= 5000则静默跳过——小语料下,图的价值在于结构清晰度而非 token 压缩。
CLI 的 benchmark 分支(graphify/cli.py)会先从 .graphify_detect.json 读取 total_words 作为语料规模,再调用 graphify/benchmark.py 的 run_benchmark 与 print_benchmark。实现细节可以帮你正确解读输出:
- 语料 token 估算:按“100 words ≈ 133 tokens”换算(
corpus_words * 100 // 75),字符级估算按每 4 字符约 1 token(graphify/benchmark.py); - 查询成本模拟:对 5 个内置样例问题(如 “how does authentication work”),先用问题词元对节点 label 打分取 top-3 起点,再做 3 层 BFS,把子图内的
NODE/EDGE行折算成 token 数(_query_subgraph_tokens); - 输出报告:打印语料 token、图规模(nodes/edges)、平均查询 token 成本与总体缩减比,以及每个问题各自的
Nx缩减系数(graphify/benchmark.py)。
该基准有专门的单测覆盖,见 tests/test_benchmark.py。
小结:按标志对照表收尾
| Flag | 命令 | 产物 / 默认值 | 关键约束 |
|---|---|---|---|
--wiki |
graphify export wiki |
graphify-out/wiki/(index.md 为 agent 入口) |
需在 Step 9 清理前运行;缺社区数据直接拒绝导出 |
--neo4j |
graphify export neo4j |
graphify-out/cypher.txt |
需 cypher-shell 批量导入;需 pip install neo4j(push 时) |
--neo4j-push |
graphify export neo4j --push bolt://localhost:7687 --user neo4j --password PASSWORD |
直推 Neo4j | MERGE 可重跑;可用 NEO4J_PASSWORD 替代明文密码 |
--falkordb |
graphify export falkordb |
graphify-out/cypher.txt(OpenCypher) |
GRAPH.QUERY 逐条执行,加载优先 --push |
--falkordb-push |
graphify export falkordb --push falkordb://localhost:6379 |
直推 FalkorDB,默认图名 graphify |
scheme 信息性、鉴权可选;可用 FALKORDB_PASSWORD |
--svg |
graphify export svg |
graphify-out/graph.svg |
可嵌入 Obsidian / Notion / README |
--graphml |
graphify export graphml |
graphify-out/graph.graphml |
Gephi、yEd 等工具可打开 |
--mcp |
$(cat graphify-out/.graphify_python) -m graphify.serve graphify-out/graph.json |
stdio MCP server,7 个查询工具 | Claude Desktop 配置需用绝对解释器路径 |
自动(total_words > 5000) |
graphify benchmark |
打印 token 缩减报告 | 语料过小则静默跳过 |
所有命令都以本地生成的 graphify-out/graph.json 为单一事实源,导出物彼此独立、可单独重跑;图数据库类导出统一采用 MERGE 幂等语义,凭据处理上优先环境变量——这套组合让导出层在“可移植产物”与“直连推送”之间提供了完整的可选项。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0625
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00