知识图谱执行流程
面向新人的 Graphify 知识图谱系统完整链路说明
精确到每个文件和关键函数,方便定位和调试
一、系统总览
核心文件位置:.venv\Lib\site-packages\graphify\
| 文件 | 行数 | 职责 |
|---|---|---|
__main__.py | 4583 | CLI 主入口,命令分发 |
serve.py | 1312 | MCP stdio 服务器 + 查询引擎 |
extract.py | 11658 | AST 提取(tree-sitter,30+ 语言) |
build.py | 490 | NetworkX 图构建 |
cluster.py | 273 | Leiden/Louvain 社群聚类 |
report.py | — | 生成 GRAPH_REPORT.md |
export.py | — | 导出 JSON/HTML |
watch.py | — | 增量更新 + 文件监听 |
cache.py | — | AST 缓存管理 |
manifest.py | — | 文件变更清单追踪 |
二、链路一:Cursor 启动 → MCP 服务就绪 → AI 查询
这是运行时的核心链路:AI 如何查询知识图谱。
关键文件调用栈
.cursor/mcp.json ← 配置入口
└─ command: ".venv/Scripts/python.exe"
└─ args: ["-m", "graphify.serve", "graphify-out/graph.json"]
graphify/__main__.py :: main() ← Python 包入口
└─ 检测 sys.argv → cmd = "serve"
└─ serve.py :: serve(graph_path) ← MCP 服务入口
├─ _load_graph(path) ← 加载图谱
│ └─ json.load() → nx.node_link_graph()
├─ _build_server(graph_path) ← 注册 MCP 工具
│ ├─ list_tools() ← 声明可用工具
│ └─ call_tool(name, args) ← 工具调度路由
└─ asyncio.run(main()) ← 启动 stdio 事件循环
查询引擎内部逻辑
serve.py :: _query_graph_text(G, question, mode, depth, token_budget)
Step 1: 分词
├─ _query_terms(question)
│ ├─ 中文 → jieba.cut() 分词
│ └─ 英文 → re.findall(r"\w+")
Step 2: 节点评分
├─ _score_nodes(G, terms)
│ ├─ 精确匹配 × 1000
│ ├─ 前缀匹配 × 100
│ ├─ 子串匹配 × 1
│ └─ 源文件路径匹配 × 0.5
Step 3: 选择种子节点
├─ _pick_seeds(scored, max_k=3, gap_ratio=0.2)
│ └─ 按分数排序,取 Top-K(置信度间隙过滤)
Step 4: 图遍历
├─ _bfs_context(seeds, depth=3) 或 _dfs_context()
│ ├─ 层 0: 种子节点
│ ├─ 层 1: 直接邻居
│ ├─ 层 2: 二度关系
│ └─ 层 3: 三度关系
Step 5: 格式化返回
└─ _format_result(nodes, edges, token_budget)
├─ 按 community 分组
├─ 去重
└─ 截断至 token 限制
MCP 暴露的 5 个工具
| 工具名 | 功能 | 关键参数 |
|---|---|---|
query_graph | 自然语言查询图谱 | question, mode(bfs/dfs), depth, token_budget |
get_node | 获取节点详情 | label(节点标签或 ID) |
get_neighbors | 获取邻居节点 | label, relation_filter |
list_communities | 列出所有社群 | — |
get_community | 获取社群内节点 | community_id |
三、链路二:代码变更 → 图谱更新
这是构建时的核心链路:代码变更后如何更新知识图谱。
关键文件调用栈
命令行: .\.venv\Scripts\graphify update . [--force]
graphify/__main__.py :: main() ← CLI 入口
└─ cmd = "update"
└─ watch.py :: _rebuild_code(path, force, no_cluster)
│
├─ 1. 增量检测
│ ├─ manifest.py :: load_manifest() ← 读取历史清单
│ ├─ 扫描文件系统 mtime
│ └─ 对比 ast_hash → 识别变动文件
│
├─ 2. AST 提取
│ ├─ extract.py :: extract(target) ← 主提取函数
│ │ ├─ collect_files() ← 收集文件(.graphifyignore 过滤)
│ │ ├─ extract_csharp(path) ← C# 提取器
│ │ ├─ extract_js(path) ← JS/Vue 提取器
│ │ ├─ extract_python(path) ← Python 提取器
│ │ └─ ... (30+ 语言)
│ └─ cache.py :: load_cached() / save_cached()
│ └─ 缓存位置: graphify-out/cache/ast/<hash>.json
│
├─ 3. 图构建
│ └─ build.py :: build_from_json(extraction)
│ ├─ _normalize_id() ← 节点 ID 标准化
│ ├─ _deduplicate_by_label() ← 三层去重
│ └─ nx.Graph.add_node() / .add_edge()
│
├─ 4. 社群聚类
│ └─ cluster.py :: cluster(G, resolution=1.0)
│ ├─ _partition(G) ← Leiden 优先,Louvain 备选
│ ├─ 社群分割(>25% 图 → 递归)
│ └─ remap_communities_to_previous() ← ID 稳定化
│
├─ 5. 报告生成
│ └─ report.py :: generate(G, communities)
│ ├─ analyze.py :: god_nodes()
│ └─ analyze.py :: surprising_connections()
│
└─ 6. 导出保存
├─ export.py :: to_json(G) → graphify-out/graph.json
├─ export.py :: to_html(G) → graphify-out/graph.html
└─ manifest.py :: save_manifest() → graphify-out/manifest.json
增量 vs 全量
| 模式 | 命令 | 行为 |
|---|---|---|
| 增量(默认) | graphify update . | 只提取变动文件,保留旧节点 |
| 全量(强制) | graphify update . --force | 重新扫描全部文件 |
增量更新的判定逻辑:
manifest.json 中的 ast_hash ≠ 当前文件内容 hash → 需要重新提取
manifest.json 中的 ast_hash = 当前文件内容 hash → 跳过,复用缓存
四、链路三:入图规则(何时触发更新)
配置文件对应
| 规则/配置 | 文件路径 | 作用 |
|---|---|---|
| 入图规则 | .cursor/rules/05-graphify-entry.mdc | 定义何时必须查图、未命中怎么处理 |
| 运维操作 | .cursor/skills/20-capabilities/10-graphify-ops/SKILL.md | L0~L3 分级操作手册 |
| 过滤清单 | .graphifyignore | 哪些路径不纳入图谱 |
| MCP 配置 | .cursor/mcp.json | 服务启动命令 |
五、数据流全景图
六、热重载机制
AI 发起查询
↓
serve.py :: _maybe_reload()
├─ 检查 graph.json 的 mtime
├─ 如果文件变化 → 重新加载
│ └─ _load_graph() → 新的 NetworkX Graph
└─ 如果未变化 → 使用内存缓存
↓
继续执行查询
这意味着:你执行 graphify update 后,无需重启 Cursor,下次 AI 查询会自动使用最新图谱。
七、常用命令速查
# 增量更新图谱(日常使用)
.\.venv\Scripts\graphify update .
# 全量重建图谱(大改后使用)
.\.venv\Scripts\graphify update . --force
# 仅重新聚类(不重新提取)
.\.venv\Scripts\graphify cluster-only graphify-out/graph.json
# 给社群命名(需要 LLM API Key)
.\.venv\Scripts\graphify label graphify-out/
# 手动启动 MCP 服务(调试用)
.\.venv\Scripts\python.exe -m graphify.serve graphify-out/graph.json
# 查看当前图谱统计
打开 graphify-out/GRAPH_REPORT.md
# 可视化浏览图谱
打开 graphify-out/graph.html
八、新人快速理解要点
1. 两条独立链路
| 链路 | 触发时机 | 关键文件 | 产物 |
|---|---|---|---|
| 构建链路 | 手动执行 graphify update | extract.py → build.py → cluster.py | graph.json |
| 查询链路 | Cursor 启动后 AI 自动调用 | serve.py(MCP 协议) | 文本上下文 |
2. 三个核心概念
| 概念 | 解释 | 类比 |
|---|---|---|
| 节点(Node) | 代码里的类、方法、配置项、业务术语 | 百科词条 |
| 边(Edge) | 节点之间的关系(调用、继承、引用) | 词条之间的超链接 |
| 社群(Community) | 紧密关联的一组节点 | 百科的分类目录 |
3. 为什么需要这个系统?
没有图谱:AI 要全局搜索 337 个文件 → 慢、不准、带入无关代码
有了图谱:AI 查一次图 → 精准定位 3-5 个相关节点 → 快、准、上下文紧凑
2283

被折叠的 条评论
为什么被折叠?



