Intégrer Graphify dans un workflow Gradle : du Knowledge Graph au diagramme PlantUML en une commande
Опубликовано 19 April 2026
- Проблема: диаграммы всегда отстают от кода
- Решение: детерминированный пайплайн Knowledge Graph → PlantUML
- Шаг 1: Установить Graphify и извлечь граф знаний
- Этап 2: Плагин Gradle преобразует Knowledge Graph в PlantUML
- Шаг 3: Ежедневное использование
- Полный pipeline в рабочем процессе Gradle
- Dogfooding: плагин документирует сам себя
- Почему это детерминировано (и почему это важно)
- Диаграммы самого конвейера
- Интеграция в управление проектом
- Настройка: 5-минутный чек-лист
- Ловушки и смягчения
- Что мы получаем в итоге
- Ссылки
Ваша кодовая база растёт. Зависимости между модулями увеличиваются. Архитектурная документация становится устаревшей до того, как она будет написана. А что если ваша сборка Gradle сможет автоматически генерировать актуальные диаграммы на основе реальной структуры кода? Это именно то, что делает пайплайн Graphify + PlantUML Gradle Plugin :`graphify . --no-viz`извлекает Knowledge Graph,`./gradlew generateKnowledgeGraphDiagram`преобразует его в диаграммы PlantUML. Ноль LLM, ноль руководств, 100% детерминированный.
Проблема: диаграммы всегда отстают от кода
Любой проект, превышающий несколько тысяч строк, сталкивается с этим синдромом:
-
Мы рисуем диаграмму архитектуры в начале проекта
-
Код развивается, зависимости изменяются
-
Диаграмма становится декоративной ложью
-
Никто не обновляет его, потому что это утомительно
-
Новички основываются на этом и допускают ошибки.
@startuml
skinparam backgroundColor #FEFEFE
skinparam ActivityBackgroundColor #FDEDEC
skinparam ActivityDiamondBackgroundColor #FFF3CD
start
:Diagramme d'architecture créé\n(manuellement, à la main);
:Le code évolue\n(nouvelles classes, nouvelles dépendances);
:Diagramme obsolète\n(ne reflète plus le code);
if (Qui met à jour ?) then (Personne)
:Documentation mensongère;
note right: Les nouveaux développeurs\nse basent dessus... et font des erreurs
else (Quelqu'un)
:Mise à jour manuelle\n(2-3 heures de travail);
note right: Déjà obsolète\nà la prochaine 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(Knowledge Graph)" as KGJSON component "PlantUML Gradle Plugin\n(generateKnowledgeGraphDiagram)" as Plugin component "KnowledgeGraphParser" as Parser component "KnowledgeGraphRenderer" as Renderer component "PlantumlService\n(validation + rendu PNG)" as PS collections "diagrams/knowledge-graph/\n(.puml + .png)" as Output Développeur --> Graphify : graphify . --no-viz Graphify --> KGJSON : extrait la structure\ndu code source Développeur --> Plugin : ./gradlew generateKnowledgeGraphDiagram Plugin --> Parser : parse(graph.json) Parser --> Plugin : KnowledgeGraph\n(noeuds + arêtes + communautés) Plugin --> Renderer : render(graph, filters) Renderer --> Plugin : code PlantUML\ndéterministe Plugin --> PS : validateSyntax + generateImage PS --> Output : .puml + .png note bottom of Plugin Pipeline DÉTERMINISTE Aucun appel LLM Résultat reproductible 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/
Извлечь Knowledge Graph
graphify . --no-viz
Флаг`--no-viz`пропускает генерацию HTML (бесполезно в конвейере Gradle). Результат — это файл`graphify-out/graph.json`contenant :
-
узлы: классы, функции, файлы — с их типом и сообществом
-
рёбраотношения между узлами (EXTRACTED из кода, INFERRED LLM)
-
сообщества: автоматические группировки связанных узлов
{
"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}
]
}
|
Исходный код ( |
Этап 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 : read
Task -> Parser : parse(graph.json)
Parser --> Task : KnowledgeGraph\n(noeuds + arêtes + communautés)
Task -> Renderer : render(graph, filters)
Renderer --> Task : code PlantUML\n(déterministe)
Task -> PS : validateSyntax(plantumlCode)
alt syntaxe valide
Task -> PS : generateImage → .png
else syntaxe invalide
Task -> Task : save .puml avec warning
end
@enduml
Внутренние компоненты
| Компонент | Роль |
|---|---|
|
парсить`graph.json`— поддерживает 3 формата : graphify нативный ( |
|
Преобразует детерминированно один`KnowledgeGraph`в коде PlantUML. Группы по типу, сообщества в пакетах, автоматическая легенда. |
|
Задача Gradle, которая оркестрирует: parse → render → validate → PNG. Настраивается через свойства Gradle. |
|
Модели данных :`KnowledgeGraph`, |
|
Проверка синтаксиса + рендеринг PNG (повторно используется всеми задачами плагина). |
Правила рендеринга
Рендерер применяет детерминированные визуальные конвенции:
| Тип ребра | Нотация PlantUML | Значение |
|---|---|---|
извлечён |
|
Извлечённая связь из исходного кода (уверенность) |
INFERRED |
|
Отношение, выведенное LLM (оценка уверенности) |
неоднозначный |
|
Неоднозначная связь (проверка) |
Сообщества отображаются как пакеты PlantUML с автоматической палитрой цветов.
Шаг 3: Ежедневное использование
Полная диаграмма
# Générer le diagramme du Knowledge Graph complet
./gradlew generateKnowledgeGraphDiagram
Sortie : 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
Полный справочник свойств
| Собственность | дефект | Описание |
|---|---|---|
|
(все) |
Фильтровать сообщества по имени (совпадение подстроки) |
|
(все) |
Типы рёбер, разделённые запятыми:`EXTRACTED`, |
|
|
Минимальный порог уверенности для рёбер |
|
(неограниченный) |
Максимальное количество узлов для отображения |
|
(все) |
Типы узлов, разделенные запятыми (пример. |
|
|
Каталог вывода для файлов`.puml` et |
Полный pipeline в рабочем процессе Gradle
Тип рабочего процесса
@startuml
skinparam backgroundColor #FEFEFE
skinparam ActivityBackgroundColor #E8F4FD
skinparam ActivityDiamondBackgroundColor #FFF3CD
skinparam ActivityBorderColor #2C3E50
start
partition "EXTRACTION" {
:graphify . --no-viz;
note right: Analyse le code source\ntree-sitter (local, pas de LLM)
:graphify-out/graph.json;
note right: Noeuds + arêtes\n+ communautés
}
partition "GÉNÉRATION" {
:./gradlew generateKnowledgeGraphDiagram;
note right: Pipeline déterministe\nparse → render → validate → PNG
if (Filtres actifs ?) then (Oui)
:Appliquer filtres\n(community, edgeTypes,\nmaxNodes, nodeTypes);
else (Non)
:Diagramme complet;
endif
:diagrams/knowledge-graph/\nknowledge-graph-full.puml\nknowledge-graph-full.png;
}
partition "INTÉGRATION" {
:git add diagrams/knowledge-graph/;
:git commit;
note right: Diagrammes versionnés\ntoujours à jour avec le code
}
stop
@enduml
Интеграция в цикл разработки
Конвейер естественно вписывается в ключевые этапы разработки :
@startuml skinparam backgroundColor #FEFEFE state "Développement" as dev state "Extraction\ngraphify . --no-viz" as extract state "Génération\n./gradlew generateKnowledgeGraphDiagram" as generate state "Commit\ndiagrammes versionnés" as commit [*] --> dev dev --> extract : Code modifié extract --> generate : graph.json à jour generate --> commit : .puml + .png générés commit --> dev : Diagrammes dans le repo note right of extract Quasi instantané sur du code Kotlin (tree-sitter, pas de LLM) end note note right of generate Déterministe Pas de LLM Résultat reproductible end note @enduml
Инкрементальное обновление
Когда код меняется, мы не перестраиваем весь граф с нуля:
# Mise à jour incrémentale (fichiers modifiés uniquement)
graphify . --update
# Puis régénérer les diagrammes
./gradlew generateKnowledgeGraphDiagram
|
|
Dogfooding: плагин документирует сам себя
Плагин PlantUML существует для преобразования запросов в диаграммы. Он также может преобразовывать граф знаний своей собственной propre кодовой базы в диаграммы документации. Это 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 "Пайплайн Knowledge Graph\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 "Пайплайн Dogfooding\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 ? | Описание |
|---|---|---|
|
Нет |
Преобразуй`graph.json`в PlantUML (детерминированный) |
|
Да |
Генерируй некоторые`.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 "ДЕТЕРМИНИРОВАННЫЙ конвейер\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 : render (fonction pure)
}
rectangle "LLM-конвейер\n(processPlantumlPrompts)" as llm {
[.prompt] as prompt
[LlmService] as llmSvc
[ChatModel] as model
[PlantUML code] as puml2
prompt --> llmSvc
llmSvc --> model : API call
model --> puml2 : réponse non-déterministe
}
note bottom of det
Тот же вход → тот же выход
Нет сетевых задержек
Нет затрат на токены
Воспроизводимо в CI
end note
note bottom of llm
Один и тот же вход → переменный выход
Сетевая задержка (1-5с)
Стоимость в токенах
Требуется API-ключ
end note
@enduml
Конкретные преимущества:
| Преимущество | воздействие |
|---|---|
Воспроизводимость |
Тоже`graph.json`→ та же диаграмма. Точно. Всегда. |
Нулевая стоимость |
Нет вызова LLM = нет токенов = нет счёта за API |
Нулевая задержка |
Parse + render занимает ~100 мс, а не 1-5 секунд. |
Совместимый CI |
Не нужен API-ключ. Нет нестабильного теста из-за переменного ответа LLM. |
версируемый |
Le |
Диаграммы самого конвейера
Чтобы замкнуть круг, вот схема конвейера, как она будет сгенерирована плагином:
@startuml
skinparam backgroundColor #FEFEFE
participant "Développeur" 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 : execute
Task -> JSON : read
Task -> Parser : parse(graph.json)
Parser --> Task : KnowledgeGraph
alt filtres actifs
Task -> Task : appliquer filtres\n(community, edgeTypes, maxNodes…)
end
Task -> Renderer : render(graph, filters)
Renderer --> Task : code PlantUML
Task -> PS : validateSyntax()
alt valide
Task -> PS : generateImage()
PS --> Out : .puml + .png
else invalide
Task -> Out : .puml (avec warning)
end
@enduml
Интеграция в управление проектом
В нашем проекте этот конвейер интегрируется в стратегию управления контекстом EAGER/LAZY для ИИ-агента. Knowledge Graph заменяет ручную архитектурную документацию на структурированный, запрашиваемый и автоматически обновляемый граф.
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
package "EAGER\n(toujours chargé)" 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 — Stratégie\n(sur demande)" as lazy_strat {
[Méthodologies] as meth
[Archives sessions] as sessions
}
package "LAZY — Graphify\n(requêtes ciblées)" as lazy_graph {
[graph.json] as gj
[Queries\n(query/path/explain)] as queries
}
package "Pipeline PlantUML\n(auto-généré)" as puml {
[generateKnowledgeGraphDiagram] as kgTask
[generateDiagramDocs] as ddTask
[Diagrammes PNG] as diagrams
}
Agent --> eager : Lit en début de session
Agent ..> lazy_strat : Charge si type détecté
Agent ..> lazy_graph : Query si besoin structurel
kgTask --> diagrams : Déterministe
ddTask --> diagrams : Via LLM
note right of gr
Condensé du Knowledge Graph
God nodes + communautés
Remplace ECOSYSTEM_OVERVIEW
(225 lignes → 50 lignes)
end note
@enduml
Союз двух систем дополняет друг друга:
-
Стратегия управляет КОГДА и КАК— управление, рабочий процесс, архивирование
-
Graphify управляет ЧТО и ГДЕ— структура кода, отношения, целевые запросы
_ Стратегия сеанса управляетКОГДА et le как(управление, workflow, пороги), Graphify управляет егоЧТО et le ГДЕ(структура кода, связи, целевые запросы). Конвейер PlantUML обрабатываетС чем(детерминированные диаграммы, с версиями, всегда актуальны). _
Настройка: 5-минутный чек-лист
| # | этап | Заказ |
|---|---|---|
1 |
Установить Graphify |
|
2 |
Настроить исключения |
Создать`.graphifyignore` |
3 |
Извлечь граф знаний |
|
4 |
Сгенерировать диаграммы |
|
5 |
Зафиксировать результаты |
|
# 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`et фильтровать по сообществу |
Слишком широкие исключения |
Слишком много файлов в`.graphifyignore`уменьшает значение графика |
Начать с исключения только credentials и build |
Направление стрелок |
Рёбра INFERRED могут иметь неоднозначное направление |
Фильтр по`-Pplantuml.kg.edgeTypes=EXTRACTED`только для определённых отношений |
Устаревший граф |
Код меняется, но граф не восстанавливается |
Использовать`graphify . --update`регулярно или git-хук`graphify hook install` |
Обновлённая стоимость |
Инкрементальные обновления почти бесплатны (tree-sitter local) |
Только документы ( |
Что мы получаем в итоге
@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
Конкретные выгоды:
| прибыль | деталь |
|---|---|
Документация всегда актуальна |
Диаграммы отражают текущий код, а не ручной снимок |
Нулевые усилия по обслуживанию |
Диаграммы перестраиваются при каждой сборке |
Снижение технического долга |
Больше не нужно поддерживать диаграммы вручную |
Визуальный контекст для новых |
Новый разработчик понимает архитектуру, глядя на диаграммы |
потенциал тонкой настройки |
Пары (подграф → диаграмма) являются примерами обучения ИИ |
Автоматическая проверка |
`PlantumlService.validateSyntax()`проверяет каждую сгенерированную диаграмму |
Быстрый онбординг |
5 диаграмм = полный вид архитектуры |
_ Тот, у кого есть _почему, может выдержать все как. __
Почему : всегда актуальные диаграммы. Как : две команды в пайплайне Gradle.
Ссылки
-
Супер советы команды fg— предыдущая статья о терминальном рабочем процессе