graphify 实战指南:用 /graphify add 摄入 URL、用 --watch 监听文件夹自动重建知识图谱
【免费下载链接】graphifyTurn any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph. A /graphify skill for Claude Code, Cursor, Codex, and Gemini CLI: local deterministic AST parsing, every edge explained, no vector store.项目地址: https://gitcode.com/GitHub_Trending/graph/graphify
本文围绕 graphify 技能的两个非默认构建功能展开:/graphify add <url>将外部 URL(推文、arXiv、PDF、网页、图片、视频)抓取进语料库并合入图谱,以及--watch后台监听文件夹、在文件变化时自动重建graph.json与GRAPH_REPORT.md。读完后你可以直接在 Claude Code 等 Agent 中执行这两条指令,并理解其底层实现(URL 分类、frontmatter 落盘、watchdog 防抖、增量 reconcile 与并发锁)是如何保证图谱在持续变化中保持正确的。
这两个功能在技能中的位置
/graphify add <url>和--watch都不属于 graphify 的默认构建流程。技能入口文件 skill-amp.md 明确列出了/graphify add的用法变体:
/graphify add <url> # fetch URL, save to ./raw, update graph /graphify add <url> --author "Name" # tag who wrote it /graphify add <url> --contributor "Name" # tag who added it to the corpus并规定:当用户执行/graphify add <url>抓取 URL 入语料库,或传入--watch让图谱在文件变化时自动重建时,加载参考文档 references/add-watch.md(本文的原始文档)。也就是说,它是 Agent 在特定触发条件下才读取的操作手册,本文将其两条操作路径完整展开。
两条命令都依赖同一个前置约定:构建完成后,graphify-out/.graphify_python中记录了当时使用的 Python 解释器路径,命令一律以$(cat graphify-out/.graphify_python)开头来保证与构建时同一环境,避免系统python3缺少 graphify 依赖导致导入失败。
用 /graphify add 把一个 URL 变成图谱节点
完整命令与参数
原始文档给出的标准执行方式如下(以graphify-out/.graphify_python指向的解释器运行内联脚本,调用 ingest 模块 的ingest函数):
$(cat graphify-out/.graphify_python) -c " import sys from graphify.ingest import ingest from pathlib import Path try: out = ingest('URL', Path('./raw'), author='AUTHOR', contributor='CONTRIBUTOR') print(f'Saved to {out}') except ValueError as e: print(f'error: {e}', file=sys.stderr) sys.exit(1) except RuntimeError as e: print(f'error: {e}', file=sys.stderr) sys.exit(1) "参数替换规则与错误处理约定:
URL替换为实际要抓取的地址;AUTHOR与CONTRIBUTOR在用户提供了姓名时替换,否则保留占位语义(最终会落为unknown)。- 命令如果以错误退出,必须向用户说明出了什么问题,不能静默继续——这是原始文档对 Agent 的硬性要求。
- 保存成功后,自动对
./raw跑一次--update管道,把新文件合入现有图谱。 ValueError与RuntimeError分别对应参数/URL 校验失败和抓取失败两类错误,源码中ingest函数正是这样抛出的:URL 未通过validate_url时抛ValueError(前缀ingest:),网络层失败(HTTPError/URLError/OSError)时包装为RuntimeError。
六种 URL 类型如何被自动识别
原始文档列出 6 类受支持且自动检测的 URL。对照 ingest.py 中的 _detect_url_type,检测逻辑是对 URL 做小写子串/后缀匹配:
| URL 类型 | 识别条件(源码实现) | 落盘结果 |
|---|---|---|
| YouTube / 视频 | 含youtube.com或youtu.be | 通过 yt-dlp 下载音频,下次运行时转写为.txt(需要pip install 'graphifyy[video]') |
| Twitter/X | 含twitter.com或x.com | 通过 oEmbed 拉取,保存为带推文正文与作者的.md |
| arXiv | 含arxiv.org | 摘要 + 元数据保存为.md |
路径以.pdf结尾 | 直接下载为.pdf | |
| 图片 | 路径以.png/.jpg/.jpeg/.webp/.gif结尾 | 下载保存,Claude vision 在下次运行时提取 |
| 任意网页 | 以上均不匹配 | 经 html2text/markdownify 转 markdown 保存为.md |
从源码结构看,有两点值得注意,它们让实际行为比文档表格更精细:
- github.com 被识别但按网页处理。
_detect_url_type中还有github.com分支返回"github",但 ingest 主函数 只对pdf/image/youtube/tweet/arxiv做了特判,其余一律走_fetch_webpage的网页转换路径。 - 落盘文件都带 YAML frontmatter。推文、arXiv、网页三类生成的
.md头部都写入source_url、type、captured_at、contributor等字段(arXiv 另有arxiv_id、paper_authors,网页另有title),这些字段会被 graphify 的文档提取器读作节点元数据。正文还做了截断:网页正文取前 12000 字符;文件名由域名+路径清洗生成(非单词字符替换为_,最长 80 字符),同名冲突时自动追加_1、_2计数器避免覆盖。 - 安全边界。所有抓取都经过 security 模块 的
validate_url/safe_fetch/safe_fetch_text,URL 字符串进入 frontmatter 前还会经_yaml_str逐字符转义(含 U+2028/U+2029 等 YAML 换行符),防止恶意页面标题通过 frontmatter 注入额外键。
成功后自动走 --update 管道
原始文档要求“保存成功后自动对./raw运行--update管道”。这条管道本身的实现细节在姊妹参考文档 references/update.md 中:先用detect_incremental对比 manifest 找出新增/变更/删除的文件,再把变更子集写入.graphify_detect.json;若变更文件全是代码则只跑 AST 提取、跳过 LLM 语义提取;否则走完整的 3A–3C 管道(含视频转写前置步骤),最后用build_merge把新提取结果与现有graph.json合并,并只把本轮真正产出内容的文件盖章进 manifest(失败的 chunk 保留未盖章状态以便下次重排)。因此一次/graphify add <url>的完整闭环是:抓取 → 落盘(带溯源 frontmatter)→ 增量检测 → 提取 → 合并 → 图谱更新。
视频摄入的依赖前提
YouTube 一类 URL 只是先下载音频文件,转写发生在下一次运行时。对应的依赖声明在 pyproject.toml 的可选依赖中:
video = ["faster-whisper; python_version >= '3.11'", "yt-dlp>=2026.6.9"]即需要 Python 3.11+ 并安装graphifyy[video]扩展,音频下载入口是 transcribe 模块 的download_audio。
用 --watch 监听文件夹自动重建图谱
命令与 debounce 参数
原始文档给出的监听命令:
$(cat graphify-out/.graphify_python) -m graphify.watch INPUT_PATH --debounce 3INPUT_PATH替换为要监听的目录。入口在 watch.py 的main段:path是位置参数(默认.),--debounce为浮点秒数,默认 3 秒。
Debounce 的语义是“等到文件活动停止后再触发”,这样一波并行 Agent 写入不会每个文件都触发一次重建。对照 watch 函数 的实现可以确认这个机制:主循环每 0.5 秒检查一次time.monotonic(),只有当距最后一次事件 ≥ debounce 秒时才把累积的变更文件打包成一个 batch 触发后续动作。
代码变更与非代码变更的分流
原始文档描述了两类行为,源码中的判定条件比文档更精确(见 _batch_triggers_rebuild / _batch_needs_llm_flag):
- 代码文件变更(.py、.ts、.go 等):立即重跑 AST 提取 + 重建 + 社区聚类,全程不需要 LLM,
graph.json与GRAPH_REPORT.md自动更新。源码里的触发条件是“batch 中含代码文件或batch 中有已删除的文件”——任何被监听文件的删除同样会触发重建,因为驱逐过期节点不需要 LLM。 - 文档、论文、图片变更:写入
graphify-out/needs_update标志文件并打印提示,要求运行/graphify --update做 LLM 语义重提取(见 _notify_only)。注意只有仍存在于磁盘上的非代码文件才写标志;纯删除批次的节点驱逐已由重建完成,不会留下过期标志。
监听器本身还有一些保护性过滤,避免自身触发风暴:只关心代码/文档/论文/图片四类扩展名(CODE | DOC | PAPER | IMAGE);.graphifyignore模式在启动时一次性加载(避免高频文件系统事件上反复解析);跳过所有含点前缀路径段的文件和graphify-out目录自身;在 Linux 上还会过滤 inotify 的opened/closed_no_write只读事件(否则监视器自己读文件就会无限重触发);macOS 上使用PollingObserver轮询观察者,因为 FSEvents 可能漏掉快速保存。
一次代码重建的内部过程
代码变更触发的重建入口是 _rebuild_code。从源码结构看,它远不止“重新提取”那么简单,这是一条带并发保护和失败回滚的完整管道:
- 并发锁与排队。重建前后用
fcntl.flock对graphify-out/.rebuild.lock加咨询锁(_rebuild_lock),进程被 kill 时锁自动释放,无需清理残留锁文件;持锁期间锁文件内写入持有者 PID 供外部轮询。若锁被占,增量调用会先把变更路径追加进.pending_changes队列(append 模式写,POSIX 下小写入原子),持锁方在重建前后各排空一次并合并变更集,保证并发 commit 的变更不会丢失;重建完成后还会做最多 20 轮“迟到排空”,让提交风暴最终收敛。 - 增量 reconcile。只重提取变更且仍存在的文件,未变更文件的节点从现有
graph.json保留;删除文件对应的过期节点被驱逐。驱逐采取 fail-closed 策略:文件仍存在于磁盘但离开扫描语料时,必须有“活的忽略规则命中”(.graphifyignore或持久化的--exclude模式)才算有意排除并清理,否则保守保留并打印警告,防止过滤器回归导致节点被误杀。 - 缩图守卫。写入前 _check_shrink 会对比新旧节点数:如果新图节点变少,且减少的节点无法全部归因于本轮重提取或删除的文件,则拒绝覆盖并提示
--force,用来拦截“半截提取导致数千节点无声消失”的事故。合法的删除(如重构删函数)则通过rebuilt_sources/deleted_paths核算放行,无需--force。 - 落盘与派生物。原子替换(先写
.graph.tmp.json再 rename)、生成GRAPH_REPORT.md、复用旧社区标签(社区成员签名校验后按 hub 节点确定性重命名)、必要时从graph.json中已存的社区信息重渲染graph.html,最后清除needs_update标志——所以一次代码重建会把此前文档变更留下的语义更新提醒一并冲掉,若那批文档确实要处理,仍需手动跑/graphify --update。
无变更时的幂等性
如果一轮重建发现拓扑没有任何变化(canonical 拓扑对比相等),watch 会打印No code-graph changes detected; outputs left untouched.并不触碰磁盘上的产物;只有当graph.html缺失或被标记 stale 时才会顺带重渲染 HTML。这保证了长时间开着 watcher 也不会产生无意义的文件写入。
Agentic 工作流中的实践建议
原始文档给出的使用姿势:
- 在后台终端运行
--watch,Agent 一波又一波的代码修改会在波次间隙被自动拾取并重建; - 如果 Agent 同时还在写文档或笔记,这些波次结束后需要一次手动
/graphify --update做语义重提取; - 按
Ctrl+C停止(源码中捕获KeyboardInterrupt,打印Stopped.并优雅停止 observer 线程)。
关键文件索引
| 路径 | 作用 |
|---|---|
| graphify/skills/amp/references/add-watch.md | 本文原始参考文档(add 与 watch 的 Agent 操作手册) |
| graphify/ingest.py | URL 分类、抓取、frontmatter 生成、落盘去重 |
| graphify/watch.py | 文件监听、防抖、锁与排队、增量 reconcile、缩图守卫 |
| graphify/skills/amp/references/update.md | add 成功后自动执行的--update增量管道 |
| graphify/skill-amp.md | 技能入口,/graphify add命令族与参考文档路由 |
| tests/test_watch.py | watch 相关行为的测试用例(含 source_file 锚定、变更集合并等场景) |
适用前提小结:以上命令均在“已至少完成一次构建、graphify-out/存在.graphify_python指针”的前提下运行;视频摄入额外要求 Python 3.11+ 与graphifyy[video]扩展;--watch需要watchdog已安装(缺失时会提示pip install watchdog)。
【免费下载链接】graphifyTurn any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph. A /graphify skill for Claude Code, Cursor, Codex, and Gemini CLI: local deterministic AST parsing, every edge explained, no vector store.项目地址: https://gitcode.com/GitHub_Trending/graph/graphify
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考