Пробуем Codex CLI от OpenAI для доработки ХрюХрюКара

от автора

Привет Хабр!

Пару дней назад я опубликовал статью про ХрюХрюКар — телегам-бот для борьбы со стоянкой автомобилей на зелёных зонах. Проект с открытым исходным кодом.

За два дня ко мне обратилось несколько сторонников с просьбой добавить их города. Но вот незадача: у меня была возможность через админ-панель Django править данные в базе, но об этом кеш сервера не узнает (основной бекэнд на Go). В результате приходилось добавлять данные и перезагружать контейнеры с go-бекэндом вручную.

Основные серверы ХХК уже имели сторы, которые получают и обрабатывают апдейты, прилетающие через redis.

По сути, оставалось внести правки в часть django-бэкенда, чтобы обрабатывать сигналы pre_save и pre_delete, сериализовать данные и отправлять их в нужный канал редиса.

Решил поручить эту задачу Codex CLI, которую вчера OpenAI представили нам с вами. Хотелось посмотреть насколько этот инструмент будет полезен в среднего размера проектах с развитой структурой, средних размеров кодовой базой и широким стеком технологий.

Если у вас совсем нет времени на просмотр всего процесса, то вот что я получил от Codex CLI примерно за 22 минуты*, пару промптов средней длины, один промпт с трейсбеком из консоли и 1.17$.

*Примечание: работа выполнялась на ПК, имеющем слабый канал связи (скорость 5-10 Мбит/сек.)

Доработка кода на Python/Django

После установки и настройки Codex CLI, я перешел в корневую директорию ХХК и выполнил в консоли команду: codex "<промпт>" и начал ждать.

Вот какой промпт я использовал:

У меня на бекэнде в Go есть сторы в папке go_backend/internal/store/redis_broker которые подписаны через редис на каналы go_backend/internal/store/channels.go. Через эти каналы сторы получают инфу об апдейтах go_backend/internal/store/update_messages.go. Сделай мне в бэкенде Django для моделей, которые в папке django_backend/core/models, набор простых сериализаторов (для преобразования экземпляра модели в простой JSON со всеми полями), при этом название и тип данных полей смотри в моделях в папке go_backend/internal/models. Сериализаторы положи в папку django_backend/core/serializers. Затем в папке django_backend/core/signals сделай обработчики сигналов pre_save и pre_delete для всех моделей, в которых надо формировать сообщения об апдейтах и засылать их в нужный канал редиса.

Вот процесс работы утилиты (ссылка на Youtube):

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

В результате первой итерации работы я получил вот этот коммит. Из положительных моментов: Codex CLI заметил что модели в Go-шной части проекта имеют теги для сериализации в JSON, которые отличаются от названия поля в модели Django. Это моя ошибка, но утилита сделала сериализатор с ее учетом.

Код по результату оказался рабочий и выполняющий мою задачу, но сервер Django не завёлся, а в консоли я увидел ошибку:

django_backend  | Traceback (most recent call last): django_backend  |   File "/backend/core/apps.py", line 10, in ready django_backend  |     import core.signals  # noqa django_backend  |     ^^^^^^^^^^^^^^^^^^^ django_backend  |   File "/backend/core/signals/__init__.py", line 3, in <module> django_backend  |     from .redis_signals import * django_backend  |   File "/backend/core/signals/redis_signals.py", line 4, in <module> django_backend  |     import redis django_backend  | ModuleNotFoundError: No module named 'redis'

Для чистоты эксперимента я решил сам не исправлять ситуацию, а просто скинуть этот трейсбек в Codex CLI. Вот результат (ссылка на Youtube):

Codex CLI предложил добавить в зависимости redis версии 4.7.0. Я все-же проверил pypi и взял последнюю версию 5.2.1.

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

Доработка кода на Go

Я запустил codex со следующим промптом:

пройди по всем сторам кеша в папке go_backend/internal/store/cache и везде в методе subscribeUpdates при получении апдейта перед блокировкой мьютекса выводи через s.log.Debug … само сообщение апдейта, чтобы я видел что приходит через редис

Вот процесс работы утилиты (ссылка на Youtube):

В результате я получил то, что хотел, правда утилита немного мне поломала отступы. Линтер поправил все отступы при сохранении и я получил вот этот коммит.

Далее проверил что все работает:

Что по расходам?

Работала модель o4-mini, потратил я 1,363,957 токенов, что стоило 1,17$:

Сейчас дашборд в OpenAI позволяет сохранять и смотреть всю историю запросов к API, и вот какого вида записи там:

Если провалиться в любую строку, то в каждой из них в начале будет набор инструкций из Codex CLI, мои инструкции, которые я положил в ~/.codex/instructions.md, сам промпт и результат работы — либо ответ, либо вызов функции. Думаю что расход можно сократить, немного ужав набор своих инструкций. У меня в ~/.codex/instructions.md были следующие инструкции (копипаста из другой утилиты):

## Global Coding Style  - Preserve my existing code style exactly. - Use single-line formatting even for long lines — do not wrap lines. - Keep comments in English. - Maintain existing comment style, indentation, and spacing. - Always use `//` for inline comments in Go. - Do not reorder imports unless explicitly asked.  ## Code Practices  - Keep logging format consistent. - Use mutexes where concurrency issues may occur — match existing usage patterns. - Respect metrics and monitoring setup already in the codebase. - Avoid introducing external libraries unless explicitly permitted.  ## Output Rules  - Only output changed lines or code snippets — do not repeat unchanged code. - Do not add explanations unless explicitly asked. - Avoid adding TODOs or FIXMEs unless explicitly requested.  ## Language Specific  ### Go  #### SQL Style  - Use raw SQL queries. - If using `database/sql`, use `?` placeholders (MySQL). - If using `sqlx`, use `:named` placeholders and `sqlx.Named` where applicable. - Stick to the existing project style — do not mix styles across projects.  #### General Go Rules  - Preserve code style, comment format, and log structure. - Do not auto-format or refactor unless explicitly requested. - Follow existing patterns for SQL declaration blocks, struct tags, etc.  ### Python - Use Django ORM and DRF conventions. - Use `gettext_lazy as _` for translations. - Use snake_case for variable and function names.

Вывод

Утилита отлично справилась с решением конкретной задачи в проекте с кодовой базой средних размеров и развитой структурой.

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

Ссылки

Репозиторий codex

Исходные коды ХрюХрюКар

Статья про ХрюХрюКар v.2

Наш телеграм-канал


ссылка на оригинал статьи https://habr.com/ru/articles/901742/