# 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 ```