- BrainTools - https://www.braintools.ru -

Как я делаю «снимок» проекта в JSON для ИИ и разворачиваю его обратно

Я много работаю с веб-проектами и параллельно постоянно использую нейросети. Довольно быстро стало ясно простое вещь: обсуждать с моделью реальный проект, перекидывая ей по одному файлу, бессмысленно. Ей нужен не фрагмент, а контекст — структура каталогов, реальные пути, живой код, а не абстрактные «примерчики».

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

На этом фоне возник очень приземлённый запрос: один раз аккуратно «сфотографировать» проект в технически удобный формат, а дальше работать уже с этим снимком. Хранить его в репозитории рядом с кодом, прикладывать к задачам, загружать ассистентам GPT, подключать к своим RAG-сервисам. Так появился небольшой PHP-репозиторий scan2json.

Репозиторий лежит на GitHub: https://github.com/simai/scan2json [1]. Его идея простая: в одну сторону он превращает проект в JSON/JSONL, а в другую — по JSONL может развернуть структуру папок и файлов в отдельную директорию. Дальше буду говорить, зачем мне это понадобилось, что именно я сделал и как этим можно пользоваться в реальной работе.

Почему «просто отправить пару файлов» не работает

Если честно, проблема не в том, что модели «не понимают код». Проблема в том, что мы подаём этот код в совершенно неудобной форме. Мы даём мозаику: кусок контроллера без шаблона, шаблон без данных, конфиг без использования. Разработчик ещё держит в голове карту проекта: он знает, где лежат модули, где общий хелпер, какие части связаны между собой. У модели этой карты нет, пока мы её явно не передали.

Инструменты в IDE частично помогают. Они могут автоматически подкидывать соседние файлы, можно настроить локальный индекс, кое-как подружить это с отдельным агентом. Но всё это жёстко привязано к конкретному редактору и плохо живёт снаружи: вы не положите такой индекс в репозиторий, не приложите к задаче, не передадите стороннему разработчику как самостоятельный артефакт.

Мне хотелось иметь именно артефакт. Файл или набор файлов, который существует независимо от IDE и конкретной машины. Его можно коммитить, версионировать, отдавать ассистентам GPT, использовать в своих сервисах. Внутри у него должен быть честный срез проекта: относительные пути, дерево каталогов и содержимое файлов. Не обязательно всего проекта — только той части, с которой я сейчас работаю. Но этот срез должен быть полным внутри себя: без «ой, забыл ещё вот этот файл».

Отсюда родилась формулировка: нужен скрипт, который из выбранной части проекта делает структурированный JSON, а при желании позволяет по этому JSON собрать отдельную копию. Всё остальное — детали реализации.

Что такое scan2json и из чего он состоит

С точки зрения [2] кода инструмент очень простой. Вокруг него нет фреймворка, лишних абстракций и прочего. Вся логика [3] крутится вокруг двух файлов:

  • scan.php — сканирует выбранную папку проекта и превращает её содержимое в JSONL, цельный JSON и JSON по частям;

  • restore.php — читает JSONL и по нему создаёт файлы и папки в отдельной директории.

Оба файла — обычные PHP-скрипты, которые я кладу под DOCUMENT_ROOT в нужном окружении. Они работают через браузер, защищены паролем и ни к чему не привязаны: им без разницы, это сайт, API-сервис или монолитное приложение.

Главным героем здесь является scan.php. Именно он решает основную задачу — сделать из живого проекта аккуратный JSON-снимок. restore.php появился чуть позже как естественное продолжение: когда стало понятно, что иногда хочется развернуть такой снимок обратно в отдельную песочницу.

С точки зрения доступа всё предельно прямолинейно. При запуске скрипт просит пароль, причём этот пароль нужно обязательно поменять: в коде по умолчанию зашит пароль по умолчанию и в скрипт встроена защита от его использования.

Как устроен scan.php: выбор корня и фильтрация

Когда я открываю scan.php в браузере и ввожу пароль, первый вопрос, который нужно решить, — откуда вообще сканировать. Мне не всегда нужен весь проект целиком: иногда достаточно одного модуля, иногда только директории app или src, иногда — отдельной «рабочей» части большого монолита.

У меня есть два способа задать корневую папку. В простейшем варианте я просто указываю путь: корень сайта, конкретный каталог, модуль и так далее. Если структуру проекта я хорошо знаю, это самый быстрый путь.

Если путь вспоминать [4] не хочется, удобнее воспользоваться встроенной навигацией. Интерфейс показывает текущую директорию, даёт возможность подняться на уровень выше и выбрать одну из подпапок. Я постепенно «проваливаюсь» туда, где лежит нужная область, и в какой-то момент просто останавливаюсь: вот отсюда и начинаем.

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

Под тонкую настройку я сделал в интерфейсе кнопку Choose items…. Логика простая: я задаю корень сканирования, нажимаю кнопку и вижу список всех элементов первого уровня внутри этой папки. Напротив каждого — чекбокс. По умолчанию всё включено. Дальше я просто снимаю галочки с того, что не хочу видеть в итоговом JSON: отдельные каталоги, большие папки с файлами, единичные тяжёлые объекты. После применения выбора сканер обходит только отмеченные элементы верхнего уровня, а внутрь уже заходит автоматически.

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

Какие форматы сканер создаёт на выходе

Когда выбор корня и фильтрации готов, я запускаю сканирование. На выходе получается несколько представлений одних и тех же данных:

  • JSONL — файл, где каждая строка соответствует одному файлу проекта и содержит поля file и content;

  • цельный JSON — один большой массив объектов {file, content};

  • разбитый JSON — тот же массив, но автоматически нарезанный на несколько файлов, если проект слишком большой для одного.

Базовым форматом для дальнейшей обработки у меня является JSONL. Он выглядит примерно так:

{"file":"local/components/app/orders/class.php","content":"..."}

Такой файл удобно читать построчно: не нужно тянуть всё в память [5], можно стримить, можно обрабатывать его любыми инструментами командной строки или своими скриптами. Я использую JSONL, когда хочу построить поверх среза собственные пайплайны: индексировать код, делать векторизацию, искать повторяющиеся структуры, собирать аналитику по проекту.

Цельный JSON нужен там, где ожидают один валидный документ: ассистенты GPT, некоторые внешние утилиты, внутренние сервисы, которым проще работать с массивом. Для больших проектов одного такого файла может быть слишком много, и тогда на помощь приходит нарезка. Сканер ориентировочно считает объём данных и, когда он становится слишком большим, закрывает текущий файл и начинает следующий. Каждая запись {file, content} всегда попадает целиком в одну часть.

Все эти файлы складываются в директорию scan_tmp под DOCUMENT_ROOT. Там же на странице я вижу список того, что уже сформировано, могу скачать нужный вариант и посмотреть, сколько примерно «слов» получилось. Это не точный подсчёт токенов под конкретную модель, но хороший индикатор масштаба: сотни тысяч слов или десятки мегабайт — это уже сигнал подумать, как лучше нарезать данные для ассистента.

Кратко про restore.php: зачем он мне нужен

Изначально я делал инструмент только «в одну сторону» — чтобы получать JSON. Но довольно быстро стало понятно, что JSONL сам по себе — это уже почти автономный артефакт. Логично уметь по нему поднять отдельную копию проекта, пусть и не полную, а именно ту, которая была в срезе.

Под это я написал restore.php. Его задача минималистична: прочитать JSONL, который ранее сформировал scan.php, и для каждой строки с объектом вида {file, content} создать соответствующий файл в выбранной директории. Скрипт нормализует относительные пути, следит за тем, чтобы никакие .. не позволили выйти за пределы целевой папки, по мере необходимости создаёт недостающие каталоги.

Важно зафиксировать одно ограничение: restore.php не знает и не пытается знать, как проект выглядел «по-настоящему». Он восстанавливает только то, что попало в JSONL. Если при сканировании я исключил какие-то каталоги, их не будет и в развёрнутой копии. Если я сканировал не весь проект, а только один модуль, после восстановления у меня будет именно этот модуль, а не весь сайт.

На практике я использую restore.php реже, чем scan.php, но он несколько раз очень помог. Например, когда нужно было собрать из снимка отдельную песочницу для экспериментов, отдать срез проекта подрядчику в виде «вот вам JSONL и скрипт, сами развернёте» или выделить проблемный модуль в отдельный мини-проект, не выдёргивая его руками из большого репозитория.

Как я использую scan2json день за днём

Сейчас scan2json для меня — не разовая утилита, а часть обычного рабочего процесса. Сценарии при этом довольно разные.

Частая ситуация: мне нужно обсудить с ИИ доработку в существующем проекте. Я беру scan.php, кладу его под DOCUMENT_ROOT, настраиваю пароль и открываю в браузере. Дальше выбираю корень, откуда буду сканировать, через путь или навигацию, отрезаю лишнее через Choose items… и запускаю сканирование. На выходе получаю JSONL, который уже можно обрабатывать любыми своими инструментами.

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

Другой сценарий — ассистенты «по проекту» внутри GPT. Здесь я обычно беру цельный JSON или набор частей, создаю ассистента, загружаю эти файлы как знания и в инструкциях объясняю, что это конкретный проект: как устроены пути, где искать шаблоны, где бизнес-логику. После этого разработчик может прийти к ассистенту и задать прикладной вопрос: где реализована регистрация, какие классы отвечают за оплату, как правильно добавить новый статус сделки. Ассистент отвечает уже с опорой на реальные файлы.

Есть и сценарии исследования. Когда я разбираю чужой или legacy-проект, мне удобно сначала сделать срез через scan.php, а уже потом подключать ассистента или свои скрипты. Можно попросить модель описать архитектуру по каталогам, найти подозрительные места (копипаст, странные зависимости), накидать список технического долга. Можно, наоборот, использовать чисто свои инструменты для анализа JSONL и только на итогах анализа звать ИИ.

Иногда бывает и обратная история: у меня уже есть старый JSONL, например, снимок конкретного релиза. Тогда я запускаю restore.php, разворачиваю срез в отдельную директорию и получаю «мини-проект» с той же структурой, но без всего, что было специально отрезано на этапе сканирования. В такой песочнице можно не бояться экспериментировать: переписывать код, подключать различные инструменты, давать доступ ассистентам — основную кодовую базу это никак не затрагивает.

Ограничения и нюансы

У инструмента есть несколько естественных ограничений и тонкостей.

Во-первых, scan2json работает по файловой системе честно и последовательно. Если в проекте много тяжёлых артефактов, медиа и бинарников, их лучше сразу исключать: либо через общие настройки, либо через Choose items…. Иначе JSON-файлы получатся слишком крупными и не очень пригодными для передачи ассистентам.

Во-вторых, restore.php не предназначен для резервного копирования. Он не восстанавливает «всё как было», он поднимает именно тот срез, который вы сами сформировали через scan.php. Для полноценной стратегии бэкапов нужны другие инструменты, а scan2json здесь может быть только вспомогательной частью — например, чтобы дополнительно хранить структурированные срезы кода.

В-третьих, к безопасности стоит относиться серьёзно. Скрипты живут под DOCUMENT_ROOT, запускаются из браузера и по этой причине должны быть защищены не только паролем в коде. Я всегда меняю пароль по умолчанию, при необходимости ограничиваю доступ по IP и предпочитаю держать инструмент либо в изолированной среде, либо на стендах, а не на открытом проде.

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

Всё остальное — детали использования и предпочтения. Кому-то удобнее всегда сканировать весь проект, кому-то — только отдельные модули. Кто-то использует JSONL только для своих внутренних анализаторов, кто-то строит поверх него полноценные ассистенты.

Для меня scan2json стал довольно простым, но полезным ответом на реальную задачу: перестать объяснять проект ИИ по кусочкам. Сейчас это два небольших скрипта, которые делают ровно то, что от них требуется: scan.php снимает структурированный снимок проекта в JSON/JSONL, а restore.php по этому снимку умеет поднять отдельную копию. Если вам близка сама идея, можно просто клонировать репозиторий, положить scan.php рядом с одним из своих проектов, снять первый срез и посмотреть, как такой формат ляжет на ваш процесс работы с ИИ.

Автор: zabarov

Источник [6]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/22825

URLs in this post:

[1] https://github.com/simai/scan2json: https://github.com/simai/scan2json

[2] зрения: http://www.braintools.ru/article/6238

[3] логика: http://www.braintools.ru/article/7640

[4] вспоминать: http://www.braintools.ru/article/3999

[5] память: http://www.braintools.ru/article/4140

[6] Источник: https://habr.com/ru/articles/973962/?utm_source=habrahabr&utm_medium=rss&utm_campaign=973962

www.BrainTools.ru

Rambler's Top100