graphify 导出与基准测试指南:从 graph.json 到 Wiki、图数据库与 MCP 实时查询
本篇基于 graphify 的 opencode 技能参考文档 exports.md 展开,完整覆盖 /graphify 流程中的全部可选导出步骤(--wiki、--neo4j/--neo4j-push、--falkordb/--falkordb-push、--svg、--graphml、--mcp)以及大语料场景下的 token 压缩基准测试。读完本文,你将掌握每种导出标志对应的命令、产物与幂等性保证,并能结合 export.py、graphdb.py、serve.py、benchmark.py 等源码,理解 Cypher 生成、MERGE 幂等推送与 MCP 工具暴露的底层实现。
参考文档的加载时机与执行原则
原文档开头明确了这份参考的触发条件:当用户在 /graphify 命令中传入了任意导出标志(--wiki、--neo4j、--neo4j-push、--falkordb、--falkordb-push、--svg、--graphml、--mcp),或者语料规模大到值得跑 token 压缩基准时,才加载并执行对应步骤。原文档强调一条关键原则:每一步只为自己的标志执行(Each step runs only for its own flag),即不传标志就不产出对应产物,导出是严格按需的。
从 cli.py 的实现可以印证这一设计:graphify export 子命令支持 html、callflow-html、obsidian、wiki、svg、graphml、neo4j、falkordb 八种格式,每种格式各自解析 --graph、--labels、--push、--user、--password 等参数,互不耦合。
Wiki 导出(仅当传入 --wiki)
只有当原始命令显式带有 --wiki 时才执行此步骤。 原文档额外指出:这一步要放在整个流程的第 9 步(清理)之前运行,因为 wiki 生成依赖 .graphify_labels.json(社区标签文件)仍然存在。
graphify export wiki
从 wiki.py 的 to_wiki() 实现可以看到产物的完整结构,它会在 graphify-out/wiki/ 下写出三类文件:
index.md:面向 Agent 的入口页,包含全部社区的目录(按规模降序排列)、god node(连接度最高的核心抽象)列表,以及节点/边/社区总数统计;<CommunityName>.md:每个社区一篇维基风格文章,含 Key Concepts(社区内度数最高的节点及来源文件)、跨社区 Relationship 统计、Source Files 列表,以及一段 EXTRACTED/INFERRED/AMBIGUOUS 三级置信度占比的 Audit Trail;<GodNodeLabel>.md:每个 god node 一篇文章,按关系类型分组列出其邻居及置信度。
两个值得注意的实现细节:to_wiki() 会先过滤掉社区列表中已不存在于图里的陈旧节点 ID(去重/增量重建后可能出现漂移),并拒绝在 communities 为空时清空 wiki/ 目录以防数据丢失;另外每次调用会先删除旧 .md 文章再整体重写,因为 to_wiki() 完全拥有 wiki/ 目录。cli.py 中的调用路径也会先检查 .graphify_analysis.json 是否存在,缺失时直接报错拒绝导出。
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 语句,重复执行是幂等的,不会产生重复节点或边。
源码层面这两条路径分别对应:
- 文件生成路径:export.py 的
to_cypher()为每个节点输出MERGE (n:<FileType> {id: ..., label: ...});,为每条边输出MATCH (a), (b) MERGE (a)-[:<RELATION> {confidence: ...}]->(b);。这里有两道安全防线:_cypher_escape()会转义单引号、反斜杠和换行符(防止标签内容破坏cypher-shell以分号分隔语句的边界,见 F-008 注释),而_cypher_label()会把节点标签和关系类型中的非法字符剥离(Cypher 的:Foo标识符位置无法转义,只能白名单过滤,非法时回退到Entity/RELATES_TO)。 - 直推路径:graphdb.py 的
push_to_neo4j()通过neo4jPython 驱动连接,逐节点执行MERGE (n:{ftype} {id: $id}) SET n += $props,节点属性会附带所属社区编号community,边则带完整关系属性。驱动未安装时会抛出明确的pip install neo4j提示。
另外,cli.py 支持用环境变量 NEO4J_PASSWORD 替代 --password 参数,避免密码出现在 ps 输出或 shell 历史中(F-031);--password 显式传入时优先级更高。
FalkorDB 导出(仅当传入 --falkordb 或 --falkordb-push)
若传入 --falkordb —— 生成 Cypher 文件。原文档特别提示:这些语句虽然是 OpenCypher,但 FalkorDB 的 GRAPH.QUERY 每次只能执行一条语句(没有 Neo4j cypher-shell 那种批量脚本导入),所以优先使用 --falkordb-push 装载图,只有想要可移植的 cypher.txt 产物时才用文件方式:
graphify export falkordb
若传入 --falkordb-push <uri> —— 直接推送到运行中的 FalkorDB 实例。凭据是可选的,仅在实例要求认证时才向用户询问:
graphify export falkordb --push falkordb://localhost:6379
默认 URI 为 falkordb://localhost:6379。这里有一个细节:协议头仅起说明作用,redis:// 或裸的 host:port 写法同样有效;认证可选;目标命名图默认为 graphify。同样使用 MERGE,重跑不产生重复。
graphdb.py 的 push_to_falkordb() 用注释完整列出了与 Neo4j 路径的差异,与原文档一一对应:
- 连接方式改为
FalkorDB(host, port, username, password),只从 URI 中解析 host/port,因此协议头随意; - 通过
db.select_graph("graphify")选择命名图,同一实例内按图名隔离; - 查询走
graph.query(cypher, params),没有 session 对象; - 认证可选:FalkorDB 默认无凭据运行,此时代码会忽略 bolt 风格的默认用户名(如 Neo4j 的
neo4j),因为 FalkorDB 会将其当作未知 ACL 用户拒绝; - MERGE/SET 语句与 Neo4j 路径完全相同,依赖 OpenCypher 兼容性实现幂等 upsert。
SVG 导出(仅当传入 --svg)
graphify export svg
cli.py 中该子命令调用 to_svg() 写出 graphify-out/graph.svg,控制台提示该图可嵌入 Obsidian、Notion 或 GitHub README。SVG 与 HTML、Obsidian 导出共用 base.py 中定义的 COMMUNITY_COLORS 十色调色板,保证社区着色在各格式间一致。
GraphML 导出(仅当传入 --graphml)
graphify export graphml
产物为 graphify-out/graph.graphml,可供 Gephi、yEd 等任意 GraphML 工具打开做进一步分析。export.py 中专门实现了 _strip_xml_illegal(),在写出前剔除 XML 1.0 无法承载的 C0 控制字符——标签直接来自语料,一个终端粘贴进来的 ANSI 转义序列就足以让 nx.write_graphml 抛异常中断整个导出,这个防护将其降级为单个标签的问题而非整次导出的失败。
MCP 服务(仅当传入 --mcp)
$(cat graphify-out/.graphify_python) -m graphify.serve graphify-out/graph.json
这会启动一个 stdio MCP 服务器,暴露以下工具:query_graph、get_node、get_neighbors、get_community、god_nodes、graph_stats、shortest_path。把它接入 Claude Desktop 或任何 MCP 兼容的 Agent 编排器,其他 Agent 就能对图谱做实时查询。
serve.py 中的工具定义与原文档列出的清单一致,关键参数包括:query_graph 支持 mode=bfs/dfs、depth(1-6)与 token_budget(默认 2000 token);shortest_path 默认遵循存储的边方向,undirected=true 可忽略方向;graph_stats 返回节点数、边数、社区数与置信度分布。源码中还可以看到服务器实现了带 LRU 缓存的图上下文管理(默认 8 个项目上下文,可用 GRAPHIFY_MAX_CONTEXTS 覆盖),以及加载前对 graph.json 的文件大小上限检查。
Claude Desktop 配置要点(原文档给出的完整示例):Claude Desktop 无法执行 $(...) 命令替换,且 uv tool install 安装方式下系统 python3 无法 import graphify,因此 command 必须写成 cat graphify-out/.graphify_python 打印出的绝对解释器路径:
{
"mcpServers": {
"graphify": {
"command": "<absolute path from: cat graphify-out/.graphify_python>",
"args": ["-m", "graphify.serve", "/absolute/path/to/graphify-out/graph.json"]
}
}
}
其中 <absolute path from: ...> 占位处填第一步 cat 命令的实际输出,args 第三个元素填 graphify-out/graph.json 的绝对路径。
Token 压缩基准测试(仅当 total_words > 5000)
若 graphify-out/.graphify_detect.json 中的 total_words 大于 5,000,则运行:
graphify benchmark
并把输出直接打印到聊天中。若 total_words <= 5000 则静默跳过——原文档的理由是:对小语料而言,图谱的价值在于结构清晰度,而不是 token 压缩。
cli.py 中的命令实现与这一描述完全对应:它从 .graphify_detect.json 读取 total_words 后调用 run_benchmark()。benchmark.py 的度量方法值得了解:
- 朴素基线:
corpus_tokens = corpus_words * 100 // 75(即按 100 词约 133 token 折算整份语料直接塞进上下文的成本); - 图查询成本:对 5 个内置样本问题(如 "how does authentication work"),用 serve.py 的
_query_terms做节点标签匹配,取得分最高的 3 个节点为起点做 3 层 BFS,把访问到的节点(label + 来源文件 + 位置)与边(关系)渲染成文本,按每 4 字符约 1 个 token 估算; - 输出:
print_benchmark()打印语料 token 数、图谱节点/边数、平均单次查询 token 数,以及reduction_ratio(每次查询节省的 token 倍数)和每个问题的明细。若样本问题在图中找不到任何匹配节点,会返回 "Build the graph first" 的错误提示。
小结
这份参考文档把 graphify 的"图谱出图"能力归纳为一条按标志触发的流水线:wiki 服务于 Agent 可读的静态维基,Neo4j/FalkorDB 服务于图数据库里的交互式 Cypher 查询(文件生成与直推两种模式,均靠 MERGE 保证幂等),SVG/GraphML 服务于可视化生态,MCP 服务则让任意 Agent 对图谱做活的查询,最后由 token 压缩基准在语料足够大时量化图谱带来的上下文节省。所有步骤共享同一份 graphify-out/graph.json 产物,命令、默认值与幂等性语义均可在上述源码路径中逐条核对。
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 StartedRust0627
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