Содержание
время чтения : 12 minutes

Ваша кодовая база растёт. Зависимости между модулями увеличиваются. Архитектурная документация становится устаревшей до того, как она будет написана. А что если ваша сборка Gradle сможет автоматически генерировать актуальные диаграммы на основе реальной структуры кода? Это именно то, что делает пайплайн Graphify + PlantUML Gradle Plugin :`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

: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)

  • сообщества: автоматические группировки связанных узлов

Пример структуры`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 : 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

Внутренние компоненты

Компонент Роль

KnowledgeGraphParser

парсить`graph.json`— поддерживает 3 формата : graphify нативный (nodes+links), legacy (communities), плоский. Преобразует числовые ID в метки.

KnowledgeGraphRenderer

Преобразует детерминированно один`KnowledgeGraph`в коде PlantUML. Группы по типу, сообщества в пакетах, автоматическая легенда.

GenerateKnowledgeGraphDiagramTask

Задача Gradle, которая оркестрирует: parse → render → validate → PNG. Настраивается через свойства Gradle.

kgmodels.kt

Модели данных :`KnowledgeGraph`, KnowledgeGraphNode, KnowledgeGraphEdge, KnowledgeGraphCommunity, EdgeType.

PlantumlService

Проверка синтаксиса + рендеринг PNG (повторно используется всеми задачами плагина).

Правила рендеринга

Рендерер применяет детерминированные визуальные конвенции:

Тип ребра Нотация PlantUML Значение

извлечён

-→(сплошная линия, чёрный)

Извлечённая связь из исходного кода (уверенность)

INFERRED

..>(пунктирная линия)

Отношение, выведенное LLM (оценка уверенности)

неоднозначный

--x(красная пунктирная линия)

Неоднозначная связь (проверка)

Сообщества отображаются как пакеты 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

Полный справочник свойств

Собственность дефект Описание

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

Полный 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

--update`повторно извлекает только измененные файлы (обнаруженные по SHA256 в`graphify-out/cache/). На коде Kotlin, это почти мгновенно, потому что tree-sitter работает локально без вызова LLM.

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 ? Описание

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 "ДЕТЕРМИНИРОВАННЫЙ конвейер\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 .puml`Сгенерировано это текст. Мы можем его`diff, рецензент в PR, версионировать в Git.

Диаграммы самого конвейера

Чтобы замкнуть круг, вот схема конвейера, как она будет сгенерирована плагином:

@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

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`et фильтровать по сообществу

Слишком широкие исключения

Слишком много файлов в`.graphifyignore`уменьшает значение графика

Начать с исключения только credentials и build

Направление стрелок

Рёбра INFERRED могут иметь неоднозначное направление

Фильтр по`-Pplantuml.kg.edgeTypes=EXTRACTED`только для определённых отношений

Устаревший граф

Код меняется, но граф не восстанавливается

Использовать`graphify . --update`регулярно или git-хук`graphify hook install`

Обновлённая стоимость

Инкрементальные обновления почти бесплатны (tree-sitter local)

Только документы (.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

Конкретные выгоды:

прибыль деталь

Документация всегда актуальна

Диаграммы отражают текущий код, а не ручной снимок

Нулевые усилия по обслуживанию

Диаграммы перестраиваются при каждой сборке

Снижение технического долга

Больше не нужно поддерживать диаграммы вручную

Визуальный контекст для новых

Новый разработчик понимает архитектуру, глядя на диаграммы

потенциал тонкой настройки

Пары (подграф → диаграмма) являются примерами обучения ИИ

Автоматическая проверка

`PlantumlService.validateSyntax()`проверяет каждую сгенерированную диаграмму

Быстрый онбординг

5 диаграмм = полный вид архитектуры

_ Тот, у кого есть _почему, может выдержать все как. __

Почему : всегда актуальные диаграммы. Как : две команды в пайплайне Gradle.

Ссылки

Похожие статьи