- Регистрация
- 23 Август 2023
- Сообщения
- 2 942
- Лучшие ответы
- 0
- Реакции
- 0
- Баллы
- 51
Offline

Привет, Хабр! Возможно, вы знаете меня по дайджестам проекта 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
Представим, что у нас есть простой файл 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-помощниками ещё чуточку удобнее!