阅读时间 : 12 minutes

您的代码库在增长。模块之间的依赖关系在增加。架构文档在还未编写之前就已经过时了。如果您的 Gradle 构建可以 自动 从代码的实际结构生成最新的图表,那会怎样?这就是 Graphify + PlantUML Gradle 插件管道所做的: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 并提取知识图谱

安装

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 插件将知识图转换为 PlantUML

流水线架构

插件`com.cheroliv.plantuml`集成一个任务`generateKnowledgeGraphDiagram`谁转换`graph.json`在PlantUML图表中以某种方式完全决定论的</think> (No output, as the text to translate is empty)

@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 : 代码 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), flat. 将数字ID解析为标签。

KnowledgeGraphRenderer

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

GenerateKnowledgeGraphDiagramTask

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

kgmodels.kt

数据模型:KnowledgeGraph, KnowledgeGraphNode, KnowledgeGraphEdge, KnowledgeGraphCommunity, EdgeType.

PlantumlService

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

渲染规则

渲染器应用确定性的视觉约定 :

边缘类型 PlantUML 表示法 意义

EXTRACTED

-→(实线,黑色)

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

推断的

..>(虚线)

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" {
    :图形化 . --no-viz;
    note right: 分析源代码\n tree-sitter (本地,没有 LLM)

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

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

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

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

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

stop

@enduml

集成到开发周期中

该管道自然融入开发的关键步骤:

@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 插件用于将提示转换为图表。它也可以将其 自己的 codebase 的 Knowledge Graph 转换为文档图表。这就是 吃自己的狗粮 :该插件消费其自身的服务。

@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 --> parser : parse
    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-5秒)
Tokens 成本
需要密钥 API
end note

@enduml

具体的好处:

优势 影响

可重复性

甚至`graph.json`→ 同样的图表。正是如此。每次。

零成本

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

零延迟

解析 + 渲染 约需 100ms,而非 1-5 秒。

兼容 CI

不需要 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分钟检查表

(Empty) 步骤 订单

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

箭头方向

INFERRED 边可能具有不明确的方向

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

过时的图

代码变了,但图没有被重新构建。

使用`graphify . --update`定期或git钩子`graphify hook install`

已更新成本

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

只有文档 (.adoc) 消耗LLM的标记

最终得到的

@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 个图示 = 架构的完整视图

_ 谁有 _为什么 可以承受所有的 怎么样。 __

为什么:图表始终保持最新。如何:在 Gradle 管道中包含两个命令。

链接

相关文章