Датасеты для LLM: токенизация, фильтрация, шардирование

Цель страницы. Дать практический пайплайн подготовки корпусов под обучение/дообучение LLM: от сбора и нормализации текста до токенизации, фильтрации качества/языка, дедупликации и шардирования для быстрого чтения с диска/объектного хранилища.

Карта процесса (сверху вниз)

  1. Сбор и нормализация: HTML→текст, очистка артефактов.
  2. Определение языка: отфильтровать нецелевые языки.
  3. Фильтрация качества: длины, доля небуквенных символов, перплексия, стоп‑листы.
  4. PII и лицензии: базовая очистка персональных данных, учёт лицензий.
  5. Дедупликация: точная (hash) и near‑dup (MinHash/LSH).
  6. Токенизация: обучение/подбор токенайзера и массовая токенизация.
  7. Шардирование/стриминг: упаковка в WebDataset/MDS/JSONL‑шарды, индексы и манифесты.
  8. Сплиты и версии: train/val/test, фиксированные сиды, контроль утечек между сплитами.
  9. Каталог и мониторинг: README/manifest, счётчики токенов, отчёты качества.

Библиотеки, которые особенно пригодятся: Hugging Face Datasets (процессинг/стриминг), SentencePiece/tokenizers (токенизация), Trafilatura (HTML→текст), KenLM (перплексия), datasketch (MinHash), WebDataset/MDS (шарды).

Формат данных (рекомендуемая схема)

**JSONL (1 объект = 1 документ/сэмпл) Минимальный набор полей:

{"id":"...", "text":"...", "lang":"ru", "source":"commoncrawl", "url":"...", 
 "license":"cc-by-sa", "timestamp":"2024-10-05", 
 "quality":{"len_chars":1234,"nonalpha_ratio":0.06,"perplexity":163.2},
 "hash":{"xxh3":"be1d..."},
 "split":"train"}

JSON Lines подходит для потоковой обработки и совместим с datasets.load_dataset("json", streaming=True). Метод Dataset.to_json() по умолчанию пишет JSONL (lines=True). Сбор и нормализация текста - Из веба/архивов: Common Crawl (WARC/WET), далее извлечение основного текста без мусора.

  • Извлечение текста: trafilatura показывает стабильные результаты на выжимке текста из HTML и удобна как CLI/библиотека.

Пример (Python):

from trafilatura import fetch_url, extract
html = fetch_url("https://example.com")
text = extract(html, favor_precision=True) # основной текст без boilerplate

Языковая фильтрация

  • fastText LID‑176 / LID‑218 — лёгкая и быстрая идентификация языка (176/217 языков).
  • CLD3 — нейросетевой детектор языка с биндингами для Python. Оба подхода широко используются в пайплайнах очистки веб‑корпусов.

Пример (fastText):

import fasttext
lid = fasttext.load_model("lid.176.bin")
lang, conf = lid.predict("Пример текста", k=1)

Фильтрация качества (включая перплексию)

  • Правила/эвристики: минимальная/максимальная длина, доля небуквенных символов, повторяющиеся паттерны, стоп‑домены.
  • Перплексия (KenLM): отбраковка «шумного» или «непохожего» на эталонный стиль текста (напр., Википедия) — классический шаг в CCNet‑подобных пайплайнах.

Пример (KenLM, Python):

import kenlm, math
lm = kenlm.Model("ru.arpa") # LM на чистом корпусе-референсе
def ppl(s): 
 ll = sum(score for score,_,_,_ in lm.full_scores(s, bos=True, eos=True))
 n = len(s.split())
 return math.exp(-ll / max(1,n))
``` **PII и лицензии**

- Для минимальной защиты персональных данных примените **Microsoft Presidio** (анализатор PII с набором готовых распознавателей), затем сохраните флаги/лог.
- Учитывайте **лицензию** источника (CC‑BY‑SA/CC‑BY/проprietary) и переносите её в метаданные записи.

**Дедупликация: точная и near‑duplicate**

- **Точная**: нормализованный текст → быстрый хеш (например, **xxHash/XXH3**) → удаление дублей.[](https://xxhash.com/?utm_source=chatgpt.com)
- **Почти дубликаты**: **MinHash + LSH** (библиотека datasketch) — вылавливает похожие тексты (по Жаккару), что критично для больших веб‑корпусов.[](https://ekzhu.com/datasketch/documentation.html?utm_source=chatgpt.com)

**Код‑набросок:**

import xxhash from datasketch import MinHash, MinHashLSH def exact_key(text): return xxhash.xxh3_128_hexdigest(text.encode("utf-8")) def shingles(text, n=5): tokens = text.split() return {" ".join(tokens[i:i+n]) for i in range(len(tokens)-n+1)} m = MinHash(num_perm=128) for sh in shingles(text): m.update(sh.encode("utf-8")) lsh = MinHashLSH(threshold=0.8, num_perm=128) lsh.insert(exact_key(text), m)


**Токенизация: выбор и массовая обработка**

- **SentencePiece** (Unigram/BPE) — стандарт для обучения собственных токенайзеров под RU/EN/мультиязык.
- **Hugging Face tokenizers/Transformers** — быстрые реализации и готовые пайплайны батч‑токенизации.[](https://github.com/google/sentencepiece?utm_source=chatgpt.com)

**Обучение SentencePiece (CLI):**

spm_train --input=corpus.txt --model_prefix=llm_spm --vocab_size=50000 --model_type=unigram --character_coverage=0.9995 --input_sentence_size=10000000 --shuffle_input_sentence=true --user_defined_symbols=[PAD],[BOS],[EOS]


**Массовая токенизация (Datasets → batched map):**

from datasets import load_dataset from transformers import AutoTokenizer ds = load_dataset("json", data_files={"train":"data.jsonl"}, streaming=True) tok = AutoTokenizer.from_pretrained("./llm_spm") # ваш SPM через HF обёртку def encode(batch): out = tok(batch["text"], truncation=True, max_length=4096) out["len"] = [len(x) for x in out["input_ids"]] return out tokenized = ds["train"].map(encode, batched=True)


**Шардирование и стриминг под обучение**

### Вариант A: WebDataset (tar‑шарды)

- Файлы одной записи делят общий **basename**; шардовка — data-{000000..000999}.tar, удобно для POSIX/объектных стораджей и последовательного I/O.[](https://github.com/webdataset/webdataset?utm_source=chatgpt.com)
- Плюсы: простые tar, поддержка стриминга из URL/объектного хранилища.[](https://pypi.org/project/webdataset/0.1.25/?utm_source=chatgpt.com)

**Пример записи токенов в tar‑шарды (схема):**

Сериализуйте токены и метаданные в .npz/.json, соберите в tar через webdataset

Имя образца: 12345.txt / 12345.json -> data-000123.tar


### Вариант B: Mosaic MDS (StreamingDataset)

Формат **MDS** ориентирован на высокую пропускную способность и быстрый «рандомный доступ» к сэмплам; удобно для долгих тренировок с возобновлением.

### Вариант C: JSONL/Parquet + HF Datasets (streaming) 

load\_dataset(..., streaming=True) позволяет работать без полного скачивания, обрабатывая данные на лету.

### Практика размеров 

- Шард 0.5–2 ГБ обычно даёт хороший баланс между размером файлов и параллелизмом воркеров.
- Храните **manifest** набора шардов и **снимок версии** (commit + сиды).

**Дополнительно:** HF Hub поддерживает WebDataset‑артефакты и инструкции по использованию.

**Сплиты, версии и защита от утечек**

- Разбейте источники **до** токенизации (train/val/test) и **контролируйте утечки**: никакие точные/near‑дубликаты не должны попадать в разные сплиты.
- Фиксируйте **сид генератора**, версии токенайзера/фильтров, список дат Common Crawl/внешних корпусов.

**Рецепт «как в CCNet, но для RU/EN»**

1. Взять сырые тексты (WET/собственные коллекции) → извлечь body‑текст (Trafilatura).
2. Языковая фильтрация (fastText/CLD3).
3. Качество: эвристики + перплексия KenLM (на референс‑корпусе).
4. Дедуп (xxHash) + near‑dup (MinHash/LSH).
5. Обучить/подобрать токенайзер (SentencePiece), токенизировать партиями.
6. Записать в шарды (WebDataset/MDS), подготовить manifest/README.
7. Прогнать sanity‑тесты качества на подвыборке. Подход вдохновлён оригинальным **CCNet** (дедуп, LID, перплексия‑фильтр под референс).

**Траблшутинг**

- **Медленный I/O / затыки диска.** Проверьте, что чтение идёт **крупными последовательными блоками** (тар‑шарды/WebDataset) и включен **prefetch** в DataLoader.
- **Сильно «шумный» корпус после чистки.** Ужесточите пороги перплексии, добавьте эвристику по доле небуквенных символов и стоп‑домены источников.
- **Смешение языков.** Комбинируйте fastText и CLD3; фильтруйте по уверенности/доле языка в документе.
- **Дубликаты в валидации.** Добавьте проверку hash/MinHash **на уровне всех сплитов**, а не только внутри train.

**Как это запускать в cloudcompute.ru**

- Используйте шаблоны из раздела **/solutions/templates/**:
 – «**Data Prep (RU/EN)**»: Jupyter/SSH‑образ с datasets, trafilatura, fasttext, pycld3, kenlm, datasketch, webdataset, mosaicml‑streaming.
 – «**Tokenizer**»: окружение с sentencepiece и transformers для обучения токенайзера и массовой токенизации.
- Для хранения и переноса см. **/solutions/storage-data/** (кэш, чекпоинты, перенос датасетов) и **/solutions/llm-training/distributed-io/**.
- Для контроля качества и метрик — **/solutions/llm-training/eval/**.

**Связанные страницы**

[База по обучению](/solutions/llm-training/)

[Смешанная точность](/solutions/llm-training/mixed-precision/)

Память/скорость: [/solutions/llm-training/memory-opt/](/solutions/llm-training/memory-opt/), [/solutions/llm-training/optimizers/](/solutions/llm-training/optimizers/)

I/O и хранение: [/solutions/llm-training/distributed-io/](/solutions/llm-training/distributed-io/), [/solutions/storage-data/](/solutions/storage-data/)

[Оценка качества](/solutions/llm-training/eval/)

Готовы запустить?

Запустить GPU-сервер