Сколько Rust помещается в 0.5B
Temper 0.5B — моя небольшая модель, дообученная на базе Qwen2.5-Coder-0.5B‑Instruct, упор которой сделан на языке Rust. Узкая специализация позволила ей обойти модели крупнее, вплоть до x3 по параметрам. Целью дообучения было проверить возможности крошечной модели в узкой задаче, сравнить с общими того же размера и выше.
Первая версия Temper
Изначально в качестве учителя был выбран Qwen3.6–35B‑A3B, который на карте NVIDIA A40 48GB за ~9 часов смог выдать 2700 примеров на Rust. Формат данных для обучения был проще, чем в итоговой версии Temper и хуже фильтровался от мусора. В каждом примере была функция с интерфейсом, doc‑комментарием, просьбой дописать и пустым телом с одним todo!(). Первая попытка с этим датасетом уже дала заметный рост по сравнению с базовым Qwen2.5-Coder-0.5B.
После трёх эпох обучения на этих примерах первая версия решала с первой попытки 64,6% тривиальных задач против 45,6% у базовой Qwen2.5-Coder-0.5B. На простых задачах (уровень немного выше тривиальных) её результат вырос больше чем вдвое, с 15,0% до 34,3%. Прирост на наборах MultiPL‑E был меньше, составил 10 пунктов на humaneval‑rs и 7 на mbpp‑rs.
Модель | Тривиальные | Простые | Средние | HumanEval‑RS | MBPP‑RS |
|---|---|---|---|---|---|
Temper 0.5B | 81,8% | 59,0% | 18,0% | 34,7% | 38,8% |
Первая версия Temper | 64,6% | 34,3% | 5,0% | 27,1% | 30,8% |
Qwen2.5-Coder-0.5B | 45,6% | 15,0% | 1,0% | 16,9% | 23,4% |
Таблица 1. Процент задач, решённых с первой попытки (pass@1). Первая версия Temper и итоговая Temper 0.5B против базовой Qwen2.5-Coder-0.5B.
Второй датасет
Дальше датасет вырос до 10 тысяч примеров с новым учителем DeepSeek‑V4-Flash. Он в целом сильнее Qwen3.6–35B‑A3B в программировании и к тому же дешевле по API. Данные стали качественнее, из них убрали дубликаты и утечки бенчмарков. Из генерации DeepSeek были приняты ~60% примеров, которые прошли компиляцию и тесты. Из них ~65% составляли просьбы без кода, ~35% были задачами с заготовками и около 35% всего датасета пришлось на алгоритмические примеры. После обучения на этом датасете Temper был дообучен с подкреплением (RL). Модель писала по несколько решений каждой задачи, награду получали те из них, что проходят тесты.
Результаты
По сравнению с первой версией эта заметно прибавила на Rust‑версиях классических бенчмарков из MultiPL‑E. Доля задач, решённых с первой попытки, на humaneval‑rs выросла на 7,6 пункта, а на mbpp‑rs на 7,9.
Модель | Тривиальные¹ | Простые¹ | Средние¹ | HumanEval‑RS | MBPP‑RS |
|---|---|---|---|---|---|
Temper 0.5B | 81,8% (94,0%) | 59,0% (76,7%) | 18,0% (35,0%) | 34,7% (57,1%) | 38,8% (54,8%) |
ThoxEdge‑RustCoder 0.5B | 55,8% (88,0%) | 13,0% (50,0%) | 1,5% (10,0%) | 13,3% (41,7%) | 12,8% (44,4%) |
rust‑mentor 0.6B | 35,4% (68,0%) | 13,7% (30,0%) | 0,0% (0,0%) | 4,6% (16,7%) | 9,7% (27,1%) |
Qwen2.5-Coder 1.5B | 70,0% (94,0%) | 42,7% (73,3%) | 11,0% (45,0%) | 31,0% (69,2%) | 34,4% (64,7%) |
Qwen2.5-Coder 0.5B | 45,6% (88,0%) | 15,0% (50,0%) | 1,0% (5,0%) | 16,9% (42,3%) | 23,4% (50,8%) |
Qwen2.5-Coder 3B (для сравнения) | 77,0% (96,0%) | 51,0% (83,3%) | 25,0% ▲ (50,0%) | 50,6% ▲ (87,2%) | 41,3% ▲ (72,9%) |
DeepSeek‑V4-Flash (учитель, 284B) | 97,8% (100,0%) | 97,3% (100,0%) | 79,5% (100,0%) | 89,6% (98,1%) | 81,2% (89,8%) |
Таблица 2. Решено с первой попытки (pass@1). В скобках процент задач, решённых хотя бы в одной из 10 попыток (pass@10). Жирным выделен лучший pass@1 среди моделей до 1.5B. Знаком ▲ отмечена 3B там, где она выше всех моделей до 1.5B. Все модели Qwen взяты в версиях Instruct. Замер проводился с temperature 0.8 и top_p 0.95, по 10 ответов на задачу, pass@k считался по несмещённой оценке из статьи Codex. ¹ Внутренний набор Rust‑задач.
Кроме моделей Qwen в сравнение вошли две открытые модели того же размера, которые другие авторы дообучили на Rust. ThoxEdge‑RustCoder-0.5B от THOX.ai построена на той же базе, что и Temper, и обучена на открытом датасете Strandset‑Rust‑v1. rust‑mentor-0.6b получена из Qwen3-0.6B через QLoRA на том же датасете и задумана как помощник для изучения Rust и ревью кода. Её LoRA‑адаптер перед замером был слит с исходной Qwen3-0.6B. Обе модели проверялись в тех же условиях, что и остальные, без системного промпта и без рассуждений.
Свой бенчмарк
Для Rust почти нет бенчмарков, на которых имеет смысл мерить крошечную модель. Например MultiPL‑E переводит на Rust задачи HumanEval и MBPP, но это алгоритмические функции над числами и списками, исходно написанные для Python. Структуры с методами, трейты, обработка ошибок через Result и работа с крейтами в них почти не встречаются, хотя именно из этого состоит повседневный код на Rust. Было решено к двум наборам MultiPL‑E добавить собственный бенчмарк из 100 задач трёх уровней сложности: каждая задача состоит из просьбы обычным текстом, публичного интерфейса и скрытых тестов. Модель возвращает полный код, он компилируется вместе с тестами, и задача засчитывается, только если проходят все тесты. Тесты, которые модель напишет сама, на результат не влияют. Для каждой задачи проверено, что эталонное решение проходит все тесты, заготовка с todo!() компилируется и не проходит ни одного.
Тривиальные (50 задач). Одна короткая функция в несколько строк над числами, строками, срезами,
OptionиResult.Простые (30 задач). Небольшой тип и работа с ним, структура с методами,
enumиmatch,HashMap,Display, итераторы и оператор?.Средние (20 задач). Крейты axum, serde, tokio, clap, regex и thiserror,
Rc<RefCell>, потоки и времена жизни.
Пример тривиальной задачи
Напиши функцию, которая возвращает число символов в строке. Каждый символ должен считаться отдельно, чтобы функция одинаково работала с пустой строкой, обычным английским текстом и строкой с неанглийскими буквами. Используй только стандартную библиотеку Rust. Используй ровно такой интерфейс:
pub fn char_count(s: &str) -> usize;
Пример простой задачи
Сделай банковский счёт с балансом, который можно посмотреть, пополнить и с которого можно снять деньги. Если денег не хватает, снятие должно вернуть ошибку ровно с текстом «insufficient funds», а баланс при этом не должен меняться. Используй только стандартную библиотеку Rust. Используй ровно такой интерфейс:
pub struct Account { /* private fields */ }
impl Account { pub fn new(balance: u64) -> Self; pub fn balance(&self) -> u64; pub fn deposit(&mut self, amount: u64); pub fn withdraw(&mut self, amount: u64) -> Result<(), String>;
}
Пример средней задачи
Напиши тип дерева со значением и списком детей, где дети могут быть общими (один и тот же ребёнок встречается в нескольких местах). Добавь две функции. Одна возвращает сумму значений узла и всего, что под ним, другая прибавляет число к значению узла и всего, что под ним. Общее поддерево нужно обходить и учитывать один раз для каждого места, где оно встречается. Используй только стандартную библиотеку Rust. Используй ровно такой интерфейс:
use std::cell::RefCell;
use std::rc::Rc;
pub struct Node { pub value: i32, pub children: Vec<Rc<RefCell<Node>>>,
}
pub fn tree_sum(node: &Rc<RefCell<Node>>) -> i32;
pub fn add_to_all(node: &Rc<RefCell<Node>>, delta: i32);
Ограничения и планы
Модель лучше всех среди сравнимых по размеру решает задачу с первой попытки, но при десяти попытках её преимущество пропадает. По pass@10 Qwen2.5-Coder-1.5B обходит её на medium, HumanEval‑RS и MBPP‑RS, и на последних двух разница доходит до 10–12 пунктов. Отчасти это цена обучения с подкреплением, которое сделало ответы модели увереннее и однообразнее. Qwen2.5-Coder-3B остаётся сильнее Temper на средних задачах и на обоих наборах MultiPL‑E. Собственные задачи бенчмарка написаны в стиле обучающих данных Temper, поэтому независимую оценку дают только наборы MultiPL‑E.
Датасет будет расти, сейчас в нём не хватает задач на веб‑фреймворки и асинхронный код. Для автодополнения в редакторе ещё предстоит решить, нужен ли модели режим заполнения середины кода (FIM).
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.