sum(abs(b) for b in xs), sorted(xs)[::-1]), то есть совмещение семейств list_transform, list_scan и arithmetic_scalar.Кроме того, для каждого семейства я руками придумал по 15 темплейтов. Темплейт это тройка "инструкция", "код" и "оракул" вида:
canonical_instruction: "given two integers a and b, return the absolute value of {{ c1 }} times {{ v1.d }} {{ op.d }} {{ c2 }} times {{ v2.d }}"
code: |
def f(a, b):
return abs({{ c1 }} * {{ v1.v }} {{ op.v }} {{ c2 }} * {{ v2.v }})
oracle: "abs({{ c1 }} * {{ v1.v }} {{ op.v }} {{ c2 }} * {{ v2.v }})"В которые я мог подставлять операции, значения и так далее из какого-то param space и проверить через оракула.
Такая система дала мне 120 темплейтов, из каждого темплейта я смог насемплить по 30 инстансов задач (3600 задач), у них я перефразировал описания по 20 раз через Qwen3-4B (72000 задач), которые я мутировал по 8 раз через AST. После дедупликации у меня получилось примерно 507 тысяч семплов с тестами, сгенерированными через оракула. Часть выкинул, оставил 141к семплов — на этом я и учил свои модели.
В качестве эвала я сделал HumanEval-лайк бенч с тремя сабсетами: EASY, MEDIUM, HARD. Отличаются они друг от друга, как нетрудно догадаться, сложностью задач — например, в EASY может быть задача "проверить на чётность", в MEDIUM "вернуть сумму чётных чисел", а в HARD — "вернуть произведение первого и последнего элемента массива". В качестве недостижимой верхней границы я взял HumanEval — всё таки задачи там на три порядка сложнее моих и вообще, только 91 из 164 задач описывается моим токенизатором. Сопоставимого размера модельки получилали в своё время там в районе 1-2%. Кроме того, важно было посмотреть не только как модель решает задачи, но и как конкретно она их не решает. Поэтому я ввёл шесть категорий решений: format_ok (всё ок), bad_format (не проходит запуск из-за ошибки синтаксиса), stub_body (пустой боди функции с pass), test_fail (не проходят тесты, но всё ок), timeout (таймаут), exec_error (ошибка исполнения).
Сабсет EASY был самым простым не только из-за низкой композициональности, но и потому что 10 из 20 задач покрывались датасетом. Это была в том числе такая проверка — насколько модель вообще выучила то, что я в неё лью. При этом важно, что покрыты были именно названия задач, то есть промпты, а не сами по себе темплейты. Я специально вычистил это из трейн сета через жаккардову близость, так что проверка была относительно честная: у модели были иные решения, чем в тесте, но были похожие задачи. Вторая половина задач в EASY, а так же MEDIUM и HARD сабсеты были сделаны для проверки генерализации модели; если модель решала там задачи, то класс, мы видим генерализацию.