Решения

Датасеты для 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) → удаление дублей.
  • Почти дубликаты: MinHash + LSH (библиотека datasketch) — вылавливает похожие тексты (по Жаккару), что критично для больших веб‑корпусов.

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

				
					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 — быстрые реализации и готовые пайплайны батч‑токенизации.

Обучение 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.
  • Плюсы: простые tar, поддержка стриминга из URL/объектного хранилища.

Пример записи токенов в 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/.