25 августа 2026 в русскоязычных ИИ-лентах снова всплыл слоган LLMScience 1044: «RL с нуля на C». Рядом в поиске стоят «reinforcement learning c», «reinforce на чистом C» и старые гайды по Atari. Живой репозиторий 2026 года это не Gym, не Stable-Baselines и не конспект Sutton & Barto. Это harshbhatt7585/cRL Харша Бхатта: autograd, политика, rollout и шаг по весам в стандартном C, плюс двухчасовое видео на канале freeCodeCamp от 19 августа 2026. Ниже сверка с кодом, не пересказ змейки и не дамп курса.
Зачем вайб-кодеру RL на C, если уже есть агент в редакторе
Когда вы просите модель «добавь RL», она почти всегда тянет Python, Gymnasium, тензор и готовый PPO. Цикл прячется за env.step и loss.backward(). Вы видите кривую награды и не видите, куда делся градиент. Вайб-кодинг здесь не «собери сайт за вечер». Это умение читать петлю, которую агент вам нагенерил, и понять, где она врёт. Каркас самого вайб-цикла мы разбирали отдельно: как собрать сайт с нуля через AI.
Чистый C снимает три слоя сразу. Нет интерпретатора. Нет фреймворка. Нет среды, которая сама считает столкновение и награду за кадром. Остаётся то, из чего собран любой современный RL, включая GRPO у reasoning-моделей: состояние, действие, награда, траектория, обновление политики. Если этот контур не держится в голове, разговоры про PPO и RLHF остаются слоганами.
Какой репозиторий настоящий. Сверка 25 августа 2026
Репозиторий на месте. Автор Harsh Bhatt, аккаунт harshbhatt7585. Создан 7 июля 2026, последний пуш 17 июля 2026. На странице GitHub в день сверки 34 звезды и 7 форков. Язык один: C. Лицензии в карточке нет. Это не зеркало PyTorch, не обёртка над BLAS и не порт Atari. Состав, который мы открыли:
- autograd.c и autograd.h: узлы графа, forward и backward, тип VAR_TYPE_REINFORCE_LOSS;
- mat.c и mat.h: матрицы, matmul с транспонированием, ReLU, softmax, сам reinforce;
- model.c: актор 76→128→128→5, softmax, лосс REINFORCE;
- env.c: среда, rollout, reward-to-go, шаг SGD и main;
- arena.c и arena.h: арена памяти, в main просят 1 ГиБ;
- prng.c, base.h, readme.md, картинка assets/training.png.
Сборка из README: clang env.c -o env -lm, затем ./env. Makefile нет. env.c подключает model.c, тот подключает остальные .c как один translation unit. Внешних библиотек нет, только libc и libm. Видео курса: Code a Reinforcement Learning Library in C from Scratch на freeCodeCamp, около двух часов двадцати минут. Анонс: Building a Reinforcement Learning Framework from Scratch in Pure C. Код в ролике и код в репозитории это один проект. Не смотрите ролик как силлабус. Смотрите файл.
Рядом в поиске часто всплывает antirez/ttt-rl: крестики-нолики, меньше 400 строк C, март 2025. Это другой атом. Там нет вычислительного графа, есть ручной backward и награда за партию. Полезный сосед, не «тот самый репозиторий 2026». Двоюродный брат по духу «с нуля на C», уже про GPT, не про политику: MicroGPT-C, GPT Карпаты на чистом C.
Петля, которую вы должны увидеть, а не змейка
Слово Snake в README сбивает. В SnakeENV нет хвоста и нет роста. Агент это одна клетка на квадратной сетке. create_env(36) даёт поле 6 на 6. Еда это вторая клетка. Стена это выход за край. Награда в get_reward: плюс 20 за еду, минус 10 за край. Эпизод рвётся на game_over или на лимите 100 шагов. Это не гайд «как научить змейку». Это крошечная среда, чтобы петля уместилась в один файл.
Цикл в train() читается сверху вниз. Сначала 64 rollout по 100 шагов. На каждом шаге: собрать вектор состояния, forward_pass по графу политики, сэмплировать действие из softmax, шаг среды, записать в траекторию. Потом с конца эпизода считают reward-to-go с gamma = 0.99. По всему rollout считают среднее и стандартное отклонение возвратов. Преимущество действия: (G - mean) / (std + 1e-8), пишут только в слот выбранного действия. Дальше forward по графу лосса, backward_pass, в конце SGD: веса минус lr / N на накопленный градиент, lr = 0.05. Эпох 2000. Это и есть петля. Игра здесь только датчик награды.
- Сброс среды: агент в центре, еда в случайной клетке.
- Состояние в вектор: one-hot клетки агента, one-hot еды, направление взгляда.
- Политика выдаёт 5 чисел, softmax, сэмпл действия.
- Среда двигает клетку, считает награду, ставит done.
- После пачки эпизодов: возвраты, базовая линия, REINFORCE, шаг по весам.
Пять действий в enum: влево, вправо, вверх, вниз и NONE. Если модель выбрала NONE, среда идёт дальше в текущем направлении. Вектор входа 76 чисел: 36 плюс 36 плюс четыре слота на направление. Выход политики 5 логитов. Это не баг в статье. Это то, что лежит в create_actor_model и в build_state_vector. Если будете форкать, сначала сверьте размер входа с максимальным индексом pov.
Autograd в C: граф, а не магия .backward()
В Python autograd это воздух. Здесь узел это структура Var: значение, градиент, флаги, до двух входов, таблица операций. Типы: add, sub, matmul, ReLU, softmax, reinforce_loss. Параметры помечены VAR_FLAG_PARAMETER | VAR_FLAG_REQUIRES_GRAD. Вход и вектор преимущества градиента не копят как веса. build_graph собирает порядок узлов от выхода. Отдельный граф до softmax это инференс политики. Отдельный граф до лосса это обучение. Forward идёт по списку. Backward ставит градиент выхода в 1 и идёт с конца. Веса чистят один раз на эпоху, затем копят градиент по всем шагам всех траекторий. Это и есть «replay buffer» из README: буфер на 1024 траектории, в обучении берут текущие 64. Off-policy DQN здесь нет. Это on-policy REINFORCE с нормализацией возвратов по пачке.
Сеть крошечная. Два скрытых слоя по 128, ReLU, выход 5, softmax. Инициализация в духе Xavier: sqrt(6 / (fan_in + fan_out)). Оптимизатор не Adam. Это вычитание градиента. Автор в ролике сам говорит: без value-головы дисперсия высокая, учиться будет долго и шумно. В логе эпохи печатают средний возврат первого шага, сколько еды съели за пачку, число сэмплов и return_std. Если std огромный, а еды ноль, петля жива, политика ещё нет.
Как собрать и что вы увидите
Нужны clang или gcc, libm, гигабайт свободной оперативки под арену. GPU не нужен. Из корня репозитория: clang env.c -o env -lm && ./env. На экране строки вида Epoch 12 | Average return: -3.140 | Foods: 0 | Samples: 1842 | Return std: 8.221. Картинка в README показывает, что кривая со временем уходит из минуса. Это не бенчмарк и не таблица ток/с. Здесь нет очереди запросов и нет prefill. Если вы привыкли мерить живой инференс LLM, это другой контур: time to first token и запуск инференса.
Практические ловушки из кода, не из рекламы курса.
- Арена на 1 ГиБ в arena_create(GiB(1)). На тесном контейнере процесс не стартует. Это не «модель большая». Это запас под граф и матрицы с запасом.
- Нет сида в README. PRNG свой, в prng.c. Два прогона не обязаны совпасть.
- Лицензии нет. Для пет-проекта нормально. В продукт без явного разрешения автора не тащите.
- Имена в коде живые: Trajactory, опечатки, мало проверок. Это учебный слой, не библиотека с API-стабильностью.
Чего в этом репозитории нет. Чтобы не ждать Atari и ChatGPT
cRL не учит играть в Breakout. Нет пикселей, нет CNN, нет frame-skip. Нет PPO, clip, GAE как в статье Schulman. В ролике мелькает actor-critic как заголовок главы, в model.c value-головы нет: один актор и REINFORCE. Нет Gym-интерфейса, который вы потом подключите к своему боту. Нет RLHF, нет reward-модели на предпочтениях, нет GRPO по группам ответов LLM.
Путаница из одной склейки запросов. Человек клонирует cRL и ждёт, что через час получит агента уровня AlphaGo. Либо просит Cursor «добавить PPO как в курсе» и получает импорт stable_baselines3 поверх этого C. Либо открывает ttt-rl Антиреза и думает, что freeCodeCamp переехал в 400 строк. Три разных атома:
- cRL, 2026: граф, арена, REINFORCE, сетка 6 на 6. Цель: прочитать петлю целиком.
- ttt-rl, 2025: одна сеть, партии против случайного соперника, ручной backward. Цель: самый короткий читаемый RL на C.
- microgpt-c, 2026: GPT, forward и backward руками, SIMD. Цель: понять трансформер, не политику.
Если вам нужен посттренинг языковой модели, это уже другая полка: группа ответов, проверяемая награда, KL к референсу. cRL туда не масштабируется сменой сетки на токены. Он нужен раньше: чтобы слово «траектория» перестало быть слайдом.
Как читать файл, если вы пишете с LLM
Не смотрите двухчасовое видео от нуля, если уже читаете C. Откройте четыре точки и пройдите их с агентом в редакторе как по карте, не как по конспекту.
- get_reward и take_action. Это контракт среды. Пока он не ясен, сеть ни при чём.
- build_state_vector. Что модель вообще видит. Если вектор врёт, политика учит шум.
- create_actor_model и var_reinforce_loss. Где политика, где лосс, где преимущество.
- Два вложенных цикла в train: сбор опыта, затем проход по той же пачке с backward.
Просите модель не «объясни RL», а «покажи, где в этом файле считается G и куда оно попадает в градиент». Если ответ ссылается на Gym, вы не в том репозитории. Если ответ пересказывает Atari, вы не в той статье. Полезный тест на понимание: замените награду за еду на 1 и за край на 0, пересоберите, посмотрите, умерла ли кривая. Это проверка петли, не исследование игр.
Когда петля уже держится, C можно закрыть. Дальше вы снова имеете право на Python. Разница в том, что loss.backward() перестанет быть заклинанием. Вы будете знать, какой граф он прячет.
Коротко
cRL на 25 августа 2026 это живой учебный RL на чистом C: autograd, REINFORCE, арена, поле 6 на 6, один бинарь, без лицензии в карточке. Репозиторий harshbhatt7585/cRL, автор Harsh Bhatt, создан в июле 2026, на странице 34 звезды. Видео freeCodeCamp от 19 августа 2026 ходит вокруг этого кода, не вокруг ALE и не вокруг университетского силлабуса. Запрос «RL с нуля на C» закрывается этим деревом файлов. «Научить змейку» и «пройти Atari» здесь ложные цели. Цель одна: увидеть петлю агента так, чтобы следующий раз, когда редактор нагенерит PPO из десяти импортов, вы знали, чего в этой куче на самом деле нет.
