Продвинутый

Graphify: код, документация и PDF в граф знаний

Алексей Кузнецов
Алексей Кузнецов
Системный администратор6 ноября 2026 г.13 мин чтения

Локальный парсинг кода, SQL-схем и PDF без векторной базы. Graphify строит граф знаний для Claude Code, Cursor, Codex и Gemini CLI.

Graphify: код, документация и PDF в граф знаний

Локальный парсинг кода, SQL-схем и PDF без векторной базы. Graphify строит граф знаний для Claude Code, Cursor, Codex и Gemini CLI.

Что такое Graphify и зачем он нужен

Что такое Graphify и зачем он нужен

Graphify — локальный инструмент для построения графа знаний из исходного кода, SQL-схем и PDF-документов. Он не использует векторную базу, а работает с абстрактным синтаксическим деревом (AST) и прямыми связями между сущностями. Результат можно отдавать в Claude Code, Cursor, Codex или Gemini CLI, чтобы ИИ-агент видел не только отдельные файлы, но и зависимости между ними.

Когда я в первый раз подключил Claude Code к большому репозиторию, модель «не видела» связи между файлами. Она знала, что функция существует, но не знала, какая таблица в PostgreSQL за ней стоит, или какой раздел PDF-регламента описывает её поведение. Graphify решает эту задачу: строит граф, где узлы — функции, классы, таблицы и разделы документов, а рёбра — вызовы, импорты, внешние ключи и ссылки.

Почему поиск по коду перестал справляться

Во-первых, обычный текстовый поиск (grep, ripgrep) находит совпадения по строке, но не понимает семантику. Если вы ищете calculate_tax, вы найдёте определение и вызовы, но не узнаете, какие поля из SQL-схемы участвуют в расчёте, или какой раздел PDF-инструкции регламентирует ставку НДС.

Во-вторых, векторные базы пытаются решить проблему семантическим поиском, но добавляют сложность: нужна модель эмбеддингов, индексация, переобучение при изменении кода. В больших монорепо это превращается в отдельный инфраструктурный проект с собственными проблемами актуальности данных.

Пример из практики. В одном проекте на Python с десятком микросервисов разработчики тратили по 15–20 минут на поиск того, кто вызывает устаревший эндпоинт. ripgrep находил все вхождения, но не различал реальный вызов и упоминание в комментарии. Векторный поиск выдавал «похожие» функции, но не показывал цепочку зависимостей до базы данных.

Graphify не заменяет ripgrep, он добавляет слой связей поверх кода. Вы получаете не просто список файлов, а граф: функция A вызывает функцию B, которая читает таблицу C, описанную в разделе D PDF-документа.

Что получается на выходе

На выходе Graphify формирует граф знаний в формате, понятном ИИ-агентам. Узлы — это сущности кода и документов, рёбра — их отношения. Можно экспортировать в JSON, GraphML или подключить напрямую к Claude Code через CLAUDE.md.

Пример конфигурации Graphify:

yaml
graphify:
  version: "1"
  sources:
    - path: ./src
      parser: python-ast
      include:
        - "*.py"
    - path: ./sql
      parser: sql-schema
      include:
        - "*.sql"
    - path: ./docs
      parser: pdf
      include:
        - "*.pdf"
  output:
    format: json
    path: ./knowledge-graph.json
    ai_integration:
      - claude-code
      - cursor

Запуск выглядит предсказуемо:

bash
graphify build --config graphify.yaml --output ./knowledge-graph.json

После этого в CLAUDE.md для Claude Code можно добавить ссылку на граф, и модель будет учитывать связи между файлами при генерации кода. Например, если вы просите добавить новое поле в таблицу, Claude Code увидит все функции, которые с этой таблицей работают, и предложит обновить их сразу, а не только одну.

Если вы уже работаете с ИИ-агентами, стоит посмотреть, как настраивать CLAUDE.md для Claude Code по Карпати и какие навыки для агентов можно подключить поверх графа Graphify.

Как Graphify строит граф знаний

Детерминистичный парсинг AST без векторной базы

Graphify не использует векторную базу и не считает эмбеддинги. Вместо этого он парсит исходный код, SQL-схемы и PDF через синтаксическое дерево (AST) и записывает связи напрямую в граф. Это даёт предсказуемость: если ты запустишь парсинг дважды на одних и тех же файлах, получишь идентичный результат. Векторные базы такого не гарантируют — достаточно чуть изменить формулировку в комментарии, и вектор «уплывёт» в другое место пространства.

Во-первых, Graphify берёт файл, определяет его тип по расширению и пропускает через соответствующий парсер. Для Python это ast модуль, для JavaScript — @babel/parser, для SQL — отдельный грамматический парсер, для PDF — извлечение текста и поиск ссылок между документами.

Вот как выглядит запуск парсинга для репозитория с кодом:

bash
graphify parse --path ./my-project \
  --include '*.py' \
  --include '*.js' \
  --include '*.sql' \
  --output knowledge-graph.json

Флаг --include задаёт маски файлов, которые нужно обработать. Graphify рекурсивно обходит директорию, пропускает node_modules, .git и другие служебные каталоги. Если нужно добавить свои исключения, правьте конфиг:

yaml
# graphify.yaml
parsers:
  python:
    enabled: true
    extract_docstrings: true
    extract_type_hints: true
  javascript:
    enabled: true
    jsx: true
  sql:
    enabled: true
    dialect: postgresql
  pdf:
    enabled: true
    extract_toc: true
    follow_links: false

exclusions:
  - '**/node_modules/**'
  - '**/.git/**'
  - '**/venv/**'
  - '**/__pycache__/**'

С практической точки зрения, детерминистичный парсинг означает, что ты можешь положить результат в Git и отслеживать изменения графа коммитом за коммитом. Если разработчик переименовал функцию, в графе изменится один узел и несколько рёбер — а не половина векторного индекса.

Если мы посмотрим на внутреннее устройство, каждый узел графа получает устойчивый идентификатор на основе хеша содержимого и пути к файлу. Это позволяет Graphify понимать, что src/utils/helpers.py и src/utils/helpers.py после рефакторинга — это всё ещё тот же файл, даже если внутри появились новые классы.

Какие связи попадают в граф

Graphify извлекает три типа сущностей и четыре типа связей между ними. Сущности — это файлы, функции, классы, таблицы SQL, разделы PDF и отдельные абзацы. Связи описывают, как эти сущности зависят друг от друга.

Вот основные типы связей:

  • import — один модуль импортирует другой
  • call — функция вызывает другую функцию
  • defines — файл или класс определяет функцию, метод или константу
  • references — документ ссылается на другой документ или раздел

Пример вывода графа в формате JSON:

json
{
  "nodes": [
    {
      "id": "file:src/auth.py",
      "type": "file",
      "label": "src/auth.py",
      "language": "python"
    },
    {
      "id": "func:src/auth.py:hash_password",
      "type": "function",
      "label": "hash_password",
      "file": "src/auth.py",
      "line": 42
    },
    {
      "id": "func:src/auth.py:verify_token",
      "type": "function",
      "label": "verify_token",
      "file": "src/auth.py",
      "line": 78
    }
  ],
  "edges": [
    {
      "from": "file:src/auth.py",
      "to": "func:src/auth.py:hash_password",
      "type": "defines"
    },
    {
      "from": "func:src/auth.py:verify_token",
      "to": "func:src/auth.py:hash_password",
      "type": "call"
    }
  ]
}

Для SQL-схем Graphify строит связи между таблицами через внешние ключи. Если в схеме есть таблица orders с полем user_id, ссылающимся на users.id, в графе появится ребро references между этими таблицами. Это полезно, когда нужно понять, какие таблицы затронет изменение в одной из них.

Пример SQL-схемы и того, что Graphify из неё извлечёт:

sql
-- schema.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    total NUMERIC(10, 2) NOT NULL,
    status VARCHAR(50) DEFAULT 'pending'
);

В графе это отобразится как два узла типа table и одно ребро references от orders к users. Если потом добавить таблицу order_items с внешним ключом на orders, граф разрастётся соответствующим образом, и ты увидишь цепочку зависимостей.

Для PDF Graphify извлекает оглавление и гиперссылки внутри документа. Если в одном PDF есть ссылка на раздел другого PDF, эта связь тоже попадает в граф. Так получается междокументовый граф знаний, который можно скормить Claude Code, Cursor, Codex или Gemini CLI — они будут видеть не только отдельные файлы, но и связи между ними.

Если ты уже используешь CLAUDE.md для настройки Claude Code, Graphify может дополнить его автоматически сгенерированным описанием графа. Подробнее про настройку CLAUDE.md можно почитать в руководстве по Карпати.

Граф знаний без векторной базы — это как бумажная карта вместо GPS: она не подскажет оптимальный маршрут в реальном времени, но ты всегда будешь знать, где именно находится каждый объект и как он связан с остальными. Для анализа кода это часто важнее, чем семантический поиск.

Интеграция с Claude Code, Cursor, Codex и Gemini CLI

Интеграция с Claude Code, Cursor, Codex и Gemini CLI

Graphify парсит исходный код, SQL-схемы и PDF-файлы локально и строит из них ориентированный граф знаний. Векторная база не требуется — граф фиксирует прямые зависимости: вызов функции, импорт модуля, внешний ключ между таблицами. Для Claude Code, Cursor, Codex и Gemini CLI это означает, что ассистент получает не «похожий по смыслу» фрагмент, а реальную архитектуру проекта с путями к файлам и номерами строк.

Навык /graphify для ИИ-ассистентов

Навык /graphify задаёт ассистенту правило: когда пользователь спрашивает о структуре кода или связях между компонентами, использовать Graphify вместо обычного чтения файлов.

Во-первых, для Claude Code навык прописывается в CLAUDE.md. Если вы ещё не настраивали этот файл, посмотрите руководство Настройка CLAUDE.md для Claude Code по Карпати — там описано, как форматировать инструкции для ассистента. Ниже пример блока, который я добавляю в свои проекты:

markdown
## Навык /graphify

Когда пользователь спрашивает о связях в коде, структуре модулей или содержимом PDF-документации, вызови Graphify.

Graphify строит граф знаний из локального репозитория без векторной базы. Он парсит:
- исходный код на Python, Go, JavaScript, TypeScript, Rust, C++;
- SQL-схемы (CREATE TABLE, внешние ключи, индексы);
- PDF-документацию (спецификации, инструкции, отчёты).

Возвращай результат в виде списка узлов и рёбер с путями к файлам и номерами строк.

С практической точки зрения, такой навык работает предсказуемее семантического поиска. Векторная база может выдать фрагмент, который «похож» на запрос, но не покажет, что функция process_order в orders.py вызывает validate_payment в payments.py, а та в свою очередь читает таблицу payments из схемы billing. Graphify отобразит эту цепочку явно.

Для Cursor навык описывается в файле правил проекта. Пример конфигурации:

json
{
  "name": "graphify",
  "description": "Построение графа знаний из кода, SQL и PDF",
  "command": "graphify query --format json --context $CURSOR_FILE",
  "triggers": ["структура", "связь", "зависимость", "pdf", "схема"]
}

Codex и Gemini CLI не требуют отдельного файла навыка — достаточно добавить инструкцию в системный промпт:

Перед ответом на вопросы об архитектуре проекта используй инструмент graphify для анализа репозитория.

Если вы ищете готовые навыки для других ассистентов, репозиторий mattpocock/skills содержит несколько полезных примеров, которые можно адаптировать под Graphify.

Пример запроса и ответ

Пользователь спрашивает:

Как связаны заказы и платежи в нашем коде? Есть ли схема таблицы платежей?

Graphify возвращает граф в формате JSON:

json
{
  "nodes": [
    {
      "id": "file:src/orders.py",
      "label": "orders.py",
      "type": "file",
      "path": "src/orders.py"
    },
    {
      "id": "func:process_order",
      "label": "process_order",
      "type": "function",
      "file": "src/orders.py",
      "line": 42
    },
    {
      "id": "file:src/payments.py",
      "label": "payments.py",
      "type": "file",
      "path": "src/payments.py"
    },
    {
      "id": "func:validate_payment",
      "label": "validate_payment",
      "type": "function",
      "file": "src/payments.py",
      "line": 15
    },
    {
      "id": "table:billing.payments",
      "label": "billing.payments",
      "type": "sql_table",
      "schema": "billing"
    }
  ],
  "edges": [
    {
      "from": "file:src/orders.py",
      "to": "file:src/payments.py",
      "label": "импортирует"
    },
    {
      "from": "func:process_order",
      "to": "func:validate_payment",
      "label": "вызывает"
    },
    {
      "from": "func:validate_payment",
      "to": "table:billing.payments",
      "label": "читает"
    }
  ]
}

Что это значит на практике. Функция process_order из модуля заказов вызывает validate_payment из модуля платежей. Эта функция читает таблицу payments в схеме billing. Если вы меняете структуру таблицы, Graphify покажет, какие именно функции и файлы затронуты — без угадываний и без векторного поиска.

Команда для запуска анализа выглядит так:

bash
graphify parse ./src --include '*.py' --include '*.sql' --include '*.pdf' --output graph.json
graphify query "Как связаны заказы и платежи?" --graph graph.json

Если мы посмотрим на вывод выше, становится ясно: ассистенту не нужно читать весь репозиторий, чтобы ответить на вопрос. Достаточно обойти несколько рёбер в графе. Это и есть предсказуемость, которой не хватает обычному поиску по ключевым словам.

Ограничения, выводы и часто задаваемые вопросы

Ограничения, выводы и часто задаваемые вопросы

Когда подход перестаёт работать

Graphify строит граф знаний локально, без векторной базы. Это его преимущество и одновременно граница. Во‑первых, если вам нужен семантический поиск по смыслу, а не по структуре, граф не поможет. Пример: запрос «как считается налог на добавленную стоимость» не найдёт фрагмент, где слова «налог» и «стоимость» не встречаются вместе, даже если смысл совпадает. Для таких задач подойдёт векторная база, а Graphify лучше использовать как дополнение.

С практической точки зрения, парсинг кода через AST зависит от языка. Поддерживаются основные — Python, JavaScript, TypeScript, Go, Java, C#, Rust — но если в репозитории есть код на редком диалекте или только что вышедшей версии языка, грамматика может не распознать конструкции. Тогда в графе появится «чёрная дыра»: файл есть, а связей нет.

Если мы посмотрим на репозиторий с несколькими сотнями тысяч файлов, локальная индексация превратится в ожидание. Graphify пересчитывает зависимости при каждом изменении, и на больших проектах это заметно замедляет работу. Для таких масштабов лучше индексировать только изменённые пути или разбить репозиторий на модули.

PDF без текстового слоя — ещё одна граница. Graphify не делает OCR, поэтому сканированные счета или договоры он прочитать не сможет. Сначала нужно прогнать файл через tesseract или аналоги, а потом уже скормить Graphify.

SQL‑схемы извлекаются по диалекту. Если в дампе есть специфичные расширения PostgreSQL или Oracle, которые парсер не знает, связи между таблицами могут потеряться. Перед индексацией стоит проверить, какой диалект используется:

bash
# Пример проверки диалекта в дампе PostgreSQL
grep -i "CREATE TABLE" dump.sql | head -20

Если парсер не справляется, можно предварительно очистить дамп от специфичных конструкций или указать диалект в конфиге:

yaml
# graphify.yaml
sql:
  dialect: postgresql
  ignore_extensions:
    - plpgsql
    - dblink

Вывод простой: Graphify хорош там, где важна предсказуемость структуры — зависимости между файлами, таблицы в базе, ссылки в документации. Он не заменяет векторный поиск и не лечит проблемы с масштабом или отсутствием текстового слоя в PDF.

Часто задаваемые вопросы

Нужен ли Graphify, если у меня уже есть векторная база?

Нет, не вместо, а вместе. Векторная база ищет по смыслу, Graphify — по структуре и связям. Например, вы можете спросить у агента «где используется функция calculate_tax?» и получить точный путь к файлу и строке, а не приблизительный фрагмент. Оба инструмента дополняют друг друга, особенно в сложных проектах с большим количеством кода и документации.

Какие языки программирования и форматы поддерживаются?

На текущий момент Graphify парсит Python, JavaScript, TypeScript, Go, Java, C# и Rust через AST. SQL‑схемы поддерживаются для PostgreSQL, MySQL и SQLite. PDF принимаются с текстовым слоем; сканы нужно предварительно обработать OCR. Полный список языков лучше уточнять в репозитории проекта, так как поддержка расширяется с каждым релизом.

Как подключить Graphify к Claude Code?

Через файл CLAUDE.md, где описывается структура графа и пути к ключевым модулям. Claude Code читает этот файл и может ориентироваться в связях, которые построил Graphify. Подробнее о настройке CLAUDE.md можно почитать в этой статье по Карпати. Для Cursor и Codex принцип аналогичный: достаточно указать путь к сгенерированному графу в конфиге агента.

Можно ли использовать Graphify с приватным кодом?

Да, и это один из главных плюсов. Парсинг происходит локально, ничего не отправляется на внешние серверы. Граф остаётся на вашем оборудовании, поэтому подходит для закрытых репозиториев и проектов с NDA.

Как часто нужно переиндексировать?

После каждого коммита или при изменении файлов. Можно настроить файловый сторож (watcher), который запускает индексацию по событию. Пример на systemd:

ini
# /etc/systemd/system/graphify-watcher.service
[Unit]
Description=Graphify file watcher
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/graphify watch --path /home/user/project --config /home/user/graphify.yaml
Restart=always
User=alexey

Но для больших репозиториев лучше индексировать только изменённые ветки, а не весь проект целиком.

Работает ли Graphify с Rivet или другими инструментами оркестрации агентов?

Да, граф можно экспортировать в формат, понятный Rivet, и использовать для маршрутизации агентов. Если вы уже строите оркестрацию на базе Rivet, Graphify даст ей точку опоры в виде реальной структуры кода, а не только описаний в промптах. Больше про Rivet можно почитать в материале про оркестрацию AI‑агентов и варианте на S3.

Почему в статье упоминается Ponytail?

Ponytail помогает агенту писать меньше кода, а Graphify — понимать, какой код уже есть. Вместе они снижают количество повторов и ошибок при генерации. Подробнее про Ponytail — в отдельной статье.

Где взять навыки для агентов, которые будут работать с графом?

В репозитории mattpocock/skills есть готовые навыки для разных агентов. Их можно адаптировать под Graphify, чтобы агент понимал, как обходить граф и извлекать зависимости. Ссылка: Навыки для ИИ‑агентов из репозитория mattpocock/skills.

Graphify не панацея, но даёт предсказуемость там, где хаос связей обычно остаётся невидимым.

Поделиться:TelegramX / TwitterVK

Читайте также