idea_world_labDEV JOURNAL
пятница, 12 июня 2026 г.

2026-06-12 Ретроспектива

Я решил снова написать ретроспективу

Оставляю размышления после долгого перерыва. Причина, по которой я не вел записи всё это время, заключалась не столько в том, что я был занят, сколько в желании оставить только идеальный текст. Я хотел записывать только после того, как результаты будут чётко оформлены, а процесс неудач или изменения направления посередине казались мне неуместными для фиксации.

Но, оглянувшись назад, именно этот процесс оказался самым значимым. За последние 10 дней готовых результатов было немного, но то, что мы исследовали для создания специализированной модели кодирования Godot, где столкнулись с трудностями и какие решения изменили, накопилось довольно много. Поэтому сегодня я решил собрать весь этот поток в один обзор.

Эксперимент с локальной моделью

Сначала я хотел сэкономить на оплате RunPod и попробовать запустить модель семейства Qwen на локальном ПК. Поскольку у меня установлен RTX 3060, я думал, что модель примерно 9 млрд параметров всё же получится запустить в WSL.

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

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

Исследование набора данных Godot

Чтобы обучить модель, сначала потребовались данные. Поэтому, ищя набор данных, который можно использовать для обучения коду Godot 4, я нашёл wallstoneai/godot-gdscript-dataset на Hugging Face.

Сначала я думал, что это просто набор файлов .gd, но после анализа с помощью Gemini выяснилось, что структура важнее. Суть в том, что вместо того, чтобы вытаскивать отдельные файлы из репозитория на GitHub, набор данных раскрывает весь репозиторий целиком, сохраняя контекст проекта.

Этот набор данных, по‑видимому, объединяет README.md репозитория, файлы .gd и структуру каталогов в один текст, включая название проекта, версию Godot, дерево файлов и содержимое каждого файла в формате Markdown. Таким образом модель видит не только отдельные фрагменты кода, но и структуру проекта и взаимосвязи между файлами.

Особенно важным оказался способ определения версии Godot 3/4. В Godot нет типичной для веб‑проектов структуры с package.json или requirements.txt. Вместо этого нужно читать значения config_version, config/features в файле project.godot или использовать различия в синтаксисе GDScript.

Например, в Godot 3 используются выражения onready var, KinematicBody, а в Godot 4 — @onready, CharacterBody3D. Выявив такие синтаксические различия с помощью регулярных выражений или парсера, можно получить представление о том, как выполнять фильтрацию по версии даже для языков без файлов версии на основе JSON.

Данных набора было недостаточно

Позже я посмотрел видео на YouTube о дообучении на старом языке программирования OPL.

Но даже после просмотра видео я не до конца понял суть. Процесс сбора набора данных и процесс дообучения должны быть связаны, однако вопрос «Если есть только набор данных, что и как обучать?» постоянно оставался.

Поэтому я спросил у наставника SSAFY, как лучше собрать данные редкого языка определённой версии. Получил важный ответ.

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

Второй момент — нужно на основе сырых данных заставить LLM создавать пары вопрос/ответ. Услышав это, я стал более ясно понимать, что мне нужно делать. Нужно не только собирать код Godot 4, но и генерировать вопросы и ответы, формируя набор данных инструкций.

Если этого не сделать, при запросе вроде «Сделай карту», модель может ответить не на Godot, а на Python. Существующие модели, скорее всего, обучались на гораздо большем количестве Python‑данных. Если правильные ответы не определены чётко, может появиться старый код Godot или совсем другой язык.

Проблемы с набором данных инструкций и промптингом

В качестве кандидата на набор данных инструкций я посмотрел Magicoder-Evol-Instruct-110K.

Но большинство примеров были ориентированы на Python. Просто взять их и использовать для создания модели, специализированной на Godot 4, выглядело неподходящим.

Тогда возник вопрос: «Нужно ли явно указывать Godot?» Если добавить много данных Godot, может быть, модель будет отвечать кодом Godot даже без явного указания.

Эту часть я уточнил у старшего студента, и направление стало более ясным. Сейчас может быть более эффективно, чем просто RAG, правильно спроектировать промптинг или структуру поиска по документам, а также создать векторные представления Markdown‑документов, чтобы модель могла находить нужные данные.

В итоге на текущем этапе я пришёл к выводу, что более точный ответ можно получить, задав явный контекст, например «Создай карту в Godot», а не просто «Создай карту». Поскольку у существующих моделей большой вес Python‑данных, важно явно указывать условие Godot в начале промпта.

Перепроектирование архитектуры

Сначала я представлял архитектуру довольно просто.

Сбор данных → создание набора вопросов/ответов → обучение модели

Однако вскоре я понял, что такая структура слишком опасна. Если собирать данные, не зная достаточно о том, что изменилось из Godot 3 в 4, можно получить неправильный код, который окажется в наборе правильных ответов. Даже если создавать набор вопросов/ответов, в нём могут перемешаться Python‑код и код Godot 3.

Поэтому я придумал структуру, в которой официальная документация служит отправной точкой. Мы краулим документы миграции из Godot 3 в 4 и официальную документацию Godot 4, создаём RAG‑чат‑бота и размещаем его на переднем плане, чтобы он определял, относится ли собранный код к Godot 3 или 4, использует ли старый API и подходит ли он для Godot 4.

Прикреплённая диаграмма — это черновой вариант конвейера, который я оформил в тот момент.

Godot специализированный конвейер обучения модели

Большой поток выглядит так:

  • Краулим официальную документацию Godot и документы миграции, создаём базу знаний RAG.
  • Скачиваем проекты Godot с GitHub по репозиториям.
  • Объединяем README, структуру файлов и код GDScript в один контекст.
  • Фильтруем на первом этапе по файлу project.godot и различиям в синтаксисе GDScript.
  • С помощью RAG‑чат‑бота дополнительно определяем, относится ли код к Godot 3/4 и использует ли старый API.
  • Оставляем только данные, подготовленные для Godot 4, и превращаем их в наборы instruction/response.
  • Обучаем модель кодинга Godot 4 с помощью SFT и DPO/Preference.

SFT и DPO направление

Дальше, задавая вопросы ChatGPT, я получил неожиданные идеи. Изначально я думал только о «модели, генерирующей код Godot 4», но задачи обучения можно разбить более детально.

В SFT можно сформулировать такие задачи:

  • Классификация кода Godot 3/4
  • Преобразование кода Godot 3 в код Godot 4
  • Генерация кода Godot 4
  • Исправление ошибок в коде Godot 4
  • Отклонение или корректировка устаревшего API Godot 3

В DPO/Preference можно чётко задать плохие и хорошие ответы. Например, ответ, содержащий синтаксис Godot 3, считается плохим, а ответ, написанный чистым кодом Godot 4 — хорошим.

Такой подход заставил меня понять, что сначала нужно решить, что считается хорошим ответом, а не просто «собрать как можно больше данных».

Краулинг официальной документации Godot

Чтобы реализовать эту идею, я нашёл инструмент для краулинга и использовал crawl4ai.

Я прокраул и задокументировал почти 1 500 страниц, включая официальную документацию Godot 4, руководство по миграции из Godot 3 в 4, справочник классов Godot 4 и учебные материалы.

Сначала казалось, что я собрал слишком много, но по сравнению с полным контекстом модели это лишь около 3 % от общего объёма, что, по моему мнению, вполне приемлемо для использования в RAG или поисковой системе по документам.

Конвейер данных и проблемы ввода‑вывода

Перепроектировав архитектуру, я столкнулся с вопросами дискового ввода‑вывода и таймингов обучения. Если сбор, предобработка, постобработка, сохранение, переиндексация и обучение идут последовательно, возникнет узкое место.

Я проконсультировался с наставником. Он посоветовал не пытаться проводить онлайн‑fine‑tuning, а сначала быстро собрать и обработать данные, а обучение выполнять пакетно.

Например, запускать reinforcement learning или fine‑tuning только когда набор данных превысит определённый порог. Как в репликационных слотах, обработка после достижения порога уменьшает нагрузку на I/O, а в тех случаях, где важна реактивность, приоритетом становится сбор и подготовка данных, а не обучение.

Полностью избавиться от расходов на переиндексацию невозможно. Поэтому более реалистично установить правила, когда переиндексировать, а когда обучать.

Итоги дня

Подводя итоги десяти дней работы, сначала я просто хотел «создать модель кодинга Godot». Сейчас у меня более конкретная схема.

  • Одних сырых наборов кода недостаточно. Нужно отфильтрованное под Godot 4 содержимое, структура проверки на основе официальных документов, наборы instruction/response, задачи SFT и критерии DPO/Preference.
  • На текущем уровне моих навыков построить модель кодинга без крупной модели типа Qwen нереально. Сравнивая локальную модель и возможности кодинга ChatGPT, я понял, что нельзя игнорировать разницу в размере модели и объёме предобучения.

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

Ретроспектива

Пишу эту ретроспективу и понимаю, что нужно понизить планку записи. Если фиксироваться только на идеальных результатах, важные процессы исчезают. Неудачные эксперименты, сомнительные решения, изменённая архитектура — всё это материал для будущих решений, и если их не задокументировать, потом будет непонятно, почему были сделаны те или иные выборы.

В дальнейшем я планирую чаще фиксировать процесс, а не только готовый результат. Лучше записать, что пошло не так, чем откладывать ретроспективу. Записывать неидеальные записи тоже нормально; главное — зафиксировать, что я пробовал, чему научился и какие критерии буду использовать дальше.

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