Temper 0.5B

huggingface.co/temper-ai
Октябрь 2026

Temper 0.5B — небольшая модель, дообученная на базе Qwen2.5-Coder-0.5B-Instruct, упор которой сделан на языке Rust. Это позволило ей обойти модели крупнее, вплоть до x3 по параметрам. Целью было проверить возможности крошечной модели в узкой задаче.

Первая версия

Изначально в качестве учителя был выбран Qwen3.6-35B-A3B, который на карте NVIDIA A40 48GB за ~9 часов смог выдать 2700 примеров на Rust. Формат данных для обучения был проще, чем в итоговой версии Temper. В каждом примере была функция с интерфейсом, doc-комментарием, просьбой дописать и пустым телом с одним todo!(). Первая попытка с этим датасетом уже дала заметный рост по сравнению с базовым Qwen.

Задача из датасета первой версии (переведено с английского)

Задание

Допиши код на Rust ниже. Замени каждый todo!() рабочей реализацией.
Не меняй определения типов и сигнатуры функций. Используй только стандартную библиотеку Rust.
Ответь полным кодом в одном блоке ```rust.

/// Calculates the number of full fuel tanks required and the amount of remaining fuel.
///
/// Given `total_fuel` and `tank_capacity`, returns a tuple `(full_tanks, remainder)`.
/// If `tank_capacity` is zero, returns `(0, total_fuel)`.
pub fn fuel_logistics(total_fuel: i64, tank_capacity: i64) -> (i64, i64) {
    todo!()
}
Ответ учителя
/// Calculates the number of full fuel tanks required and the amount of remaining fuel.
///
/// Given `total_fuel` and `tank_capacity`, returns a tuple `(full_tanks, remainder)`.
/// If `tank_capacity` is zero, returns `(0, total_fuel)`.
pub fn fuel_logistics(total_fuel: i64, tank_capacity: i64) -> (i64, i64) {
    if tank_capacity == 0 {
        return (0, total_fuel);
    }
    let full_tanks = total_fuel / tank_capacity;
    let remainder = total_fuel % tank_capacity;
    (full_tanks, remainder)
}

После трёх эпох обучения на этих примерах первая версия решала с первой попытки 64,6% тривиальных задач против 45,6% у базовой Qwen2.5-Coder-0.5B. На простых задачах её результат вырос больше чем вдвое, с 15,0% до 34,3%. Прирост на наборах MultiPL-E оказался скромнее и составил 10 пунктов на humaneval-rs и 7 на mbpp-rs.

Temper 0.5BПервая версия TemperQwen2.5-Coder-0.5B
0 20 40 60 80 100 trivial 81,8 easy 59,0 medium 18,0 humaneval-rs 34,7 mbpp-rs 38,8
Рис. 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% всего датасета пришлось на алгоритмические примеры.

Задача без заготовки (переведено с английского)

Задание

Напиши функцию, которая принимает два отсортированных списка строк и сливает их в один отсортированный список, оставляя только строки, которые не начинаются с 'a' и не заканчиваются на 'z'.

Используй только стандартную библиотеку Rust.

Ответ учителя
pub fn merge_filtered(list1: Vec<String>, list2: Vec<String>) -> Vec<String> {
    let mut result = Vec::with_capacity(list1.len() + list2.len());
    let mut i = 0;
    let mut j = 0;
    while i < list1.len() && j < list2.len() {
        if list1[i] <= list2[j] {
            let s = &list1[i];
            if !s.starts_with('a') && !s.ends_with('z') {
                result.push(s.clone());
            }
            i += 1;
        } else {
            let s = &list2[j];
            if !s.starts_with('a') && !s.ends_with('z') {
                result.push(s.clone());
            }
            j += 1;
        }
    }
    while i < list1.len() {
        let s = &list1[i];
        if !s.starts_with('a') && !s.ends_with('z') {
            result.push(s.clone());
        }
        i += 1;
    }
    while j < list2.len() {
        let s = &list2[j];
        if !s.starts_with('a') && !s.ends_with('z') {
            result.push(s.clone());
        }
        j += 1;
    }
    result
}

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

Результаты

По сравнению с первой версией эта заметно прибавила на Rust-версиях классических бенчмарков из MultiPL-E. Доля задач, решённых с первой попытки, на humaneval-rs выросла на 7,6 пункта, а на mbpp-rs на 7,9. С вероятностью 95% реальный прирост лежит между 3,0 и 12,3 пункта на первом наборе и между 5,1 и 10,7 на втором, так что это не случайность.

0 10 20 30 40 50 60 70 80 90 100 0.5B 1B 1.5B 2B 3B параметры DeepSeek-V4-Flash, учитель, 284B (13B активных)83,8 Qwen2.5-Coder-3B44,1 Qwen2.5-Coder-1.5B33,4 Qwen3.5-0.8B10,2 Qwen2.5-Coder-0.5B21,4 ThoxEdge-RustCoder-0.5B13,0 rust-mentor-0.6B8,1 Temper 0.5B37,5
0 10 20 30 40 50 60 70 80 90 100 0.5B 1B 2B 3B параметры DeepSeek-V4-Flash, учитель, 284B (13B активных)83,8 Coder-3B44,1 Coder-1.5B33,4 Qwen3.5-0.8B10,2 Coder-0.5B21,4 ThoxEdge13,0 rust-mentor8,1 Temper 0.5B37,5
Рис. 2. Доля решённых с первой попытки задач MultiPL-E (pass@1, %, humaneval-rs и mbpp-rs вместе, 510 задач) в зависимости от размера модели. Шкала параметров логарифмическая.

Свой бенчмарк

Для Rust почти нет бенчмарков, на которых имеет смысл мерить крошечную модель. MultiPL-E переводит на Rust задачи HumanEval и MBPP, но это алгоритмические функции над числами и списками, исходно написанные для Python. Структуры с методами, трейты, обработка ошибок через Result и работа с крейтами в них почти не встречаются, хотя именно из этого состоит повседневный код на Rust.

Поэтому к двум наборам MultiPL-E добавлен собственный бенчмарк из 100 задач трёх уровней сложности. Каждая задача состоит из просьбы обычным текстом, публичного интерфейса и скрытых тестов. Модель возвращает полный код, он компилируется вместе с тестами, и задача засчитывается, только если проходят все тесты. Тесты, которые модель напишет сама, на результат не влияют. Для каждой задачи проверено, что эталонное решение проходит все тесты, заготовка с todo!() компилируется и не проходит ни одного.

Просьбы в бенчмарке написаны в том же стиле, что и обучающие данные Temper. Значит, независимое сравнение с другими моделями дают именно наборы MultiPL-E, а свои задачи показывают, насколько модель справляется с обычным кодом на Rust.

Другие модели для 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. Обе модели проверялись в тех же условиях, что и остальные, без системного промпта и без рассуждений.

Табл. 1. Решено с первой попытки (pass@1). Мелким шрифтом доля задач, решённых хотя бы в одной из 10 попыток (pass@10).

Temper
0.5B
ThoxEdge-
RustCoder 0.5B
rust-mentor
0.6B
Qwen2.5-Coder
1.5B
Qwen3.5
0.8B
Qwen2.5-Coder
0.5B
Qwen2.5-Coder
3Bдля сравнения
DeepSeek-V4
Flashучитель, 284B
Тривиальные задачиtrivial¹81,8%pass@10 94,0%55,8%pass@10 88,0%35,4%pass@10 68,0%70,0%pass@10 94,0%45,2%pass@10 84,0%45,6%pass@10 88,0%77,0%pass@10 96,0%97,8%pass@10 100,0%
Простые задачиeasy¹59,0%pass@10 76,7%13,0%pass@10 50,0%13,7%pass@10 30,0%42,7%pass@10 73,3%13,3%pass@10 36,7%15,0%pass@10 50,0%51,0%pass@10 83,3%97,3%pass@10 100,0%
Средние задачиmedium¹18,0%pass@10 35,0%1,5%pass@10 10,0%0,0%pass@10 0,0%11,0%pass@10 45,0%3,0%pass@10 5,0%1,0%pass@10 5,0%25,0%pass@10 50,0%79,5%pass@10 100,0%
Генерация функцийHumanEval-RS34,7%pass@10 57,1%13,3%pass@10 41,7%4,6%pass@10 16,7%31,0%pass@10 69,2%6,9%pass@10 20,5%16,9%pass@10 42,3%50,6%pass@10 87,2%89,6%pass@10 98,1%
Базовые задачиMBPP-RS38,8%pass@10 54,8%12,8%pass@10 44,4%9,7%pass@10 27,1%34,4%pass@10 64,7%11,6%pass@10 33,3%23,4%pass@10 50,8%41,3%pass@10 72,9%81,2%pass@10 89,8%

Подсвечен лучший pass@1 среди моделей до 1.5B. Знаком ▲ отмечена 3B там, где она выше всех моделей до 1.5B. Все модели Qwen взяты в версиях Instruct. Замер: temperature 0.8, top_p 0.95, 10 ответов на задачу, pass@k по несмещённой оценке из статьи Codex. ¹ Внутренний набор Rust-задач.

Ограничения и планы

У Temper есть заметные ограничения. Модель лучше всех среди сравнимых по размеру решает задачу с первой попытки, но при десяти попытках её преимущество пропадает. По 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).