ruTron-quality-classifier-base
Russian only. The model was trained and evaluated only on Russian web documents (FineWeb-2
rus_Cyrl). It was not tested on other languages; its scores for them are meaningless.
A multi-head quality model for Russian web text, made for pretraining-data filtering. For
every document it predicts an overall pretraining value, 13 quality axes on a 1–5
scale, 8 content flags, topic, format, audience and region. It imitates the labels that
Claude Sonnet 5.5 gave to 26,000 FineWeb-2 documents
(krysyuk/fineweb-2-russian-quality-annotations-26k).
This is the more accurate of the two models. It runs the whole frozen
nvidia/Nemotron-3-Embed-1B-BF16 encoder over up to 4,096 tokens per document, so it
is about 16 times slower than
krysyuk/ruTron-quality-classifier-lite.
The lite model scored all 699M documents of rus_Cyrl:
krysyuk/fineweb-2-russian-quality-full.
| base (this model) | lite | |
|---|---|---|
| Encoder | all 16 layers, inside the model file | first 4 layers, inside the model file |
| Text read | up to 4,096 tokens (first 10,000 + last 1,700 characters) | first 512 tokens |
overall QWK / axes QWK (test) |
0.876 / 0.870 | 0.820 / 0.832 |
| Speed, Apple M4 Pro | ~1.2 docs/s | ~19 docs/s |
| Use for | accurate scoring, thousands to millions of documents | whole corpora |
Quick start
pip install torch "transformers>=5.18" safetensors pyarrow huggingface_hub
hf download krysyuk/ruTron-quality-classifier-base --local-dir ruTron-quality-classifier-base
cd ruTron-quality-classifier-base
python predict.py --input docs.jsonl --output scores.jsonl # one {"id", "text"} per line
python predict.py --input docs.parquet --output scores.jsonl --device cuda
import sys
from huggingface_hub import snapshot_download
path = snapshot_download("krysyuk/ruTron-quality-classifier-base")
sys.path.insert(0, path)
from predict import QualityScorer
scorer = QualityScorer(path) # cuda / mps / cpu picked automatically
scorer.score(["Текст документа ..."])[0]
# {"overall": 2.65, "overall_direct": 2.66, "overall_stacked": 2.64, "p_overall_4plus": 0.0001,
# "axes": {"cleanliness": 3.4, ...}, "flags": {"unsafe_content": 0.003, ..., "answer_dump": false},
# "topic": {"engineering": 0.91, ...}, "format": "review", "audience": "enthusiasts", "region": "none"}
Everything is in this repo: encoder, heads and tokenizer in one model.safetensors
(~2.5 GB), nothing else is downloaded. Tested
with torch 2.14 and transformers 5.18.
Output
| Field | Meaning |
|---|---|
overall |
Pretraining value, expected level on 1–4 (4 = "4 or 5"): mean of the two overall heads. Use this one |
overall_direct, overall_stacked |
The two heads: from the text directly, and from the predicted axes, flags and categories |
p_overall_4plus |
Probability that the annotator would give 4 or 5; use it to pick the top |
axes.* |
Expected score 1–5 for each of the 13 axes |
flags.* |
Probabilities of 8 flags; answer_dump is a keyword rule (true / false) |
topic |
Top-3 topics with probabilities (multi-label) |
format, audience, region |
Most likely class |
Rating criteria
The model reproduces the rubric of the annotations dataset.
overall |
Decision | Typical documents |
|---|---|---|
| 1 | Exclude | Spam, doorways, garbage, any unsafe content |
| 2 | Rather exclude | Ads, filler |
| 3 | Keep: ordinary acceptable web | News, forum post, blog |
| 4 | Keep with a higher weight | Substantive, well-written text: explanations or facts |
| 5 | Reference quality, upsample | Textbook, encyclopedic article, deep analysis |
Levels 4 and 5 are merged into "4+": 5 is only ~0.1% of the data.
| Output | Count | Names |
|---|---|---|
| Quality axes, 1–5 | 13 | cleanliness, language_quality, naturalness, information_density, factual_specificity, educational_value, reasoning_depth, expertise_level, credibility, originality, commercial_neutrality, durability, domain_depth |
| Flags, probability | 8 | unsafe_content, seo_doorway, machine_generated, truncated_or_fragment, suspected_mt, pii_present, official_document, mixed_language |
| Rule flag, true / false | 1 | answer_dump |
| Categories | 4 | topic (30 topics), format (26), audience (7), region (5); names in labels.json |
What every axis, flag and category means, with a description of each level:
annotations dataset, "Rating criteria".
The exact annotation prompt is in that repo, prompt/annotate_v6.system.md.
Suggested use: drop overall < 1.5 (or < 2), and documents with high unsafe_content /
seo_doorway / machine_generated; upsample the top by p_overall_4plus.
Input
The model sees what the annotator saw: the first 10,000 and last 1,700 characters of the
document, with the passage: prefix, cut at 4,096 tokens. predict.py does this.
Architecture
text → Nemotron-3-Embed-1B (frozen, bf16)
├─ mean pooling of all 17 hidden states → learned layer mix
├─ 256-token chunks at layers 4/8/12/16 → layer mix → attention pooling over chunks
└─ 32 text statistics (Gopher / C4-style: script shares, duplicate lines/n-grams, ...)
→ trunk MLP (1024) → 13 ordinal axis towers (CORN) · 8 flag logits · topic · format · audience · region
→ overall: direct ordinal head + stacked head over the predicted
axis / flag / category probabilities (trained out-of-fold)
The heads (46M parameters) were trained with 5-fold cross-validation, which the stacked
overall head needs; all five are stored in model.safetensors and averaged at
inference. The encoder weights (1.14B parameters, bf16) are included unchanged.
Evaluation
Test split: 2,501 held-out documents (half uniform random, half from a "probably good"
pool, the same mix as training). run05: 200 random documents labelled by Claude Opus
agents instead of Sonnet, which shows how the model agrees with a different annotator.
Sonnet itself agrees with those labels at mean axis QWK ≈ 0.89; that is roughly the
ceiling.
| test | run05 | |
|---|---|---|
| Axes, mean QWK | 0.870 | 0.847 |
overall QWK (1–4) |
0.876 | 0.847 |
overall Spearman |
0.891 | 0.877 |
PR-AUC overall ≥ 4 |
0.75 (base rate 4.7%) | 0.66 (base rate 6%) |
Junk: Sonnet gave 1, overall < 1.5 |
precision 0.93, recall 0.89 | precision 0.86, recall 0.88 |
Per-axis QWK, test:
| Axis | base | lite |
|---|---|---|
cleanliness |
0.89 | 0.86 |
language_quality |
0.85 | 0.83 |
naturalness |
0.87 | 0.85 |
information_density |
0.88 | 0.85 |
factual_specificity |
0.89 | 0.86 |
educational_value |
0.87 | 0.82 |
reasoning_depth |
0.82 | 0.77 |
expertise_level |
0.87 | 0.83 |
credibility |
0.85 | 0.80 |
originality |
0.85 | 0.80 |
commercial_neutrality |
0.92 | 0.88 |
durability |
0.90 | 0.86 |
domain_depth |
0.85 | 0.80 |
Flags, PR-AUC on test. The three marked ones are unreliable: the annotator disagrees with itself on them too.
| Flag | base | lite |
|---|---|---|
seo_doorway |
0.99 | 0.97 |
unsafe_content |
0.94 | 0.89 |
machine_generated |
0.90 | 0.89 |
mixed_language |
0.89 | 0.89 |
official_document |
0.70 | 0.71 |
pii_present (unreliable) |
0.48 | 0.42 |
truncated_or_fragment (unreliable) |
0.47 | 0.39 |
suspected_mt (unreliable) |
0.36 | 0.38 |
Categories, test:
| Category | Metric | base | lite |
|---|---|---|---|
topic |
top-1 accuracy | 0.78 | 0.69 |
region |
macro-F1 | 0.82 | 0.70 |
audience |
macro-F1 | 0.75 | 0.56 |
format |
macro-F1 | 0.63 | 0.54 |
Full numbers: metrics.json.
Speed
The encoder dominates. On an Apple M4 Pro (MPS, bf16) the model scores 1.2 documents
per second (2,500 tokens/s; an average document is ~1,550 tokens after truncation).
For whole corpora use the lite model, which also has a production script with FP8 and
torch.compile.
Limitations
- Russian only (see the top of the card).
- It imitates one LLM annotator (Claude Sonnet 5.5, prompt v6) and inherits its biases; the rubric favours educational and factual text.
- Trained on FineWeb-2 web pages; books, code and chat are out of distribution.
- Top quality (
overall4+) is rare (~2.4% of random documents), so precision in the top is moderate; treat scores as a ranking signal, not a verdict on one document.
Files
| File | |
|---|---|
model.safetensors |
Encoder (all 16 layers, bf16, unchanged) + 5 cross-validation head sets + the stacked overall head |
tokenizer.json, tokenizer_config.json |
Tokenizer of the encoder |
config.json, labels.json |
Head config, class names, order of text statistics |
predict.py |
Inference: command line and QualityScorer |
modeling.py, heuristics.py |
Model code and the 32 text statistics |
metrics.json |
Validation / test / run05 metrics |
LICENSE, NOTICE |
OpenMDW-1.1, the encoder's license, and its attribution notices |
License
OpenMDW-1.1, the license of the base encoder
nvidia/Nemotron-3-Embed-1B-BF16,
which is included here unchanged. The heads were trained on labels produced by Claude Sonnet 5.5 for FineWeb-2 texts
(ODC-By 1.0).
Русский
Только для русского языка. Модель обучена и проверена только на русских веб-документах (FineWeb-2
rus_Cyrl). На других языках её не проверяли, и её оценки для них не имеют смысла.
Многоголовая модель качества русского веб-текста для фильтрации данных предобучения. Для
каждого документа она предсказывает общую ценность для предобучения overall, 13 осей
качества по шкале 1–5, 8 флагов содержания, тему, формат, аудиторию и регион. Модель
повторяет разметку, которую Claude Sonnet 5.5 сделал для 26 000 документов FineWeb-2
(krysyuk/fineweb-2-russian-quality-annotations-26k).
Это более точная из двух моделей. Она прогоняет весь замороженный энкодер
nvidia/Nemotron-3-Embed-1B-BF16 по 4 096 токенам документа, поэтому примерно в 16 раз
медленнее, чем
krysyuk/ruTron-quality-classifier-lite.
Lite-модель оценила все 699 млн документов rus_Cyrl:
krysyuk/fineweb-2-russian-quality-full.
| base (эта модель) | lite | |
|---|---|---|
| Энкодер | все 16 слоёв, внутри файла модели | первые 4 слоя, внутри файла модели |
| Что читает | до 4 096 токенов (первые 10 000 + последние 1 700 символов) | первые 512 токенов |
QWK overall / осей (test) |
0.876 / 0.870 | 0.820 / 0.832 |
| Скорость, Apple M4 Pro | ~1,2 док/с | ~19 док/с |
| Для чего | точная оценка, от тысяч до миллионов документов | целые корпуса |
Быстрый старт
pip install torch "transformers>=5.18" safetensors pyarrow huggingface_hub
hf download krysyuk/ruTron-quality-classifier-base --local-dir ruTron-quality-classifier-base
cd ruTron-quality-classifier-base
python predict.py --input docs.jsonl --output scores.jsonl # по строке {"id", "text"}
python predict.py --input docs.parquet --output scores.jsonl --device cuda
import sys
from huggingface_hub import snapshot_download
path = snapshot_download("krysyuk/ruTron-quality-classifier-base")
sys.path.insert(0, path)
from predict import QualityScorer
scorer = QualityScorer(path) # cuda / mps / cpu выбирается сам
scorer.score(["Текст документа ..."])[0]
Всё лежит в этом репозитории: энкодер, головы и токенизатор, веса в одном
model.safetensors (~2,5 ГБ), больше ничего не скачивается.
Проверено на torch 2.14 и transformers 5.18.
Выход
| Поле | Смысл |
|---|---|
overall |
Ценность для предобучения, ожидаемый уровень 1–4 (4 = «4 или 5»): среднее двух голов overall. Используйте его |
overall_direct, overall_stacked |
Две головы: прямо по тексту и по предсказанным осям, флагам и категориям |
p_overall_4plus |
Вероятность, что аннотатор поставил бы 4 или 5; по ней удобно отбирать лучшее |
axes.* |
Ожидаемая оценка 1–5 по каждой из 13 осей |
flags.* |
Вероятности 8 флагов; answer_dump - правило по ключевым словам (да / нет) |
topic |
3 самые вероятные темы с вероятностями (мультиметка) |
format, audience, region |
Самый вероятный класс |
Критерии оценки
Модель воспроизводит рубрику датасета с разметкой.
overall |
Решение | Типичные документы |
|---|---|---|
| 1 | Исключить | Спам, дорвеи, мусор, любой небезопасный контент |
| 2 | Скорее исключить | Реклама, вода |
| 3 | Оставить: обычный приемлемый веб | Новость, пост на форуме, блог |
| 4 | Оставить с повышенным весом | Содержательный, хорошо написанный текст: объяснения или факты |
| 5 | Эталон, апсемплить | Учебник, энциклопедическая статья, глубокий анализ |
Уровни 4 и 5 объединены в «4+»: оценка 5 - всего около 0,1% данных.
| Выход | Сколько | Названия |
|---|---|---|
| Оси качества, 1–5 | 13 | cleanliness, language_quality, naturalness, information_density, factual_specificity, educational_value, reasoning_depth, expertise_level, credibility, originality, commercial_neutrality, durability, domain_depth |
| Флаги, вероятность | 8 | unsafe_content, seo_doorway, machine_generated, truncated_or_fragment, suspected_mt, pii_present, official_document, mixed_language |
| Флаг-правило, да / нет | 1 | answer_dump |
| Категории | 4 | topic (30 тем), format (26), audience (7), region (5); названия в labels.json |
Что значит каждая ось, флаг и категория, с описанием каждого уровня:
датасет с разметкой, раздел «Критерии оценки».
Точный промпт разметки лежит там же, prompt/annotate_v6.system.md.
Как использовать: отбросить overall < 1.5 (или < 2) и документы с высокими
unsafe_content / seo_doorway / machine_generated, лучшее по p_overall_4plus
апсемплить.
Вход
Модель видит то же, что видел аннотатор: первые 10 000 и последние 1 700 символов
документа с префиксом passage: , обрезанные до 4 096 токенов. Это делает predict.py.
Архитектура
текст → Nemotron-3-Embed-1B (заморожен, bf16)
├─ mean pooling всех 17 скрытых состояний → обучаемая смесь слоёв
├─ куски по 256 токенов, слои 4/8/12/16 → смесь слоёв → attention pooling по кускам
└─ 32 текстовые статистики (в духе Gopher / C4: доли алфавитов, повторы строк и n-грамм, ...)
→ MLP-ствол (1024) → 13 порядковых башен осей (CORN) · 8 логитов флагов · тема · формат · аудитория · регион
→ overall: прямая порядковая голова + стекинг-голова по предсказанным
вероятностям осей, флагов и категорий (обучена out-of-fold)
Головы (46 млн параметров) обучены 5-фолдовой кросс-валидацией, она нужна для
стекинг-головы overall. Все пять наборов лежат в model.safetensors и усредняются на
инференсе. Веса энкодера (1,14 млрд параметров, bf16) лежат в том же файле без изменений.
Качество
Test: 2 501 отложенный документ (половина - равномерно случайные, половина - из пула
«вероятно хороших», как в обучении). run05: 200 случайных документов, размеченных
агентами Claude Opus вместо Sonnet; показывает согласие модели с другим аннотатором.
Сам Sonnet совпадает с этой разметкой на среднем QWK осей ≈ 0.89, это примерный потолок.
| test | run05 | |
|---|---|---|
| Оси, средний QWK | 0.870 | 0.847 |
QWK overall (1–4) |
0.876 | 0.847 |
Спирмен overall |
0.891 | 0.877 |
PR-AUC overall ≥ 4 |
0.75 (база 4.7%) | 0.66 (база 6%) |
Мусор: Sonnet поставил 1, overall < 1.5 |
точность 0.93, полнота 0.89 | точность 0.86, полнота 0.88 |
QWK по осям, test:
| Ось | base | lite |
|---|---|---|
cleanliness |
0.89 | 0.86 |
language_quality |
0.85 | 0.83 |
naturalness |
0.87 | 0.85 |
information_density |
0.88 | 0.85 |
factual_specificity |
0.89 | 0.86 |
educational_value |
0.87 | 0.82 |
reasoning_depth |
0.82 | 0.77 |
expertise_level |
0.87 | 0.83 |
credibility |
0.85 | 0.80 |
originality |
0.85 | 0.80 |
commercial_neutrality |
0.92 | 0.88 |
durability |
0.90 | 0.86 |
domain_depth |
0.85 | 0.80 |
Флаги, PR-AUC на test. Трём отмеченным доверять нельзя: аннотатор и сам с собой по ним не согласен.
| Флаг | base | lite |
|---|---|---|
seo_doorway |
0.99 | 0.97 |
unsafe_content |
0.94 | 0.89 |
machine_generated |
0.90 | 0.89 |
mixed_language |
0.89 | 0.89 |
official_document |
0.70 | 0.71 |
pii_present (ненадёжный) |
0.48 | 0.42 |
truncated_or_fragment (ненадёжный) |
0.47 | 0.39 |
suspected_mt (ненадёжный) |
0.36 | 0.38 |
Категории, test:
| Категория | Метрика | base | lite |
|---|---|---|---|
topic |
точность top-1 | 0.78 | 0.69 |
region |
macro-F1 | 0.82 | 0.70 |
audience |
macro-F1 | 0.75 | 0.56 |
format |
macro-F1 | 0.63 | 0.54 |
Все цифры: metrics.json.
Скорость
Время уходит на энкодер. На Apple M4 Pro (MPS, bf16) модель оценивает 1,2 документа в
секунду (2 500 токенов/с; средний документ после обрезки ~1 550 токенов). Для целых
корпусов берите lite-модель: к ней есть продакшн-скрипт с FP8 и torch.compile.
Ограничения
- Только русский язык (см. начало карточки).
- Модель подражает одному LLM-аннотатору (Claude Sonnet 5.5, промпт v6) и наследует его предвзятость; рубрика предпочитает образовательные и фактологичные тексты.
- Обучена на веб-страницах FineWeb-2; книги, код и чаты - вне распределения.
- Верхний уровень (
overall4+) редок (~2,4% случайных документов), поэтому точность в топе умеренная. Оценки - сигнал для ранжирования, а не вердикт по одному документу.
Файлы
| Файл | |
|---|---|
model.safetensors |
Энкодер (все 16 слоёв, bf16, без изменений) + 5 наборов голов кросс-валидации + стекинг-голова overall |
tokenizer.json, tokenizer_config.json |
Токенизатор энкодера |
config.json, labels.json |
Конфиг голов, имена классов, порядок текстовых статистик |
predict.py |
Инференс: командная строка и QualityScorer |
modeling.py, heuristics.py |
Код модели и 32 текстовые статистики |
metrics.json |
Метрики на validation / test / run05 |
LICENSE, NOTICE |
OpenMDW-1.1, лицензия энкодера, и его уведомления об авторстве |
Лицензия
OpenMDW-1.1, лицензия базового энкодера
nvidia/Nemotron-3-Embed-1B-BF16,
он входит сюда без изменений. Головы обучены на разметке Claude Sonnet 5.5 для текстов FineWeb-2 (ODC-By 1.0).
- Downloads last month
- 15
Model tree for krysyuk/ruTron-quality-classifier-base
Base model
mistralai/Ministral-3-3B-Base-2512