Understand-Anything 节点ID命名规范深度解析:file:、function: 前缀规则与别名归一化完全指南
【免费下载链接】Understand-AnythingGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.项目地址: https://gitcode.com/GitHub_Trending/un/Understand-Anything
Understand-Anything 是一款将任意代码库转换为交互式知识图谱的开源工具,支持在 Claude Code、Codex、Cursor、Copilot、Gemini CLI 等 AI 编程助手中直接探索、搜索并提问。而这一切的地基,是一套严格的节点 ID 命名规范——每个文件、函数、类、配置都在图谱中拥有file:、function:这样带前缀的唯一身份。本文带你完整读懂这套规范的设计逻辑与别名归一化机制,帮你快速上手知识图谱数据格式。
为什么知识图谱需要「节点 ID 命名规范」?
知识图谱由两类元素组成:
- 节点(Node):文件、函数、类、模块、配置、文档等
- 边(Edge):
imports、calls、contains等关系
边通过节点 ID 引用两端,因此ID 就是图谱的"主键"。一旦 ID 写错(比如 LLM 输出src/utils.ts而不是file:src/utils.ts),引用它的边就会悬空,整个子图随之断裂。Understand-Anything 因此做了两件事:
- 定义一套统一的前缀格式(
<类型前缀>:<路径>[:<名称>]) - 内置一套归一化流水线,自动修复 LLM 生成的各种"不规范 ID"
核心实现位于 normalize-graph.ts,完整规范文档见 SKILL.md。
13 种节点类型前缀一览
知识图谱共定义 13 种节点类型,每种对应一个(或多个)合法前缀:
| 类型 | 说明 | ID 规范 |
|---|---|---|
file | 源码文件 | file:<相对路径> |
function | 函数或方法 | function:<相对路径>:<名称> |
class | 类、接口、类型 | class:<相对路径>:<名称> |
module | 逻辑模块/包 | module:<名称> |
concept | 抽象概念或模式 | concept:<名称> |
config | 配置文件(YAML/JSON/TOML) | config:<相对路径> |
document | 文档(Markdown 等) | document:<相对路径> |
service | 可部署服务定义 | service:<相对路径> |
table | 数据库表/迁移 | table:<相对路径>:<表名> |
endpoint | API 端点/路由 | endpoint:<相对路径>:<端点名> |
pipeline | CI/CD 流水线 | pipeline:<相对路径> |
schema | Schema 定义 | schema:<相对路径> |
resource | 基础设施资源 | resource:<相对路径> |
完整定义可参考 SKILL.md 中的 KnowledgeGraph Schema 参考。
两大核心前缀:file: 与 function:
绝大多数图谱节点由这两类构成:
file:src/index.ts—— 文件节点,前缀后紧跟相对路径function:src/utils.ts:formatDate—— 函数节点,三段式:类型:路径:函数名
构建时,图谱会在文件与函数之间自动建立contains边(权重 1.0),函数之间建立calls边(权重 0.8)。生成逻辑见 graph-builder.ts。
💡 记住这个规律:文件类节点是"两段",符号类节点是"三段"(类型:路径:名称)。
别名归一化:normalizeNodeId 如何修复脏 ID
真实场景中,LLM 分批分析产出的 ID 五花八门。归一化函数 normalizeNodeId() 能自动修复以下四类问题,且幂等——正确 ID 原样通过:
| 原始 ID(问题) | 修复后 | 修复类型 |
|---|---|---|
file:file:src/foo.ts | file:src/foo.ts | 双重前缀 |
my-project:file:src/foo.ts | file:src/foo.ts | 项目名前缀 |
frontend/src/utils.ts | file:frontend/src/utils.ts | 裸路径缺前缀 |
formatDate(带 filePath 元数据) | func:src/utils.ts:formatDate | 从元数据重建 |
file:src/foo.ts | file:src/foo.ts | 首尾空白 |
修复策略分三步:
- 剥离开头非法片段:按冒号逐段剥离,直到遇到合法前缀(
file、func、class、config等 16 种),或耗尽为止 - 处理双重前缀:如
file:file:src/foo.ts,跳过外层保留内层 - 兜底重建:裸 ID 若是函数/类节点,会用节点的
filePath+name元数据重建为完整三段式 ID
所有行为均有测试覆盖,可参考 normalize-graph.test.ts。
批量归一化流水线:从 LLM 输出到最终图谱
单个 ID 修好了还不够——边(Edge)引用的也是 ID。normalizeBatchOutput() 执行完整的批量流水线:
- Pass 1:归一化所有节点 ID,同时把复杂度值(如数字
4、字符串"trivial")映射到simple/moderate/complex - 去重:同 ID 节点只保留最后一个
- Pass 2:通过 ID 映射表重写所有边的
source/target引用;对映射表未覆盖的端点,再从边 ID 自身推断类型二次归一化 - 丢弃悬空边:引用不存在节点的边被移除并记录原因(
missing-source/missing-target)
同时,合并脚本 merge-batch-graphs.py 还会执行一个经典修复:func:→function:前缀归一化——这是 LLM 最常见的输出变体,脚本会在 stderr 报告修复数量(如170 × func: → function:),语义层面的剩余问题由 assemble-reviewer 智能体 接手复核。
类型别名表:LLM 写错类型也能自动纠正
除了 ID,节点的type字段也有别名归一化。核心别名表 NODE_TYPE_ALIASES 覆盖了 LLM 常用的"非正式叫法":
func、fn、method→functioninterface、struct→classdoc、readme、docs→documentci、job→pipelineapi、route、query→endpointdb、migration、view→table
边类型同样有一张 EDGE_TYPE_ALIASES 表:extends→inherits、invokes→calls、import→imports等。有意思的是,implemented_by被故意排除在别名之外——因为它会反转边的方向,自动纠正比保留正确语义更有风险。
新手速查:三句话记住命名规范
- ✅ 文件节点:
file:src/App.tsx,配置:config:tsconfig.json,文档:document:README.md - ✅ 符号节点:
function:src/utils.ts:formatDate、class:src/models/User.ts:User(路径 + 名称缺一不可) - ✅ 拿不准就交给归一化——只要节点带有
type、filePath、name元数据,normalizeNodeId就能自动重建正确 ID
了解规范后,你可以打开仪表盘直观查看每个节点的真实 ID 与连接关系:
写在最后
节点 ID 命名规范看似枯燥,实则是 Understand-Anything 知识图谱"教代码"能力的基石:统一的主键让边引用可靠、让增量更新可比对、让 LLM 的随机输出变得可控。掌握file:/function:前缀规则与别名归一化机制,你就能读懂甚至手写一份合格的知识图谱 JSON——这正是玩转这套工具的第一步。
【免费下载链接】Understand-AnythingGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.项目地址: https://gitcode.com/GitHub_Trending/un/Understand-Anything
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考