Diplomovka/perun/README.md
2026-11-04 23:46:33 +01:00

341 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Slovenská Aya: Mistral-SK a OLMo
## Scenár
Cieľom je inštrukčne dotrénovať Mistral-SK-7B a základný OLMo 2 7B na spoločnej slovenskej časti Aya Collection a porovnať ich adaptáciu. Použije sa **SFT s LoRA v LLaMA-Factory, zrýchlený Unslothom**. Jeden tréning využije **štyri H200 na jednom uzle Peruna cez DDP**.
Možnosti LoRA do návrhu scenára:
- **LoRA (Low-Rank Adaptation)**
- **QLoRA (Quantized Low-Rank Adaptation)**
- **rsLoRA (Rank-Stabilized LoRA)**
- **DoRA (Weight-Decomposed Low-Rank Adaptation)**
## Prehľad súborov
| Súbor | Úloha |
| --- | --- |
| `configs/mistral.yaml` | Základný tréningový config pre `slovak-nlp/mistral-sk-7b`. |
| `configs/olmo.yaml` | Základný tréningový config pre `allenai/OLMo-2-1124-7B`. |
| `scripts/prepare_data.py` | Načítanie, čistenie, deduplikácia a rozdelenie dát. |
| `scripts/train.py` | Spustenie LLaMA-Factory podľa zvoleného configu. |
| `scripts/evaluate.py` | Loss, perplexita, generovanie a slovný F1 / presná zhoda na eval alebo test množine. |
Balík má spolu šesť súborov. `evaluate.py` odvodí nastavenia z rovnakého modelového YAML a konkrétnu použitú konfiguráciu uloží až k výsledkom.
Poradie používania je **príprava dát → tréning → vyhodnotenie**. Príprava dát sa vykoná raz pre oba modely. Tréning sa spustí samostatne pre každý model alebo experiment a následne sa vyhodnotí vytvorený adaptér. Model a hyperparametre sa nastavujú v YAML; Python skripty vykonávajú jednotlivé kroky.
## Spoločný dataset do 4 096 tokenov a nastavenie H200
Oba modely používajú **`cutoff_len: 4096`**. Limit zahŕňa celú SFT sekvenciu: systémový text Alpaca, inštrukciu a prípadný vstup, celú referenčnú odpoveď, EOS a koncové oddeľovače. Spúšťací skript kontroluje pôvodnú kontextovú kapacitu modelu podľa `cutoff_len`.
`prepare_data.py` si načíta oba YAML configy a ich presné tokenizéry. **Celý pár vyradí, ak prekročí limit čo i len pri jednom modeli.** Všetky ponechané príklady zapíše bez orezania. Filtrovanie prebehne pred deduplikáciou a spoločným rozdelením na train/eval/test, takže oba modely dostanú rovnaké príklady. Inštrukcia a pole `input` sa spájajú rovnako ako v Alpaca konvertore LLaMA-Factory.
Nastavenie jedného tréningu:
- štyri H200 cez DDP, `bf16: true`, `use_unsloth: true`, `use_unsloth_gc: true`, bez kvantizácie;
- batch 8 na GPU, akumulácia 1: **4 × 8 × 1 = efektívny batch 32**;
- eval loss s batchom 8 na GPU, záverečné generovanie po jednom príklade;
- LoRA rank 16, alpha 32, dropout 0, projekcie attention aj MLP;
- jedna epocha, AdamW, cosine scheduler, warmup 8 %, clipping gradientov 0,5;
- loss iba z odpovedí, bez packingu, dynamický padding na dĺžku aktuálnej dávky;
- validácia/checkpoint každých 1 000 optimizer krokov, výber podľa najnižšieho loss, limit checkpointov 2.
Spúšťač overuje, že dáta majú záznam o dĺžkovom filtrovaní pre daný model, revíziu, šablónu a limit. Kontrola pri tokenizácii tiež zastaví beh, ak by predspracovanie chcelo orezať vstup alebo odpoveď. Konfigurácia načítaného základného modelu sa uloží do `adapter/base_model_config.json`.
LR `0.0001` pri Mistrale nadväzuje na 300k experiment; pri OLMo je východiskový kandidát. Zmenené nastavenia stále treba overiť podľa eval dát. OLMo je základný model pre vlastné SFT a jeho karta uvádza angličtinu.
## Prostredie na Perunovi
Na spustenie sa používa kompatibilné GPU prostredie s LLaMA-Factory, Unsloth, Unsloth Zoo, PyTorch a CUDA pre H200. LLaMA-Factory používa aj `datasets`, `huggingface_hub` a `PyYAML`; generatívna evaluácia potrebuje `rouge-chinese`, `jieba` a `nltk`. Python má byť aspoň 3.11 podľa aktuálnych požiadaviek LLaMA-Factory. Dĺžkový filter pri príprave dát používa Transformers a PyYAML a načíta oba tokenizéry; váhy modelov na túto CPU úlohu nepotrebuje.
### Požiadavky a inštalácia prostredí
Priečinok `requirements` obsahuje verzie odvodené z exportu Hrušky.
| Súbor | Prostredie |
| --- | --- |
| `requirements/training.txt` | Python 3.11.16; LLaMA-Factory, Unsloth, PyTorch 2.6.0 s CUDA 12.4 a generatívna evaluácia. |
| `requirements/lm-eval.txt` | Python 3.11.16; lm-evaluation-harness, Transformers 4.48.2 a PyTorch 2.6.0 s CUDA 12.4. |
| `requirements/skbench.txt` | Python 3.13.17; export 308 balíkov SK-bench vrátane vLLM 0.28.0, Transformers 5.12.1 a PyTorch 2.13.0. |
| `requirements/skbench/pyproject.toml` a `uv.lock` | Pôvodné závislosti a uzamknuté verzie SK-bench pre obnovenie cez uv. |
Git závislosti LLaMA-Factory, lm-eval a lighteval sú pripnuté na pôvodné commity. Neplatná lokálna cesta k pip bola v tréningovom a lm-eval exporte nahradená verziou `pip==26.2.1` z Condy. Výpočtové knižnice zachovávajú pôvodné verzie.
Do tréningových požiadaviek boli doplnené `jieba==0.42.1`, `rouge-chinese==1.0.3`, `nltk==3.10.3` a jeho závislosti `joblib==1.6.0` a `defusedxml==0.7.1` pre generatívnu evaluáciu. Doplnený je aj `torchao==0.13.0`, pretože ho vyžaduje zachytená verzia Unsloth Zoo a export ho neobsahoval. Táto verzia TorchAO podporuje Python API s PyTorch 2.6; jej natívne C++ rozšírenia sú určené pre PyTorch 2.8. Scenár používa LoRA bez kvantizácie TorchAO.
Pre tréning je `setuptools` upravený na `80.10.2`, rovnako ako vo funkčnom SK-bench exporte. Knižnica jieba používa `pkg_resources`, ktorý bol zo setuptools 82 odstránený. Tréningové a benchmarkové verzie ostatných zachytených balíkov sa nemenia.
Ide o požiadavky pripravené z funkčných prostredí Hrušky a uvedených doplnení. Čistá inštalácia a výpočet na H200 sa overia na Perunovi.
#### Tréning a evaluácia na pripravených Aya dátach
Nasledujúce príkazy sa zadávajú z koreňa balíka v prostredí s dostupnou Condou a Gitom. PyTorch a xformers sa najprv nainštalujú z rovnakého oficiálneho CUDA 12.4 indexu:
```bash
conda create -n aya_train_perun python=3.11.16 pip=26.2.1 -y
conda activate aya_train_perun
python -m pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 xformers==0.0.29.post3 \
--index-url https://download.pytorch.org/whl/cu124
python -m pip install -r requirements/training.txt
python -m pip check
```
Na pridelenom GPU uzle sa overia importy, CUDA a BF16:
```bash
python -c 'import unsloth, torch, jieba, nltk; from rouge_chinese import Rouge; assert torch.cuda.is_available(); assert torch.cuda.is_bf16_supported(); print("GPU:", torch.cuda.get_device_name(0)); print("Viditelne GPU:", torch.cuda.device_count()); print("CUDA:", torch.version.cuda)'
```
Príprava dát, tréning aj `scripts/evaluate.py` sa potom spúšťajú v `aya_train_perun` podľa ďalších častí dokumentácie. Overené opravy generovania z Titanu sú súčasťou `scripts/train.py`.
#### lm-evaluation-harness
Príkazy sa zadávajú z koreňa balíka:
```bash
conda create -n aya_lmeval_perun python=3.11.16 pip=26.2.1 -y
conda activate aya_lmeval_perun
python -m pip install torch==2.6.0 --index-url https://download.pytorch.org/whl/cu124
python -m pip install -r requirements/lm-eval.txt
python -m pip check
lm_eval --help
```
Súbor inštaluje framework pri revízii `6d2abda4fd171e68a8789330c4149e37c1ca0bda`. Vlastné slovenské úlohy, zoznam benchmarkov a evaluačné dáta sa prenášajú samostatne; požiadavky obsahujú Python knižnice.
#### SK-bench
Na obnovenie SK-bench sa používa uv 0.13.5 a zdrojová kópia projektu z Hrušky pri revízii `15823bbcc2d995e69441fcb7d34abb61bd8180c5`. Súbory `pyproject.toml` a `uv.lock` sa skopírujú z tohto balíka do koreňa zdrojovej kópie SK-bench. Ak je uv potrebné doplniť, nainštaluje sa cez `python -m pip install uv==0.13.5` v existujúcom Python prostredí; vlastné závislosti SK-bench sa vytvoria v jeho samostatnej `.venv`.
Z koreňa balíka, pri zdrojovej kópii SK-bench uloženej v `../sk-bench`:
```bash
cp requirements/skbench/pyproject.toml requirements/skbench/uv.lock ../sk-bench/
cd ../sk-bench
uv sync --locked --no-default-groups --python 3.13.17
uv pip check --python .venv/bin/python
uv run --locked python -c 'import torch, vllm, transformers; print(torch.__version__, vllm.__version__, transformers.__version__)'
```
Základná uzamknutá zostava zodpovedá všetkým 308 balíkom exportovaným z Hrušky. Skupiny `dev` a `hpc` sa pri tomto obnovení nepridávajú. `requirements/skbench.txt` uchováva rovnaké konkrétne verzie v pip formáte; pri používaní projektu cez uv sa vychádza z jeho `uv.lock`.
SK-bench používa CUDA 13; pri jeho prenose sa na pridelenom GPU uzle overí ovládač cez `nvidia-smi` a dostupnosť CUDA v PyTorchi. Pôvodný export Hrušky uvádza ovládač 580.178.04.
Zdroje: [PyTorch CUDA zostavy](https://pytorch.org/get-started/previous-versions/#v260), [kompatibilita TorchAO](https://github.com/pytorch/ao/issues/2919), [závislosti Unsloth Zoo 2026.8.16](https://pypi.org/pypi/unsloth-zoo/2026.8.16/json), [zmeny setuptools](https://setuptools.pypa.io/en/latest/history.html#v82-0-0), [uzamknuté prostredia uv](https://docs.astral.sh/uv/concepts/projects/sync/).
### Odosielanie úloh cez Slurm
Priame Python príkazy sú určené pre už pridelený výpočtový uzol. Z prihlasovacieho uzla sa úlohy odosielajú cez `sbatch --wrap`. Príkazy sa zadávajú z koreňa balíka s aktivovaným Python prostredím; tento priečinok sa použije aj pri výpočte.
Pred odoslaním sa v rovnakom termináli nastavia projektový účet a QoS. Hodnoty `NAZOV_PROJEKTU` a `PRIDELENE_QOS` sa nahradia údajmi prideleného projektu:
```bash
AYA_ACCOUNT="NAZOV_PROJEKTU"
AYA_QOS="PRIDELENE_QOS"
```
Na Perunovi sa pre výpočet používa pracovný priečinok na SCRATCH. Dáta a výsledky určené na uchovanie sa po výpočte skopírujú do projektového úložiska. Parameter `--time` určuje maximálny čas úlohy.
## 1. Príprava dát
Príkazy sa spúšťajú z koreňa balíka s aktivovaným Python prostredím. Príprava dát používa CPU; na Perunovi sa vykonáva na výpočtovom uzle s pridelenými CPU.
```bash
python scripts/prepare_data.py --output-dir data/aya_slovak_4096
```
Odoslanie prípravy dát ako CPU úlohy:
```bash
sbatch --job-name=aya_prepare \
--account="$AYA_ACCOUNT" --qos="$AYA_QOS" \
--partition=cpu_short --nodes=1 --ntasks=1 \
--cpus-per-task=8 --mem=64G --time=12:00:00 \
--output=%x_%j.log \
--wrap='python -u scripts/prepare_data.py --output-dir data/aya_slovak_4096'
```
Tréningové úlohy sa odosielajú po úspešnom dokončení prípravy dát.
Výstupný priečinok prípravy dát musí byť nový alebo prázdny.
### `prepare_data.py`
Jeho vstupom sú slovenské zdrojové dáta Aya Collection a obe modelové konfigurácie. Používa CPU a tokenizéry Mistralu a OLMo. Výsledkom je jeden spoločný dátový balík pre oba modely.
1. Načíta slovenský split `train` datasetu `CohereLabs/aya_collection_language_split` pri pevnej revízii. Zdroj číta postupne.
2. Vyradí neplatné riadky, prázdne zadania a prázdne odpovede. Polia `inputs` a `targets` prevedie na `instruction/input/output` a odstráni okrajové medzery.
3. Pomocou oboch tokenizérov zmeria celú SFT sekvenciu vrátane formátu Alpaca a odpovede. Ak príklad prekročí `cutoff_len` pri ktoromkoľvek modeli, vyradí celý pár.
4. Odstráni duplicitné normalizované páry zadania a odpovede. Rovnaké normalizované zadanie s rôznymi odpoveďami ponechá ako jednu skupinu.
5. Podľa seedu, predvolene `42`, vytvorí train/eval/test. Celá skupina zadania zostane v jednej množine. Do eval a test vyberie najviac 1 000 príkladov na každú množinu; ostatné ponechané príklady patria do train.
6. Uloží dáta vo formáte, ktorý následne načíta LLaMA-Factory.
Príklad uloženého riadka:
```json
{"instruction":"Aké je hlavné mesto Slovenska?","input":"","output":"Bratislava."}
```
Výstupy v `data/aya_slovak_4096`:
| Súbor | Obsah a použitie |
| --- | --- |
| `train.jsonl` | Príklady na učenie LoRA parametrov. |
| `eval.jsonl` | Validačné príklady na sledovanie loss a ladenie. |
| `test.jsonl` | Odložené príklady na záverečné vyhodnotenie. |
| `dataset_info.json` | Registrácia súborov pod názvami `aya_train`, `aya_eval`, `aya_test` a mapovanie ich stĺpcov pre LLaMA-Factory. |
| `manifest.json` | Zdrojová revízia, seed, skutočné počty, nastavenia dĺžkového filtra a kontrolné súčty súborov. |
| `*.metadata.jsonl` | Pôvod a identifikácia príkladov v rovnakom poradí ako v príslušnom dátovom súbore. |
| `excluded_long.jsonl` | Identifikácia a namerané dĺžky vyradených dlhých príkladov. |
Na deduplikáciu a rozdelenie dát používa dočasnú SQLite databázu. Po úspešnom dokončení ju odstráni; prepínač `--keep-db` ju ponechá. Počty eval a test príkladov možno nastaviť cez `--eval-size` a `--test-size`, seed cez `--seed`. Vlastný vstupný JSONL možno načítať cez `--local-jsonl`.
Oba modely potom používajú tie isté výsledné súbory. Každý model si ich pri tréningu tokenizuje svojím tokenizérom. LLaMA-Factory používa pripravené `aya_train` a `aya_eval` bez ďalšieho automatického delenia cez `val_size`.
## 2. Tréning
### `train.py`
Je to spúšťač tréningu v LLaMA-Factory. Ako vstup dostane modelový YAML a už pripravený dátový balík.
1. Načíta model, revíziu, cesty k dátam, LoRA parametre, learning rate, batch a ostatné nastavenia z YAML.
2. Skontroluje existenciu dát, ich kontrolné súčty a zhodu dĺžkového filtra s použitým modelom, revíziou, šablónou a limitom.
3. Uloží presnú použitú konfiguráciu a záznam behu.
4. Cez `torchrun` spustí štyri procesy DDP a v každom zavolá tréning LLaMA-Factory.
Pri aktuálnych konfiguráciách prebieha SFT s LoRA, Unslothom a BF16. Základné váhy modelu sú zmrazené a učia sa LoRA parametre. Loss sa počíta z odpovedí. LLaMA-Factory každých 1 000 optimizer krokov vykoná validáciu a uloží checkpoint; na konci načíta checkpoint s najnižším eval loss.
Kontrola pomocou `--dry-run` sa vykonáva po príprave dát. Overí základné nastavenia a dátové súbory bez načítania váh a bez spustenia tréningu.
Kontrola konfigurácie a pripravených dát bez spustenia tréningu:
```bash
python scripts/train.py configs/mistral.yaml --dry-run
python scripts/train.py configs/olmo.yaml --dry-run
```
Každý tréning sa spúšťa samostatne v prostredí so štyrmi dostupnými GPU:
```bash
python scripts/train.py configs/mistral.yaml
python scripts/train.py configs/olmo.yaml
```
Odoslanie tréningov cez Slurm na štyri H200. Nasledujúci príklad spustí modely postupne; `afterok` umožní spustenie OLMo po úspešnom dokončení Mistralu:
```bash
AYA_MISTRAL_JOB=$(sbatch --parsable --job-name=aya_mistral \
--account="$AYA_ACCOUNT" --qos="$AYA_QOS" \
--partition=gpu_long --nodes=1 --ntasks=1 --gres=gpu:4 \
--cpus-per-task=32 --mem=256G --time=2-00:00:00 \
--output=%x_%j.log \
--wrap='python -u scripts/train.py configs/mistral.yaml')
sbatch --job-name=aya_olmo \
--dependency="afterok:$AYA_MISTRAL_JOB" \
--account="$AYA_ACCOUNT" --qos="$AYA_QOS" \
--partition=gpu_long --nodes=1 --ntasks=1 --gres=gpu:4 \
--cpus-per-task=32 --mem=256G --time=2-00:00:00 \
--output=%x_%j.log \
--wrap='python -u scripts/train.py configs/olmo.yaml'
```
Jedna úloha Slurmu spustí `train.py`, ktorý vytvorí štyri procesy DDP. Parametre `--run-dir` a `--resume` sa pri odosielaní uvádzajú v Python príkaze vo vnútri `--wrap`.
Každý proces DDP má na pridelenej GPU kópiu modelu a spracúva inú časť dávky. Gradienty sa synchronizujú medzi GPU, takže štyri GPU vykonávajú jeden spoločný tréning. Pri batchi 8 na GPU a akumulácii 1 je efektívny batch **4 × 8 × 1 = 32**. Každý proces importuje Unsloth pred Transformers a LLaMA-Factory.
Výsledkom tréningu je **LoRA adaptér**, ktorý sa používa spolu so základným modelom. Pre Mistral sa uloží do `runs/mistral/adapter`, pre OLMo do `runs/olmo/adapter`. Checkpointy sú v podpriečinkoch adaptéra.
V nadradenom priečinku behu zostanú:
- `train.log` – priebeh a hlásenia tréningu;
- `used_config.yaml` – presné nastavenia odovzdané LLaMA-Factory;
- `run.json` – záznam behu, efektívny batch a identifikácia použitých dát.
## 3. Vyhodnotenie na eval dátach
### `evaluate.py`
Ako vstup dostane rovnaký modelový YAML, pripravené dáta a dotrénovaný adaptér. Načíta základný model spolu s adaptérom a vykoná dve samostatné fázy na jednej GPU:
1. **Eval loss a perplexita:** model spracuje zadania s pôvodnými referenčnými odpoveďami. Vypočíta sa strata pri predpovedaní odpovedí a z nej perplexita.
2. **Generovanie a porovnanie odpovedí:** model dostane zadania a vytvorí vlastné odpovede. Skript ich porovná s úplnými referenciami pomocou slovného F1 a normalizovanej presnej zhody.
Predvolene sa vyhodnotí pripravená množina `eval.jsonl`:
```bash
python scripts/evaluate.py configs/mistral.yaml --output-dir results/mistral_eval
python scripts/evaluate.py configs/olmo.yaml --output-dir results/olmo_eval
```
Po úspešnom dokončení príslušného tréningu sa vyhodnotenie odošle ako úloha s jednou GPU:
```bash
sbatch --job-name=aya_mistral_eval \
--account="$AYA_ACCOUNT" --qos="$AYA_QOS" \
--partition=gpu_short --nodes=1 --ntasks=1 --gres=gpu:1 \
--cpus-per-task=8 --mem=64G --time=12:00:00 \
--output=%x_%j.log \
--wrap='python -u scripts/evaluate.py configs/mistral.yaml --output-dir results/mistral_eval'
sbatch --job-name=aya_olmo_eval \
--account="$AYA_ACCOUNT" --qos="$AYA_QOS" \
--partition=gpu_short --nodes=1 --ntasks=1 --gres=gpu:1 \
--cpus-per-task=8 --mem=64G --time=12:00:00 \
--output=%x_%j.log \
--wrap='python -u scripts/evaluate.py configs/olmo.yaml --output-dir results/olmo_eval'
```
Pre vyhodnotenie test množiny sa do Python príkazu vo vnútri `--wrap` pridá `--split test` a zvolí sa nový výstupný priečinok, napríklad `results/mistral_test`.
V priečinku behu sa uchovávajú pôvodné súbory `run.json` a `used_config.yaml`. Vyhodnotenie porovná manifest pripravených dát so záznamom z tréningu; iné rozdelenie alebo iný dataset odmietne. Rovnaká kontrola platí pre eval aj test.
Adaptér z iného behu sa určí parametrom `--adapter runs/mistral_dalsi/adapter`. Predvolene sa použije adaptér z `output_dir` v modelovom YAML. Prepínač `--dry-run` overí pripravené vstupy a zobrazí odvodené evaluačné nastavenia.
Generovanie je greedy, s jedným lúčom a limitom najviac 256 nových tokenov. Limit možno zmeniť cez `--max-new-tokens`. Pri každom vstupe sa počet nových tokenov obmedzí aj zostávajúcim miestom do 4 096 tokenov. Celý vstup a úplná referencia zostávajú zachované; prípadné zníženie limitu sa zapíše do logu.
Skript zapisuje výsledky do priečinka z `--output-dir`:
| Súbor | Obsah súboru |
| --- | --- |
| `summary.json` | Hlavný súhrn: eval loss, perplexita, F1, presná zhoda a počet vyhodnotených príkladov. |
| `loss/eval_results.json` | Výsledky samostatného výpočtu eval loss v LLaMA-Factory. |
| `generation/generated_predictions.jsonl` | Vygenerované odpovede modelu. |
| `scores/per_sample.jsonl` | Predikcia, úplná referencia a skóre pre každý príklad. |
| `scores/metrics.json` | Podrobné súhrny metrík aj rozdelenie podľa typu úlohy. |
| `evaluation.json` | Zvolený split, modelový config, adaptér a stav vyhodnotenia. |
Pri výsledkoch zostanú aj logy a konkrétne použité konfigurácie oboch evaluačných fáz. Pre vyhodnotenie možno ako vstupný config použiť aj `runs/mistral/used_config.yaml` alebo OLMo ekvivalent.
Eval slúži na ladenie a výber checkpointu. Po ukončení výberu nastavení sa vyhodnotí odložená testovacia množina a výsledky sa uložia do nového výstupného priečinka:
```bash
python scripts/evaluate.py configs/mistral.yaml --split test --output-dir results/mistral_test
python scripts/evaluate.py configs/olmo.yaml --split test --output-dir results/olmo_test
```
Externé lm-eval a SK-bench majú vlastné spúšťanie. Tento balík obsahuje prípravu dát, tréning a vyhodnotenie na pripravených eval/test dátach.
### Sledovanie odoslaných úloh
```bash
squeue -u "$USER"
```
Výstup úlohy sa zapisuje do logu v pracovnom priečinku. V názve `%x_%j.log` sa `%x` nahradí názvom úlohy a `%j` jej číslom. Pre prípravu dát s číslom úlohy 12345:
```bash
tail -f aya_prepare_12345.log
```