Привет, Хабр! Возможно, вы знаете меня по дайджестам проекта far2l, но сегодня хочу поделиться кое-чем другим. Это небольшая и очень полезная утилита и формат файлов для неё, которые родились из моей повседневной работы с AI-ассистентами (в том числе в процессе работы над тем же фаром). Штука получилась настолько удобной, что я решил поделиться ей с сообществом. Поехали!
Боль и страдания ручного копипаста
Думаю, многим здесь знаком этот цикл:
Вы: «Перепиши вот эту функцию, чтобы она обрабатывала ещё и такой-то случай».
AI: «Конечно! Вот обновлённый код…» (выдаёт красивый блок кода).
Вы: Вручную выделяете этот блок, переключаетесь в IDE, находите нужный файл и нужную функцию, аккуратно заменяете старый код на новый, поправляете отступы, которые почти всегда едут. Запускаете, видите ошибку, возвращаетесь к AI и повторяете всё заново.
Ручной копипаст — самое узкое место во всём процессе. Он отнимает время, утомляет и провоцирует ошибки. Да, есть платные плагины для IDE, позволяющие AI менять код самостоятельно, но они стоят денег, некоторые недоступны в РФ, а ещё мне удобнее самому решать, какие части кода проекта экспонировать нейронке, это сильно влияет на качество результата.
Конечно, все мы пробовали предлагать ИИ сразу генерировать patch-файлы, и, конечно, знаем, что файлы получаются битыми. Происходит это от того, что на входе сетка «видит» не байты, а токены, и сгенерировать верный с точностью до байта патч она не в состоянии.
Размышляя о том, как можно было бы упростить процесс, я вспомнил про систему обновлений форума Simple Machines. Там использовался семантический подход: вместо строгих инструкций «замени строку 4 на вот такую», файлы с обновлениями содержали семантические инструкции «найди вот этот блок кода, и допиши после него вот это». Интуиция подсказывала: такой патч ИИ сочинить будет куда проще!
Из этой идеи родился формат файлов .ap (AI-friendly Patch), который уже некоторое время существенно облегчает мою жизнь и экономит время.
Как устроен .ap?
Это простой, человекочитаемый YAML-файл. Формат использует несколько ключевых понятий:
действие, action: Что мы делаем? (REPLACE, INSERT_AFTER, INSERT_BEFORE, DELETE).
цель, target: Где мы это делаем?
фрагмент, snippet: Уникальный фрагмент кода, который нужно найти. Поиск «умный» — он игнорирует отступы и пустые строки
якорь, anchor (необязательно): Если snippet встречается в файле несколько раз (например, return result), можно указать «якорь» — более крупный и точно уникальный блок кода (скажем, сигнатура функции), внутри которого нужно искать snippet
На примере из README
Представим, что у нас есть простой файл greeter.py
:
# greeter.py
def say_hello():
# Эту строку мы хотим изменить
print("Hello, world!")
Мы просим AI изменить приветствие (не забыв «скормить» ему спеку на .ap формат и инструкцию генерировать ответ именно в нём). Вместо нового блока кода он выдаёт нам вот такой файл (назовём его afix.ap
— я обычно использую это имя, чтоб легко было найти патч вверху списка файлов в папке):
# afix.ap
version: "1.0"
changes:
- file_path: "greeter.py"
modifications:
- action: REPLACE
target:
snippet: 'print("Hello, world!")'
content: 'print("Hello, AI-powered Habr!")'
Запускаем патчер из командной строки:
python3 ap.py --patch afix.ap
И наш greeter.py
автоматически обновляется:
# greeter.py
def say_hello():
# Эту строку мы хотим изменить
print("Hello, AI-powered Habr!")
И, разумеется, формат позволяет пропатчить (или создать с нуля) целую серию файлов. Больше никакого ручного поиска и копипаста! Вся рутина автоматизирована.
Как начать пользоваться?
Всё необходимое — в репозитории:
Сам скрипт-патчер
ap.py
(в папкеimplementation
)Файл со спецификацией формата
ap.md
Общаясь с AI, прикладываем к промпту содержимое ap.md
и ставим задачу: «сгенерируй ответ в формате ap». Как минимум, Gemini 2.5 Pro отлично с этим справляются. Полученный .ap файл сохраняем себе и применяем скриптом ap.py
.
Приглашаю обсуждать и тестировать!
Вот такая штука получилась. Я уже активно использую её в своих проектах, и она экономит мне кучу времени и нервов. Возможно, это только начало: наверняка и формат и утилиту можно улучшить.
Поэтому и делюсь этим с вами. Пробуйте, тестируйте, ломайте! Что если snippet будет слишком коротким? А что если он найдётся 10 раз? Как поведёт себя патчер с разными окончаниями строк (спойлер: я постарался это учесть)?
Буду рад любому фидбеку, идеям и, конечно, тикетам в багтрекере. Давайте вместе сделаем взаимодействие с AI-помощниками ещё чуточку удобнее!
nidalee
Я думал, все уже перешли на агентов, которые либо сами правят файлы, либо пишут пулл реквесты.
Rive
Чем выше разнообразие, тем ниже риски что дополнительный компьют не удастся привлечь, если основные каналы его поставки заблокируют.