graphify 语义抽取 Subagent 规范解析:让文档、论文与图片进入可查询知识图谱的 JSON 契约

【免费下载链接】graphify Turn 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. 【免费下载链接】graphify 项目地址: https://gitcode.com/GitHub_Trending/graph/graphify

graphify 的核心管线分两层:AST 结构化抽取(确定性、零成本)覆盖代码符号,而语义抽取(LLM 驱动)负责把文档、论文、图片等非结构化语料转成知识图谱片段。本文深入讲解驱动第二层的“子代理提示词规范”——一份以 graphify/skills/trae/references/extraction-spec.md(及其 skillgen 生成产物 tools/skillgen/expected/graphify__skills__trae__references__extraction-spec.md)为代表的规范文档。读完你将掌握:语义子代理的逐字提示词结构、节点/边/超边 JSON 模式、确定性节点 ID 规则、离散置信度标尺、source_file 溯源契约,以及这些规则在 graphify/skill-trae.md 的 B0–B3 分块流水线中如何被组装执行。

一、这份规范在管线中的位置:Step 3 Part B

graphify 的抓取(skill)工作流在“Step 3 - Extract entities and relationships”一分为二(见 graphify/skill-trae.md):

  • Part A — 结构化抽取:对代码文件做确定性 AST 解析,免费、无需 LLM,产物写入 graphify-out/.graphify_ast.json;
  • Part B — 语义抽取:仅当语料中至少有一个文档(doc)、论文(paper)或图片(image)分块时才运行;每个语义子代理拿到的是规范文档中的逐字提示词(需替换 FILE_LIST、CHUNK_NUM、TOTAL_CHUNKS、DEEP_MODE、CHUNK_PATH 五个占位符),并将结果 JSON 写入自己的分块文件 graphify-out/.graphify_chunk_NN.json。

两个关键约束贯穿全文:

  1. 纯代码语料跳过 Part B。一个典型的 /graphify . 只含代码时,AST 已覆盖全部需要,语义规范文件“永远不被读取”,并先写入一个空语义文件以免 Part C 合并时报 FileNotFoundError。
  2. 图构建过程不需要 API Key。语义层只有在用户已设置 GEMINI_API_KEY/GOOGLE_API_KEY 时才可选走后端(graphify.llm.extract_corpus_parallel,默认模型 gemini-3-flash-preview);未设置时由宿主 Agent 自身充当 LLM。graphify 不读取 Anthropic/OpenAI 等任何其他提供商的 Key。

需要说明:本文所述“引用文档”是各平台 SKILL 目录下同名规范文件的一份快照(Trae 平台对应的 expected 生成物与 graphify/skills/trae/references/extraction-spec.md 内容完全一致)。它同时也是各 Skill 平台共享的抽取契约。

二、三层证据置信度:EXTRACTED / INFERRED / AMBIGUOUS

规范要求子代理对每一条关系边都要先定性,再给定量分值,规则如下(规范原文逐字继承):

  • EXTRACTED:关系在源文件中显式存在——导入、调用、引用、"see §3.2" 这类互引;
  • INFERRED:合理推断——共享数据结构、隐含依赖;
  • AMBIGUOUS:不确定——标记供复核,而不是省略。

AMBIGUOUS 的核心价值在于“宁缺毋滥”的反面:抽取是丢失信息的单向过程,把可疑关系标注出来交给下游复核,比悄悄丢掉更能保住召回率。这一三层模型同样内建在 graphify/llm.py 的 _EXTRACTION_SYSTEM 系统提示词中(见 EXTRACTED: relationship explicit in source 等三行规则)。

三、按文件类型差异化抽取:与 AST 分工,绝不重复劳动

规范明确规定语义子代理不要重抽代码的导入边——AST 已经拿到了;代码文件要专注产出 AST 找不到的语义边。这保证了 file_type:"code" 节点由模型补充,而结构边仍由确定性子系统生成,两者在 Part C 合并(对应 graphify/extract.py 中“AST-extracted nodes from semantic/LLM nodes… replaces its AST edges without evicting the semantic edges”的合并逻辑)。

代码文件(code)

聚焦三类语义边:调用关系、共享数据、架构模式。两条铁律:

  1. calls 方向永不可反:source 必须是调用方(发出调用的函数/类),target 必须是被调方。
  2. calls 绝不跨语言:Python 函数不能 calls 一个 JS/TS/Go/Rust/Java 符号,反之亦然。跨语言调用边是“幻影伪影”(phantom artifacts),一旦出现就会被识别为伪造关系。

文档 / 论文文件(document / paper)

抽取具名概念、实体、引文。关于设计理由(为什么做这个决策、权衡取舍、设计意图),规范有一个容易被误用、但又强调过两遍的规则:

把 rationale(理由)作为相关概念节点上的一个属性存储——绝不要为它单独创建 rationale 节点或片段节点。只有当某事物本身是具名实体或概念时才创建节点。

也就是说不存在“理由节点”这种半实体。同时规范允许使用 file_type:"rationale" 为“概念状节点”(思想、原则、机制、设计模式)归类——注意这与“rationale 属性”是两回事:前者是给概念本身的文件类型标签,后者是挂在具名概念节点上的理由正文。这与 graphify/llm.py _EXTRACTION_SYSTEM 中的指示一致:Rationale … store as a rationale attribute on the relevant node. Do NOT create separate rationale nodes。

图片文件(image):用视觉理解“它是什么”,不只是 OCR

规范对图片的抽取要求明显高于文本 OCR,按图型分类给出指令:

图型要抽取的内容
UI 截图布局模式、设计决策、关键元素、用途
图表指标、趋势/洞察、数据来源
推文/帖子主张作为节点、作者、提及的概念
示意图组件及其连接关系
研究图它证明了什么、方法、结果
手写/白板想法与箭头,不确定的识别标记为 AMBIGUOUS

这是纯视觉理解任务:AST 无法解析像素,因此语义子代理是图片进入知识图谱的唯一通道。LLM 后端路径中,图片通过 _ImageRef 封装并按后端能力选择 vision 通道(见 graphify/llm.py 的 _partition_semantic_files、_build_image_refs 等函数)。

四、file_type 六枚举:契约内别无他值

任何节点上的 file_type 必须是以下六个值之一,其余全部非法、会被拒绝:

code | document | paper | image | rationale | concept

该枚举在下游消费端有真实语义:合并/裁剪逻辑会区分代码节点与语义节点(例如 graphify/extract.py 中对 file_type == "rationale" 与命名空间的处理、graphify/llm.py 的证据绑定只针对 file_type == "code" 的节点做源码定位)。模型一旦输出自定义标签,整个分块的合并行为就会退化,因此规范用“会拒绝”而非“建议遵守”表述。

五、--mode deep:激进的 INFERRED 模式

当用户以 --mode deep 发起抓取时(graphify/skill-trae.md 要求把这个开关一路传到每个子代理:DEEP_MODE=true),规范指示子代理对 INFERRED 边更激进:补充间接依赖、共享假设、潜在耦合;拿不准的标成 AMBIGUOUS 而不是省略。

注意 deep 模式不是放开想象力的开关。在 graphify/llm.py 的 _DEEP_EXTRACTION_SUFFIX 中措辞更收敛:只允许为具体的架构信号(共享数据契约、显式生命周期耦合、源码中可见的多步流程依赖)增加 INFERRED 边,并要求“避免宽泛的概念相似边”。可见 deep 模式的精髓是“深”而非“野”。

六、语义相似边:跨结构的非平凡关联

若分块内两个概念解决同一问题、代表同一思想,却没有任何结构链接(无导入、无调用、无引用),规范允许加一条 semantically_similar_to 边,标为 INFERRED,并给出 0.6–0.95 的相似度。规范示例:

  • 两个都校验用户输入、但从不互相调用的函数;
  • 代码里的类与论文里描述同一算法的概念;
  • 两个用不同方式处理同一失败模式的错误类型。

同样有限制:只在相似确实非平凡且跨领域时才加,不为显然相似的东西添加。这是图谱避免“近重复聚集噪声”的重要防线。

七、超边(hyperedges):二元边表达不了的分组

当 3 个及以上节点明显共同参与某个共享概念、流程或模式,而二元边两两表达又说不清时,加入顶层 hyperedges 数组。规范示例:

  • 实现同一协议/接口的所有类;
  • 认证流程中的全部函数(即便它们并不两两互调);
  • 论文某节中构成一个完整思想的所有概念。

并给出克制性上限:每个分块最多 3 条超边,只在分组信息超出二元边总和外才值得使用。超边的三个关系取值是 participate_in | implement | form,同时也要带 confidence/confidence_score。

八、YAML frontmatter 透传

若文件带 YAML frontmatter(--- ... ---),规范要求把 source_url、captured_at、author、contributor 复制到该文件产出的每一个节点上。这一规则让“某网页正文某段主张”具备可追溯的出处元数据——后续导出 HTML 图谱或做审计时,节点能直接回链到采集来源。

九、置信度标尺:每边必带、绝不 0.5、离散取值

规范用一个独立小节把打分制度讲得非常死:

  • confidence_score 在每条边上都必填——永不省略;
  • 永远不要用 0.5 当默认值;
  • EXTRACTED 边:恒为 1.0;
  • INFERRED 边:从下面恰好取一个离散值:
值含义
0.95直接结构证据(共享数据结构、具名跨文件引用)
0.85强推断(清晰的功能对齐,但无直接符号链)
0.75合理推断(共享问题域 + 相似形态,需要解读)
0.65弱推断(主题相关,无形态证据)
0.55推测但合理(仅表面共现)
—都不合适?标 AMBIGUOUS,不要选 0.4 及以下
  • AMBIGUOUS 边:0.1–0.3。

规范还解释了为何如此设计:模型遵循离散标尺远好于连续区间。生产观测到明显的双峰分布(>50% 堆在 0.5、>40% 堆在 0.85+),说明区间引导正被模型坍缩成二值判断。离散取值 + 禁用 0.5 就是针对这一退化模式的工程性对抗。这与 graphify/llm.py 顶层系统提示词中的打分规则完全同源(同见 INFERRED edges: pick exactly ONE value 注释)。

十、确定性节点 ID:与 AST 抽取器对得上,否则就是幽灵重复

节点 ID 是全篇对工程质量要求最高的部分,因为 ID 必须与 AST 抽取器生成的 ID 完全一致:

  • 只允许小写 [a-z0-9_],不含点号、斜杠;
  • 格式:{stem}_{entity}
    • stem = 完整仓库相对路径去掉扩展名,每一级目录都保留,逐段小写、非字母数字字符替换为 _;
    • entity = 符号名,同样规范化;
  • 用每一级目录而非仅直接父目录,从而区分不同目录下的同名文件。

规范给出的正例对照表:

源文件 + 符号期望 ID
src/auth/session.py + ValidateTokensrc_auth_session_validatetoken
lib/utils/helpers.py + parse_urllib_utils_helpers_parse_url
tests/test_foo.py + _helpertests_test_foo_helper
docs/v1/api/README.md + getUserdocs_v1_api_readme_getuser
顶层文件 setup.py + my_funcsetup_my_func

并给出反面教材:只留文件名(session_validatetoken)或只留直接父目录(auth_session_validatetoken)都会产生 孤儿幽灵重复节点。如果要对旧版“仅直接父目录”格式的项目重新抽取,规范要求用户运行 graphify extract --force 干净重建。最关键的纪律是:永远不要给 ID 追加分块号、序号或任何后缀(禁止 _c1、_c2、_chunk2),ID 必须由标签本身确定性决定——同一实体无论被哪个分块处理,都必须产出同一 ID。

这一确定性约束在实现层有对应物:graphify/ids.py 的 normalize_id(graphify/ids.py)通过 casefold + NFKC 迭代至不动点、再过滤到 [a-z0-9_],保证幂等、大小写折叠稳定、仅含 \w 与下划线。整条管线对“同一实体稳定映射同一 ID”的追求贯穿 graphify/extract.py(例如把 AST 文件节点与语义分块合并时避免拆出幽灵节点的注释),这正是 Part B 分块能并行、Part C 又能无歧义合并的前提。

十一、完整输出 JSON 模式(逐字继承)

子代理必须输出唯一合法的 JSON,无解释、无 Markdown 围栏、无前言。模式原文如下:

{
  "nodes": [
    {
      "id": "auth_session_validatetoken",
      "label": "Human Readable Name",
      "file_type": "code|document|paper|image|rationale|concept",
      "source_file": "<FILE_LIST path verbatim>",
      "source_location": null,
      "source_url": null,
      "captured_at": null,
      "author": null,
      "contributor": null
    }
  ],
  "edges": [
    {
      "source": "node_id",
      "target": "node_id",
      "relation": "calls|implements|references|cites|conceptually_related_to|shares_data_with|semantically_similar_to|rationale_for",
      "confidence": "EXTRACTED|INFERRED|AMBIGUOUS",
      "confidence_score": 1.0,
      "source_file": "<FILE_LIST path verbatim>",
      "source_location": null,
      "weight": 1.0
    }
  ],
  "hyperedges": [
    {
      "id": "snake_case_id",
      "label": "Human Readable Label",
      "nodes": ["node_id1", "node_id2", "node_id3"],
      "relation": "participate_in|implement|form",
      "confidence": "EXTRACTED|INFERRED",
      "confidence_score": 0.75,
      "source_file": "<FILE_LIST path verbatim>"
    }
  ],
  "input_tokens": 0,
  "output_tokens": 0
}

字段要点归纳:

  • 边关系取值枚举:calls | implements | references | cites | conceptually_related_to | shares_data_with | semantically_similar_to | rationale_for;
  • 超边关系枚举:participate_in | implement | form;
  • 节点顶层另有可选的 rationale 字段承载“为什么”(见第三节);LLM 后端模式(graphify/llm.py)中的 schema 还补充了 rationale 键与面向后端的提示变体;
  • input_tokens/output_tokens 由子代理填充(LLM 后端会回填真实 usage,见 graphify/skill-trae.md 对占位零值的说明)。

十二、source_file 溯源契约:逐字照抄,绝不改写

凡节点、边、超边,source_file 都必须设为来源文件在 FILE_LIST 中出现时的原样路径——逐字且为绝对路径:

  • 不要缩写成 basename;
  • 不要重新相对化;
  • 不要剥掉任何目录前缀;
  • 不要改分隔符——引擎会在下游统一分隔符并相对化到构建根目录。

原因规范解释得很直白:FILE_LIST 条目需逐字符复制,才能让全量构建与增量 --update 站在同一基线上,使 build_merge 的“重抽即替换”(replace-on-re-extract)命中既有节点而不是不断累积重复。若每个分块都按自己的“本地视角”改路径,同源文件的多次抽取就会变成永不重合的重复节点。

十三、落盘纪律:绝对路径 CHUNK_PATH

子代理产出 JSON 后,必须用 Write 工具写到规范给定的确切绝对路径 CHUNK_PATH。规范特别强调:不允许相对路径——Write 会相对一个未定义的 cwd 解析相对路径,文件将被静默丢失。这正是把“Part C 合并”与“B3 缓存回写”建立在磁盘文件存在性之上的原因(见 graphify/skill-trae.md:以文件存在作为成功信号,缺失则告警“子代理可能被派发成只读 Explore 类型”)。

十四、从提示词到流水线:Trae 平台上的 B0–B3 装配

规范文档并非孤立存在,它在 graphify/skill-trae.md 的调度代码中按 B0–B3 被实例化:

  1. B0 缓存检查:对 detect 结果中 document/paper/image 三类文件调用 graphify.cache.check_semantic_cache,传入 prompt_file=SPEC_PATH(规范文件的绝对路径)。由于缓存条目按提示词归属(issue #1939),graphify 升级改过提示词后旧条目会重新抽取,提示词未变则复用。只对 uncached 列表派发子代理。
  2. B1 分块:每块 20–25 个文件;每张图片独占一块(视觉需要独立上下文);同目录文件尽量合块以增加抽取跨文件关系的机会。
  3. B2 单消息并行派发:对每个块调用一次 Task,且全部在同一个响应里发出以并行执行;把规范提示词(替换好 5 个占位符)作为任务描述,子代理各自写到 graphify-out/.graphify_chunk_NN.json。Trae 平台的一个关键差异是:不支持 PreToolUse 钩子,因此 AGENTS.md 规则才是常驻的机制(见 graphify/skill-trae.md)。
  4. B3 收集 / 缓存 / 合并:以磁盘文件为成功信号收集各块,无效 JSON 告警跳过;回填真实 token 数后把 _graphify_chunk_* 合并为 _graphify_semantic_new.json,再经 save_semantic_cache 入缓存(同样带 SPEC_PATH 戳记),最终与缓存命中合并进 .graphify_semantic.json 供 Part C 使用。超过一半块失败即停止并提示用 general-purpose 子代理重跑。

整条链路里,本规范(extraction-spec)既是被缓存体系“指纹化”的对象(提示词变了缓存即失效),又是并行子代理唯一的行为契约——前后一致、单一事实来源。

十五、工程要点自查清单

把规范浓缩成可执行的验收标准:

  1. 输出纪律:仅输出合法 JSON,无解释、无 Markdown 围栏、无前言;
  2. 定性先行:每条边先定 EXTRACTED/INFERRED/AMBIGUOUS,AMBIGUOUS 宁标勿删;
  3. 与 AST 分工:代码文件不重抽 import,只补语义边;calls 方向 source=调用方,且严禁跨语言;
  4. rationale 不建点:设计理由挂到具名概念节点的 rationale 属性上;只有概念本身才可用 file_type:"rationale";
  5. 图片靠视觉:按图型抽取本质而非做 OCR;
  6. 打分禁用 0.5:EXTRACTED=1.0;INFERRED 只在 {0.95,0.85,0.75,0.65,0.55} 中取值,不匹配则标 AMBIGUOUS(0.1–0.3);
  7. ID 确定性:{完整相对路径去扩展名}_{实体}、全小写 [a-z0-9_]、不加任何分块后缀;旧格式工程用 graphify extract --force 重建;
  8. source_file 逐字:来自 FILE_LIST 原样绝对路径,保证全量与增量共享基线;
  9. 落盘用绝对路径:写到 CHUNK_PATH,相对路径会静默丢文件。

十六、延伸阅读

  • 平台技能全流程:graphify/skill-trae.md(Step 3 及 B0–B3 代码);各 Agent 平台的同名技能文件(graphify/skill-agents.md、graphify/skill-claude.md、graphify/skill-codex.md 等)均复用同款规范,各有平台派发差异;
  • LLM 后端系统提示词与模式:graphify/llm.py(_EXTRACTION_SYSTEM、_DEEP_EXTRACTION_SUFFIX、extract_corpus_parallel);
  • 语义缓存归属机制:graphify/cache.py(check_semantic_cache / save_semantic_cache 的 prompt_file 参数);
  • ID 规范化实现:graphify/ids.py(normalize_id 的 casefold + NFKC 迭代);AST 侧结构化抽取见 graphify/extract.py 与 graphify/extractors。

一言以蔽之:这份 extraction-spec 是 graphify“无向量库、全图可解释”主张在语义层的落地契约——用确定性的 ID 与离散置信度,把 LLM 的自由文本输出约束成可合并、可缓存、可增量的图谱事实。

【免费下载链接】graphify Turn 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. 【免费下载链接】graphify 项目地址: https://gitcode.com/GitHub_Trending/graph/graphify

更多推荐