ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

qwen-code 内置 CodeScope 图数据库 Schema 全解:节点、边与 Cypher 查询实践

qwen-code 内置 CodeScope 图数据库 Schema 全解:节点、边与 Cypher 查询实践 qwen-code 内置 CodeScope 图数据库 Schema 全解节点、边与 Cypher 查询实践【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-codeCodeScope 是 qwen-code 仓库中内置的代码知识图谱技能codegraph skill所依赖的图数据模型它把源码库索引成“结构 演化”双层图并叠加函数级语义向量从而支撑调用图分析、死代码识别、变更归因、Bug 根因定位与 PR 风险评估等能力。本文以 schema.md 为主线完整讲解 CodeScope 的节点Nodes、边Edges、回填状态Backfill State以及 neug 图引擎的 Cypher 语法能力并结合配套的 SKILL.md、patterns.md、bug-analysis.md 与 pr-analysis.md 给出可直接复用的查询模板。读完本文你将能看懂.codegraph索引的内部结构写出准确、高效的 Cypher 查询并理解MODIFIES/TOUCHES/CHANGES等演化边在何时可用、如何规避查询误区。一、Schema 总览两层知识图谱 语义向量CodeScope 将源码索引为一张双层知识图谱结构层structure以File、Function、Class、Module为节点用CALLS、IMPORTS、DEFINES_FUNC、HAS_METHOD、BELONGS_TO以及 UML 风格的INHERITS/COMPOSES/AGGREGATES/USES边描述代码的静态组织关系解析来源为 AST演化层evolution以Commit、PR、AUTHOR为节点用MODIFIES、TOUCHES、CHANGES、OPENS边把提交与 PR 关联到具体的函数与文件语义层semantic embeddings为每个函数生成向量嵌入通过zvec向量索引支持vector_only_search、similar、cross_locate等语义检索。当前 CodeScope 支持 Python、JavaScript/TypeScript、C、Java含 Hadoop 级 8K 文件规模的仓库。整套 schema 由 schema.md 统一定义是理解所有上层 APIcs.impact()、cs.hotspots()、cs.change_attribution()、cs.analyze_issue()等的底层基础。二、节点类型Nodes8 类节点的属性与语义节点关键属性说明Fileid, path, language, loc, is_externalis_external1表示系统头文件 / 库桩文件Functionid, name, qualified_name, signature, file_path, start_line, end_line, doc_comment, class_name, is_historicalis_historical1表示已删除 / 重命名的历史函数Classid, name, qualified_name, file_path—Moduleid, name, path_prefix从目录自动发现如kernel/schedCommitid, hash, message, author, timestamp, version_tagversion_tagbf表示已计算 MODIFIES 边Metadataid, value管线状态如oldest_commitPRid, title, author, risk_level, label打开的 PR由codegraph pr-review prepare写入AUTHORlogin, name, company, location, bio, avatar_url打开 PR 的 GitHub 用户几个需要重点理解的设计细节File.is_external与Function.is_historical是查询过滤器。系统头文件、库桩以及已删除/重命名的“幽灵函数”仍保留在图中作为历史记录但绝大多数分析场景都要把它们排除详见下文“查询过滤器”一节。Commit.version_tag是演化分析的开关。只有version_tag bfbackfilled的提交才带有函数级的MODIFIES边未回填的提交只有文件级TOUCHES边。这一点直接决定了哪些演化查询可用。PR与AUTHOR节点不是索引阶段产生的而是运行codegraph pr-review prepare时由 pr-analysis.md 描述的CrossPRAnalyzer写入图中的。AUTHOR节点通过OPENS边指向其发起的PRPR节点上的risk_level与label列则由pr-review label持久化label 以分号分隔。Module节点按目录前缀自动发现例如kernel/sched文件通过BELONGS_TO边挂到模块上。跨模块耦合分析cs.module_coupling()与层发现cs.layer_discovery()都依赖这一组织方式。三、边类型Edges14 类关系的含义与用法边From → To含义CALLSFunction → Function静态调用图从 AST 解析DEFINES_FUNCFile → Function文件定义此函数DEFINES_CLASSFile → Class文件定义此类HAS_METHODClass → Function类包含此方法IMPORTSFile → Fileinclude / import 依赖BELONGS_TOFile → Module文件属于此模块INHERITSClass → Class类继承COMPOSESClass → Class组合关系强所有权UML 实心菱形AGGREGATESClass → Class聚合关系可选/弱引用UML 空心菱形USESClass → Class依赖关系按调用使用UML 虚线箭头MODIFIESCommit → Function提交修改了此函数需回填TOUCHESCommit → File提交修改了此文件始终存在CHANGESPR → FunctionPR 修改此函数infohunkdiff 中修改、deleted删除、related新增调用、new新增OPENSAUTHOR → PR作者发起此 PR3.1 结构类边调用图与归属关系CALLS边是静态调用图的骨架由 AST 解析得到是impact()影响面分析、hotspots()扇入×扇出风险排名、dead_code()零调用者检测、bridge_functions()跨模块桥函数等方法的底层数据。查询“谁调用了free_irq”即围绕CALLS边展开MATCH (caller:Function)-[:CALLS]-(f:Function {name: free_irq}) RETURN caller.name, caller.file_path ORDER BY caller.name LIMIT 30DEFINES_FUNC/DEFINES_CLASS/HAS_METHOD完成 File、Class、Function 三者之间的挂接BELONGS_TO将文件归入自动发现的模块。例如按模块统计函数规模MATCH (f:Function)-[:DEFINES_FUNC]-(file:File)-[:BELONGS_TO]-(m:Module) WHERE f.is_historical 0 RETURN m.path_prefix, count(f) AS func_count ORDER BY func_count DESC LIMIT 303.2 UML 类关系边COMPOSES / AGGREGATES / INHERITS / USESCodeScope 在索引阶段从类字段与类型注解中提取三种 UML 关系参见 SKILL.md关系UML 符号含义检测方式COMPOSES*--实心菱形强所有权——字段始终持有实例非可选字段且赋值为构造对象AGGREGATESo--空心菱形可选/弱引用——可能为NoneOptional[X]、X \| None或赋值为NoneINHERITS\|--空心箭头子类继承父类class A(B)USES为按调用计数的依赖关系虚线箭头语义。查询示例# 获取所有组合关系A 强持有 B list(cs.conn.execute(MATCH (c1:Class)-[:COMPOSES]-(c2:Class) RETURN c1.name, c2.name)) # 获取所有聚合关系A 可选持有 B list(cs.conn.execute(MATCH (c1:Class)-[:AGGREGATES]-(c2:Class) RETURN c1.name, c2.name)) # 某个类直接拥有多少对象 list(cs.conn.execute(MATCH (c:Class {name: Llama})-[:COMPOSES]-(t:Class) RETURN t.name)) # 类的完整依赖图组合 聚合 继承 list(cs.conn.execute( MATCH (c:Class {name: GPUModelRunner})-[r:COMPOSES|AGGREGATES]-(t:Class) RETURN type(r), t.name ))这三类边可以一键渲染为 MermaidclassDiagram见 SKILL.md 的“Generating a Mermaid class diagram”一节inherits list(cs.conn.execute(MATCH (c1:Class)-[:INHERITS]-(c2:Class) RETURN c1.name, c2.name)) composes list(cs.conn.execute(MATCH (c1:Class)-[:COMPOSES]-(c2:Class) RETURN c1.name, c2.name)) aggregates list(cs.conn.execute(MATCH (c1:Class)-[:AGGREGATES]-(c2:Class) RETURN c1.name, c2.name)) print(classDiagram) for src, tgt in inherits: print(f {tgt} |-- {src}) # parent |-- child for src, tgt in composes: print(f {src} *-- {tgt}) # owner *-- owned for src, tgt in aggregates: print(f {src} o-- {tgt}) # holder o-- optional3.3 演化类边MODIFIES / TOUCHES / CHANGES / OPENS演化层边将“代码发生了什么变化”与图结构关联起来TOUCHESCommit → File提交改动的文件所有已摄入的提交始终存在用于文件级演化查询例如“哪些文件被修改最频繁”MATCH (c:Commit)-[:TOUCHES]-(f:File) RETURN f.path, count(c) AS commits ORDER BY commits DESC LIMIT 20MODIFIESCommit → Function提交改动的函数仅在回填后存在见第四节。它支撑change_attribution()哪些提交改过某函数与co_change()常一起修改的函数。例如MATCH (c:Commit)-[:MODIFIES]-(f:Function) WHERE c.hash STARTS WITH abc123 RETURN f.name, f.file_pathCHANGESPR → FunctionPR 与函数的修改关系info属性区分四种类型见 pr-analysis.md 的_write_pr_graph_nodes流程hunkPR 修改了此函数在图中按name file_path确认deletedPR 删除了此函数按name file_path确认relatedPR 新增调用了此函数按name确认newPR 新增的函数图中尚不存在无需预确认。查询单个 PR 改动的函数MATCH (pr:PR {id: 439})-[c:CHANGES]-(f:Function) RETURN c.info AS change_type, f.name, f.file_path ORDER BY c.info, f.nameOPENSAUTHOR → PR记录 PR 作者用于按作者聚合或过滤分析。CHANGES边是跨 PR 冲突检测的核心当两个 PR 以hunk/deleted指向同一函数时它们处于同一连通分量需要成批评审见 pr-analysis.md 的 usecase3 查询。四、回填状态Backfill StateMODIFIES 边何时可用Schema 中一个非常关键的约束是并非所有提交都带有MODIFIES边只有version_tag bf的提交才有而TOUCHES边对所有已摄入提交始终存在。原因在于MODIFIES是函数级边需要额外的 diff 分析代价更高。索引时通过--backfill-limit控制回填数量参见 SKILL.md# 首次索引摄入 git 历史并回填 200 个提交的函数级 MODIFIES 边 codegraph init --repo . --lang auto --commits 500 --backfill-limit 200 # 已建索引后增量补充只加 MODIFIES 边无需重建结构 codegraph ingest --repo . --db $CODESCOPE_DB_DIR --backfill-limit 200对应的状态检查 Cypher-- 已回填有 MODIFIES 边的提交数 MATCH (c:Commit) WHERE c.version_tag bf RETURN count(c) AS backfilled-- 全部已摄入提交数 MATCH (c:Commit) RETURN count(c) AS total_commits在写演化类查询前建议先用这两条语句摸清数据可用性SKILL.md 的 “Checking Data Availability” 一节也给出了 Python 等价写法# 多少提交被索引 list(cs.conn.execute(MATCH (c:Commit) RETURN count(c))) # 多少提交带有 MODIFIES 边已回填 list(cs.conn.execute(MATCH (c:Commit) WHERE c.version_tag bf RETURN count(c)))判断规则若图中没有任何提交演化类方法返回空结果——先引导用户运行codegraph ingest --commits ...若提交存在但未回填TOUCHES文件级查询仍可用MODIFIES函数级查询不可用。五、neug Cypher 参考支持的语法与限制Schema 文档同时界定了底层图引擎neug的 Cypher 方言能力这是编写安全查询的前提。5.1 支持的语法MATCH、WHERE、RETURN、ORDER BY、LIMIT、WITH聚合count()、count(DISTINCT x)内联属性过滤{name: foo}变长路径[*1..3]字符串谓词STARTS WITH、CONTAINS、ENDS WITH比较、、、、、布尔AND、OR、NOT例如利用变长路径查询多跳调用者MATCH (caller:Function)-[:CALLS*1..3]-(f:Function {name: kfree}) RETURN DISTINCT caller.name, caller.file_path LIMIT 50利用内联属性过滤 字符串谓词按名称模式查函数MATCH (f:Function) WHERE f.name STARTS WITH irq_ RETURN f.name, f.file_path LIMIT 205.2 限制LimitationsWITH之后链式MATCH可能受限——优先使用单个MATCH子句用逗号分隔多个模式。例如跨模块调用统计就是把多条路径写进一个MATCHMATCH (f1:Function)-[:CALLS]-(f2:Function), (file1:File)-[:DEFINES_FUNC]-(f1), (file2:File)-[:DEFINES_FUNC]-(f2), (file1)-[:BELONGS_TO]-(m1:Module {path_prefix: fs}), (file2)-[:BELONGS_TO]-(m2:Module {path_prefix: mm}) RETURN f1.name, f2.name, count(*) AS calls ORDER BY calls DESC LIMIT 20不支持通过 Cypher 执行CREATE/SET/DELETE——图的写入例如pr-review prepare写入 PR 节点与CHANGES边、pr-review label持久化 label统一走 Python APICrossPRAnalyzer/PRReview。Cypher 只负责查询pr-analysis.md 也确认 PR 节点是临时性的prepare()每次运行前会删除既有PR节点与CHANGES边再重新插入。六、查询过滤器避免误导性结果的关键在 SKILL.md 的 “Important Filters for Cypher” 一节中明确列出了四个写查询时必须带上的过滤器f.is_historical 0——排除已删除/重命名的历史函数它们仍在图中作为历史记录f.is_external 0File 节点——排除系统头文件与库文件c.version_tag bf——只有回填过的提交才有MODIFIES边未回填提交只有TOUCHES文件级边总是使用LIMIT——大型代码库可能返回数十万行。一个完整的扇入/扇出风险查询同时体现过滤器与聚合MATCH (caller:Function)-[:CALLS]-(f:Function)-[:CALLS]-(callee:Function) WHERE f.is_historical 0 WITH f, count(DISTINCT caller) AS fi, count(DISTINCT callee) AS fo RETURN f.name, f.file_path, fi, fo, fi * fo AS risk ORDER BY risk DESC LIMIT 20此外 pr-analysis.md 还特别提醒不要通过 JOINFunction与File节点来定位函数如file.path ENDS WITH ...因为Function节点自身就存有完整路径f.file_path应始终用f.file_path ENDS WITH ...查询。七、Schema 之上的能力地图从结构查询到 Bug/PR 分析理解了节点、边与回填状态后整套 codegraph skill 的高层 API 就可以映射回这些图元素能力底层图/向量依据入口调用者/被调用者、影响面CALLS边 语义相关性cs.impact()、裸 Cypher热点函数扇入×扇出cs.hotspots()死代码零扇入排除入口点cs.dead_code()循环依赖、模块耦合、桥函数IMPORTS/BELONGS_TO/CALLScs.circular_deps()、cs.module_coupling()、cs.bridge_functions()类层次与 UML 图INHERITS/COMPOSES/AGGREGATEScs.class_hierarchy()、裸 Cypher Mermaid变更归因 / 共同变更MODIFIES边需回填cs.change_attribution()、cs.co_change()提交意图搜索Commit 节点 语义cs.intent_search()Bug 根因定位File/Function 节点匹配 cross_locateimpactcs.analyze_issue()、cs.analyze_top_bugs()PR 风险与冲突PR/CHANGES边 CALLS连通分量codegraph pr-review prepare、PRReview例如 patterns.md 中的“共同变更函数”查询直接落在MODIFIES边上MATCH (c:Commit)-[:MODIFIES]-(f1:Function), (c)-[:MODIFIES]-(f2:Function) WHERE f1.id f2.id RETURN f1.name, f2.name, count(c) AS co_changes ORDER BY co_changes DESC LIMIT 20而 bug-analysis.md 的“将 Bug 关联到修复提交”则是issue.linked_commitsMODIFIES边的组合for sha in issue.linked_commits: rows list(cs.conn.execute(f MATCH (c:Commit)-[:MODIFIES]-(f:Function) WHERE c.hash STARTS WITH {sha[:12]} RETURN f.name, f.file_path ))PR 侧pr-analysis.md的跨 PR 冲突检测则同时使用CHANGES与CALLS边-- 两个 PR 修改/删除了同一函数自动化连通分量检测的依据 MATCH (pr1:PR)-[c1:CHANGES]-(f:Function)-[c2:CHANGES]-(pr2:PR) WHERE c1.info IN [hunk,deleted] AND c2.info IN [hunk,deleted] AND pr1.id pr2.id RETURN pr1.id, pr2.id -- 依赖链重叠PR A 改的函数被 PR B 改的函数调用 MATCH (pr1:PR)-[c1:CHANGES]-(f:Function)-[:CALLS]-(g:Function)-[c2:CHANGES]-(pr2:PR) WHERE c1.info hunk AND c2.info hunk AND pr1 pr2 RETURN pr1.id, pr2.id八、实操要点数据检查与故障排查在动手查询前建议按 SKILL.md 的步骤确认索引状态codegraph status --db $CODESCOPE_DB_DIR无索引时创建索引--commits摄入 git 历史以启用演化查询--backfill-limit启用函数级MODIFIEScodegraph init --repo . --lang auto --commits 500 --backfill-limit 200Python 侧统一入口import os os.environ[HF_HUB_OFFLINE] 1 # 使用本地模型权重时必须设置 from codegraph.core import CodeScope cs CodeScope(os.environ[CODESCOPE_DB_DIR]) rows list(cs.conn.execute( MATCH (caller:Function)-[:CALLS]-(f:Function {name: free_irq}) RETURN caller.name, caller.file_path LIMIT 10 )) for r in rows: print(r) cs.close() # 用完后务必关闭最后SKILL.md 的 Troubleshooting 表也针对图/向量存储常见问题给出了处置建议例如数据库锁文件残留、zvec LOCK 文件丢失、stale WAL 导致的recovery idmap failed等CLI 在启动时会尽可能自动清理锁问题。理解这些边界条件能帮助你在基于 schema 编写查询时少走弯路——记住一条核心原则先查version_tag与is_historical/is_external再决定查询策略图写入走 Python APICypher 只做读取。参考文档.qwen/skills/codegraph/schema.md——图 Schema 权威定义节点、边、回填状态、Cypher 语法.qwen/skills/codegraph/SKILL.md——codegraph skill 总览安装、索引、核心 API、过滤器、排障.qwen/skills/codegraph/patterns.md——可直接复用的 Cypher 模板与组合策略.qwen/skills/codegraph/bug-analysis.md——Bug 根因分析工作流.qwen/skills/codegraph/pr-analysis.md——PR 影响分析与跨 PR 冲突检测【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表