阅读时间 : 12 minutes

您的代码库在增长。模块之间的依赖关系在增加。架构文档在还未写完之前就已经过时。如果您的 Gradle 构建能够 automatiquement 根据实际代码结构生成最新的图表,那将会怎样?这正是 Graphify + PlantUML Gradle 插件 pipeline 所实现的:graphify . --no-viz`提取 Knowledge Graph,./gradlew generateKnowledgeGraphDiagram`它转换为PlantUML图。零 LLM,零手册,100% 确定性。

问题:图表总是落后于代码

任何超过几千行的项目都会遇到这种综合征:

  1. 在项目开始时绘制一个架构图

  2. 代码在演变,依赖关系在变化

  3. 图表变成了装饰性的谎言

  4. 没有人愿意更新它,因为这很麻烦。

  5. 新来的人以此为依据并犯错

@startuml
skinparam backgroundColor #FEFEFE
skinparam ActivityBackgroundColor #FDEDEC
skinparam ActivityDiamondBackgroundColor #FFF3CD

start

:架构图已创建\n(手动,手工);

:代码在演变\n(新类,新依赖);

:已过时的图表\n(不再反映代码);

if (Qui met à jour ?) then (Personne)
    :误导性文档;
    note right: 新开发者\n以此为依据...并犯错误
else (Quelqu'un)
    :手动更新\n(2-3 小时的工作);
    note right: 已经 过时\n在 下一个 PR
endif

stop

@enduml

问题不是 是否需要图表 ? — 毫无疑问,大家都知道答案是肯定的。问题:谁在保持它们最新?

答案:没有人。除非是自动的。

解决方案:确定性 Knowledge Graph → PlantUML 管道

原则很简单:不是手动绘制图表,而是我们生成自代码的实际结构。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur
component "Graphify\n(pip install graphifyy)" as Graphify
collections "graphify-out/graph.json\n(知识图谱)" as KGJSON
component "PlantUML Gradle 插件\n(generateKnowledgeGraphDiagram)" as Plugin
component "KnowledgeGraphParser" as Parser
component "KnowledgeGraphRenderer" as Renderer
component "PlantumlService\n(验证 + 渲染 PNG)" as PS
collections "图表/knowledge-graph/\n(.puml + .png)" as Output

Développeur --> Graphify : graphify . --no-viz
Graphify --> KGJSON : 提取源代码中的 \n 结构
Développeur --> Plugin : ./gradlew generateKnowledgeGraphDiagram
Plugin --> Parser : parse(graph.json)
Parser --> Plugin : KnowledgeGraph\n(节点 + 边 + 社区)
Plugin --> Renderer : render(graph, filters)
Renderer --> Plugin : 代码 PlantUML\n确定性
Plugin --> PS : validateSyntax + generateImage
PS --> Output : .puml + .png

note bottom of Plugin
流水线 DÉTERMINISTE
没有调用 LLM
可再现的结果
end note

@enduml

只有两个命令。

# Étape 1 : extraire le Knowledge Graph
graphify . --no-viz

# Étape 2 : générer les diagrammes PlantUML
./gradlew generateKnowledgeGraphDiagram

结果?文件`.puml` et .png`在`diagrams/knowledge-graph/, 在 Git 中进行版本控制,始终与代码保持同步。

步骤 1:安装 Graphify 并提取 Knowledge Graph

安装

Graphify 是一个 Python 工具,它分析您的代码库并构建一个结构化的知识图谱:

# Méthode recommandée
uv tool install graphifyy && graphify install --platform opencode

# Alternative avec pip
pip install graphifyy && graphify install --platform opencode

配置排除项

创建一个文件`.graphifyignore`在项目根目录下,以排除不属于业务逻辑的文件:

# Secrets — JAMAIS dans le graphe
*-context.yml
*.env

# Fichiers générés
build/
.gradle/

# Tests fonctionnels
src/functionalTest/

提取知识图谱

graphify . --no-viz

标志`--no-viz`跳过HTML生成(在Gradle流水线中不必要)。结果是一个文件`graphify-out/graph.json`包含 :

  • 节点: 类、函数、文件 — 它们的类型和社区

  • 边缘: 节点之间的关系(从代码中提取,由LLM推断)

  • 社区: 自动分组的关联节点

结构示例`graph.json`
{
  "nodes": [
    {"id": "0", "label": "LlmService", "file_type": "code", "community": 0},
    {"id": "1", "label": "ApiKeyPool", "file_type": "code", "community": 0},
    {"id": "2", "label": "PlantumlService", "file_type": "code", "community": 1}
  ],
  "links": [
    {"source": "1", "target": "0", "relation": "uses", "confidence": "EXTRACTED", "weight": 0.9},
    {"source": "0", "target": "2", "relation": "calls", "confidence": "INFERRED", "weight": 0.7}
  ]
}

源代码 (.kt, .java) 由 tree-sitter 在本地进行分析,不可上诉的LLM. 只有文档文件 (.adoc, .md) 需要进行一次LLM调用以进行语义提取。 因此`--update`在Kotlin代码上编译几乎是即时的。

步骤 2:Gradle插件将Knowledge Graph转换为PlantUML

流水线架构

插件`com.cheroliv.plantuml`包含一个任务`generateKnowledgeGraphDiagram`谁转换`graph.json`以 PlantUML 图表的方式完全决定论的 :

@startuml
skinparam backgroundColor #FEFEFE

participant "Gradle" as G
participant "GenerateKnowledgeGraphDiagramTask" as Task
participant "KnowledgeGraphParser" as Parser
participant "KnowledgeGraphRenderer" as Renderer
participant "PlantumlService" as PS

collections "graphify-out/graph.json" as JSON

G -> Task : execute
Task -> JSON : 阅读
Task -> Parser : parse(graph.json)
Parser --> Task : KnowledgeGraph\n(节点 + 边 + 社区)
Task -> Renderer : render(graph, filters)
Renderer --> Task : code PlantUML\n(确定的)
Task -> PS : validateSyntax(plantumlCode)
alt syntaxe valide
    Task -> PS : generateImage → .png
else syntaxe invalide
    Task -> Task : 保存 .puml 并带有警告
end

@enduml

内部组件

组件 角色

KnowledgeGraphParser

解析`graph.json`— 支持 3 种格式: 原生 graphify (nodes+links), 遗产 (communities), 平坦。 解析数字 ID 为标签。

KnowledgeGraphRenderer

确定性地转换一个`KnowledgeGraph`在PlantUML代码中。按类型分组,社区以包形式,自动图例。

GenerateKnowledgeGraphDiagramTask

负责编排:parse → render → validate → PNG 的 Gradle 任务。可通过 Gradle 属性进行配置。

kgmodels.kt

数据模型 :`KnowledgeGraph`, KnowledgeGraphNode, KnowledgeGraphEdge, KnowledgeGraphCommunity, EdgeType。

PlantumlService

语法验证 + PNG 渲染(由插件的所有任务重复使用)。

渲染规则

渲染器应用确定的视觉惯例:

边缘类型 PlantUML 表示法 意义

提取的

-→(实线, 黑色)

从源代码中提取的关系(确定性)

推断

..>(虚线)

由LLM推断的关系(置信度得分)

含糊的

--x(红色虚线)

模糊的关系(待验证)

社区以带有自动调色板的 PlantUML 包的形式呈现。

步骤 3:日常使用

完整图表

# Générer le diagramme du Knowledge Graph complet
./gradlew generateKnowledgeGraphDiagram

输出:diagrams/knowledge-graph/knowledge-graph-full.puml + .png

按社区筛选

# Une seule communauté
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.community=community_0

# Limiter le nombre de noeuds (lisibilité)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.community=community_0 \
  -Pplantuml.kg.maxNodes=15

按边类型过滤

# Uniquement les relations certaines (EXTRACTED)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.edgeTypes=EXTRACTED

# Relations certaines + inférées
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.edgeTypes=EXTRACTED,INFERRED

按节点类型和置信度过滤

# Uniquement les classes de code
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.nodeTypes=code

# Seuil de confiance minimum (pour les INFERRED)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.minConfidence=0.7

自定义输出目录

./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.outputDir=docs/architecture

属性完整参考

属性 默认 描述

plantuml.kg.community

(所有)

按名称过滤社区 (子字符串匹配)

plantuml.kg.edgeTypes

(全部)

以逗号分隔的边类型:EXTRACTED, INFERRED, AMBIGUOUS

plantuml.kg.minConfidence

0.0

边的最小置信度阈值

plantuml.kg.maxNodes

(无限)

要显示的最大节点数

plantuml.kg.nodeTypes

(所有)

以逗号分隔的节点类型(例如`class`, code)

plantuml.kg.outputDir

diagrams/knowledge-graph

输出目录用于文件`.puml` et .png

Gradle 工作流中的完整管道

工作流类型

@startuml
skinparam backgroundColor #FEFEFE
skinparam ActivityBackgroundColor #E8F4FD
skinparam ActivityDiamondBackgroundColor #FFF3CD
skinparam ActivityBorderColor #2C3E50

start

partition "EXTRACTION" {
    :graphify . --no-viz;
    note right: 分析源代码\ntree-sitter (本地, 无 LLM)

    :graphify-out/graph.json;
    note right: 节点 + 边\n+ 社区
}

partition "生成的RATION" {
    :./gradlew generateKnowledgeGraphDiagram;
    note right: 确定性流水线\n解析 → 渲染 → 验证 → PNG

    if (Filtres actifs ?) then (Oui)
        :应用过滤器\n(community, edgeTypes,\nmaxNodes, nodeTypes);
    else (Non)
        :完整的图表;
    endif

    :图表/knowledge-graph/\nknowledge-graph-full.puml\nknowledge-graph-full.png;
}

partition "INTÉGRATION" {
    :git add diagrams/knowledge-graph/;
    :提交;
    note right: 版本化图表\n始终与代码保持同步
}

stop

@enduml

集成到开发周期

pipeline 自然地融入了开发的关键阶段 :

@startuml
skinparam backgroundColor #FEFEFE

state "开发" as dev
state "提取\ngraphify . --no-viz" as extract
state "生成\n./gradlew generateKnowledgeGraphDiagram" as generate
state "提交\n版本图表" as commit

[*] --> dev
dev --> extract : 已修改的代码
extract --> generate : graph.json 更新
generate --> commit : .puml + .png 已生成
commit --> dev : 存储库中的图表

note right of extract
在 Kotlin 代码上几乎即时
(tree-sitter, 没有 LLM)
end note

note right of generate
确定的
没有 LLM
可重复的结果
end note

@enduml

增量更新

当代码发生变化时,我们不会从零开始重建整个图:

# Mise à jour incrémentale (fichiers modifiés uniquement)
graphify . --update

# Puis régénérer les diagrammes
./gradlew generateKnowledgeGraphDiagram

--update`仅重新提取已修改的文件(由 SHA256 检测到的`graphify-out/cache/). 对于 Kotlin 代码,几乎是即时的,因为 tree-sitter 在本地工作,没有 LLM 调用。

狗粮:插件自行记录

PlantUML 插件可以将提示转换为图表。它还可以将其 propre 代码库的 Knowledge Graph 转换为文档图表。这是 dogfooding:插件使用其自身的服务。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "正常流水线\n(用户 → 图表)" as normal {
    [Fichier .prompt] as prompt
    [LlmService\n+ ApiKeyPool] as llm1
    [ProcessPlantumlPromptsTask] as task1
    [Diagramme PNG] as out1

    prompt --> task1
    task1 --> llm1
    llm1 --> out1
}

package "流水线知识图谱\n(确定性,无 LLM)" as kg {
    [graphify-out/graph.json] as kgjson
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantumlService] as ps
    [Diagramme PNG\n(documentation du plugin)] as out2

    kgjson --> parser
    parser --> renderer
    renderer --> ps
    ps --> out2
}

package "流水线自用测试\n(LLM → 插件文档)" as dogfood {
    [GraphifyPromptAdapter] as gpa
    [Fichiers .prompt\nauto-générés] as auto_prompt
    [LlmService\n+ ApiKeyPool] as llm2
    [ProcessPlantumlPromptsTask] as task2
    [Diagramme PNG\n(documentation LLM)] as out3

    kgjson --> gpa
    gpa --> auto_prompt
    auto_prompt --> task2
    task2 --> llm2
    llm2 --> out3
}

note "相同的 LlmService,相同的 ApiKeyPool,\n相同的 PlantumlService\n—— 零重复" as N

@enduml

关联的 Gradle 任务:

任务 LLM ? 描述

generateKnowledgeGraphDiagram

不

转换`graph.json`在 PlantUML (确定性的)

generateDiagramDocs

是

生成一些`.prompt`从图中,通过 LLM 处理它们(dogfooding)

# Documentation déterministe (rapide, pas de LLM)
./gradlew generateKnowledgeGraphDiagram

# Documentation LLM (plus riche, consomme des tokens)
./gradlew generateDiagramDocs

为什么它是确定的(以及为什么这很重要)

流水线的关键点`generateKnowledgeGraphDiagram`:他不调用任何LLM. 转换`graph.json`→ PlantUML 是一个纯函数。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle "管道 DÉTERMINISTE\n(generateKnowledgeGraphDiagram)" as det {
    [graph.json] as json
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantUML code] as puml

    json --> 解析r : 解析
    parser --> renderer : KnowledgeGraph
    renderer --> puml : 渲染(纯函数)
}

rectangle "管道 LLM\n(processPlantumlPrompts)" as llm {
    [.prompt] as prompt
    [LlmService] as llmSvc
    [ChatModel] as model
    [PlantUML code] as puml2

    prompt --> llmSvc
    llmSvc --> model : API 调用
    model --> puml2 : 非确定性响应
}

note bottom of det
相同输入 → 相同输出
无网络延迟
无 Token 成本
可在 CI 中重现
end note

note bottom of llm
相同输入 → 可变输出
网络延迟 (1-5s)
令牌成本
需要一个密钥 API
end note

@enduml

具体的好处:

优势 影响

可重复性

即使`graph.json`→ 同一张图。的确。每次。

零成本

没有 LLM 调用 = 没有 token = 没有 API 账单。

零延迟

Parse + render 需要约 100 毫秒,而不是 1-5 秒。

兼容持续集成

不需要 API 密钥。不会因 LLM 响应可变而出现不稳定的测试。

可版本化

Le .puml`生成的文本。我们可以它`diff, PR中的审阅者,在 Git 中进行版本控制。

管道本身的图表

为了闭环,以下是插件生成的管道图:

@startuml
skinparam backgroundColor #FEFEFE

participant "开发者" as Dev
participant "Gradle" as G
participant "GenerateKnowledgeGraphDiagramTask" as Task
participant "KnowledgeGraphParser" as Parser
participant "KnowledgeGraphRenderer" as Renderer
participant "PlantumlService" as PS
collections "graphify-out/graph.json" as JSON
collections "diagrams/knowledge-graph/" as Out

Dev -> G : ./gradlew generateKnowledgeGraphDiagram
G -> Task : 执行
Task -> JSON : 读
Task -> Parser : parse(graph.json)
Parser --> Task : KnowledgeGraph

alt filtres actifs
    Task -> Task : 应用过滤器\n(community, edgeTypes, maxNodes…)
end

Task -> Renderer : render(graph, filters)
Renderer --> Task : 代码 PlantUML

Task -> PS : validateSyntax()
alt valide
    Task -> PS : generateImage()
    PS --> Out : .puml + .png
else invalide
    Task -> Out : .puml (带警告)
end

@enduml

项目治理中的整合

在我们的项目中,此管道集成到AI代理的EAGER/LAZY上下文管理策略中。知识图谱替换了手动的架构文档,采用了一个结构化、可查询且自动更新的图。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "EAGER\n(始终加载)" as eager {
    [PROMPT_REPRISE.adoc\n(contexte session)] as pr
    [INDEX.adoc\n(vue d'ensemble)] as idx
    [GRAPH_REPORT.adoc\n(~50 lignes)] as gr
}

package "LAZY — 策略\n(按需)" as lazy_strat {
    [Méthodologies] as meth
    [Archives sessions] as sessions
}

package "LAZY — Graphify\n(目标查询)" as lazy_graph {
    [graph.json] as gj
    [Queries\n(query/path/explain)] as queries
}

package "Pipeline PlantUML\n(自动生成)" as puml {
    [generateKnowledgeGraphDiagram] as kgTask
    [generateDiagramDocs] as ddTask
    [Diagrammes PNG] as diagrams
}

Agent --> eager : 在会话开始时阅读
Agent ..> lazy_strat : 如果检测到类型则加载
Agent ..> lazy_graph : 如果需要结构性查询
kgTask --> diagrams : 确定的
ddTask --> diagrams : 通过 LLM

note right of gr
知识图谱摘要
God节点 + 社区
替换 ECOSYSTEM_OVERVIEW
(225 行 → 50 行)
end note

@enduml

两种系统的结合是互补的:

  • 该策略管理何时和如何— 治理, 工作流, 归档

  • Graphify 处理什么和哪里— 代码结构,关系,有针对性的查询

_ 会话策略管理什么时候 et le 如何(治理, 工作流, 阈值),Graphify 管理什么 et le 哪里(代码结构, 关系, 有针对性的查询). PlantUML 管道处理用什么(确定性图表, 已版本化, 始终保持最新). _

准备:5分钟清单

# 步骤 命令

1

安装 Graphify

uv tool install graphifyy

2

配置排除项

创建`.graphifyignore`

3

提取知识图谱

graphify . --no-viz

4

生成图表

./gradlew generateKnowledgeGraphDiagram

5

提交结果

git add diagrams/knowledge-graph/

# Script complet en 5 commandes
uv tool install graphifyy
cat > .graphifyignore << 'EOF'
*-context.yml
*.env
build/
.gradle/
EOF
graphify . --no-viz
./gradlew generateKnowledgeGraphDiagram
git add graphify-out/GRAPH_REPORT.adoc graphify-out/graph.json diagrams/knowledge-graph/

陷阱与缓解措施

陷阱 描述 减缓

图形过于密集

一个大型项目会产生数百个不可读的节点

使用`-Pplantuml.kg.maxNodes=30`并按社区筛选

排除范围过大

文件过多在`.graphifyignore`减少图的价值

首先仅排除 credentials 和 build

箭头方向

推断的边可能具有不明确的方向

按…​过滤`-Pplantuml.kg.edgeTypes=EXTRACTED`仅限于确定的关系

过时的图形

代码发生了变化,但图未被重建

使用`graphify . --update`经常或 git 钩子`graphify hook install`

成本已更新

增量更新几乎免费 ( tree-sitter local )

只有文档 (.adoc) 消耗 LLM tokens

我们最终得到的

@startuml
skinparam backgroundColor #FEFEFE

rectangle "前" as avant {
    card "手绘图表\n总是过时\n没人更新它们" as av1 #FDEDEC
}

rectangle "之后" as apres {
    card "自动生成的图表\n始终与代码保持同步\n在 Git 中进行版本控制\n确定且可复现" as ap1 #E8F8E8
}

avant --> apres : graphify . --no-viz\n+ ./gradlew generateKnowledgeGraphDiagram

@enduml

具体的好处:

利润 细节

文档始终保持最新

图表反映了当前代码,而不是手动快照

零维护工作量

图表在每次构建时会重新生成。

技术债务减少

不再需要手动维护图表

面向新人的视觉背景

新开发者通过观察图表来理解架构

微调潜力

(子图 → 图)对是 AI 训练的示例

自动验证

`PlantumlService.validateSyntax()`检查每个生成的图表

快速入职

5 个图表 = 架构的完整视图

</think> 拥有_为什么_的人能够承受所有的_怎么样_。 __

为什么:图表始终保持最新。 如何:在 Gradle 流水线中有两条命令。

链接

相关文章