- BrainTools - https://www.braintools.ru -
Кодинг-агенты умеют быстро генерировать код, но результат часто расходится с ожиданиями. Естественный язык слишком неоднозначен для передачи точных требований, а классические unit-тесты с десятками ассертов тяжело читаемы.
Хороший подход для работы с агентами базируется на принципах BDD (Behavior-Driven Development). Нам важно не то, как реализована задача, а как ведет себя система. Лучший способ передать это поведение [1] машине и легко проверить человеку – исполняемые спецификации.
Подход схож с такими идеями, как снепшот-тесты и Cucumber/Gherkin. Вместо написания тестового кода для каждого сценария, мы пишем тестовый раннер, а всю логику [2] валидации выносим в файлы исполняемых спецификаций.
Файл исполняемой спецификации выступает как контракт:
Входные данные: аргументы, исходные файлы, состояние системы.
Ожидаемый результат: stdout, выходные файлы, последовательность вызовов.
Тестовый раннер читает исполняемую спецификацию, запускает код и сравнивает фактический результат с поведением [3], зафиксированным в файле.
При разработке утилиту outln из предыдущей статьи [4], я сделал формат спецификации на основе yaml. При желании можно использовать, например, json или toml (я рассматривал toml, но yaml показался более читаемым в этом сценарии). Можно, конечно, придумать и свой формат, но плюс существующего формата в том, что агент с ним уже знаком – меньше шанс запутаться в синтаксисе.
Задача утилиты — пройтись по всем исходникам в папке и вывести названия файлов и header-комментарии из них.
Одна из спецификаций:
args: # входные параметры для cli
- src
src/one.ts: | # файл 1
/** One summary. */
export const one = 1;
src/two.ts: | # файл 2
/** Two summary. */
export const two = 2;
stdout: | # результат, который мы ожидаем получить
src/one.ts: One summary.
src/two.ts: Two summary.
Пример со сценарием ошибки [6]:
args:
- foobar
stderr: |
Error: Directory foobar does not exist
exit_code: 1
Получившиеся yaml-файлы и есть исполняемые спецификации. Запускаем cli с данными из args на папке описанной в файле и сравниваем то что получилось с ожидаемым результатом из stdout и stderr. Как видим:
Всё в одном месте: аргументы, входные файлы и ожидаемый вывод.
Читается и понимается за 10 секунд.
Легко расширяется: например, если нужно добавить влияние env — это просто еще одно поле.
Агенту максимально легко копировать такой формат для создания новых файлов спецификаций.
В проекте outln на данный момент 127 таких спецификаций, большинство из них созданы агентом.
Главная ценность исполняемой спецификации заключается в том, что она становится общим артефактом для совместной работы.
Естественный язык удобен человеку, но оставляет пространство для галлюцинаций агента. Написание жесткого кода тестов понятно машине, но сильно замедляет и утомляет человека. Спецификация же выступает единым источником истины, который находится ровно посередине. Человеку легко формулировать бизнес-правила в виде понятных структур, а ИИ работает с предсказуемыми форматами данных.
Помимо этого, формат дает и другие преимущества:
Стабильный контракт: Агент не спорит с формулировками. Он видит четкое правило: конкретный вход → конкретный выход.
Документация через примеры: Агент может сам генерировать новые исполняемые спецификации по вашему шаблону, опираясь на контекст задачи.
Масштабируемое ревью: Проверить глазами 10 файлов исполняемых спецификаций намного быстрее, чем вникать в 10 новых unit-тестов.
Инициализация: Задается формат исполняемых спецификаций и реализуется базовый раннер. Реализация раннера как правило это достаточно тривиальная задачи и ее можно отдать агенту.
Постановка задачи:
Можно написать спецификации самостоятельно (тогда их не придется ревьювить).
Либо поставить задачу агенту: “Добавь новые исполняемые спецификации для функционала X”. В этом случае основное усилие будет направлено на ревью спецификаций, которые у него получились.
Итерация: Агент запускает новые спецификации и видит разницу между текущим поведением и ожидаемым, тем самым получая четкую цель для реализации.
Исполняемые спецификации превращают работу с кодинг-агентом из рулетки “надеюсь, оно сработает” в контролируемый процесс. Машине даются не абстрактные требования, а четкий пример поведения — общий артефакт, который одинаково легко понятен как агенту, так и человеку.
Ссылки:
Пример раннера который используется для тестов outln можно посмотреть тут: https://github.com/ptol/casefile-runner [7]
Примеры спецификаций тут: https://github.com/ptol/outln/tree/main/tests/cases [8]
Автор: dotneter
Источник [9]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/26542
URLs in this post:
[1] поведение: http://www.braintools.ru/article/9372
[2] логику: http://www.braintools.ru/article/7640
[3] поведением: http://www.braintools.ru/article/5593
[4] предыдущей статьи: https://habr.com/ru/articles/1005800/
[5] Image: https://sourcecraft.dev/
[6] ошибки: http://www.braintools.ru/article/4192
[7] https://github.com/ptol/casefile-runner: https://github.com/ptol/casefile-runner
[8] https://github.com/ptol/outln/tree/main/tests/cases: https://github.com/ptol/outln/tree/main/__tests__/cases
[9] Источник: https://habr.com/ru/articles/1006140/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1006140
Нажмите здесь для печати.