This commit is contained in:
Jakub Schwarc 2026-10-25 00:59:11 +02:00
parent 67061cf373
commit ac0a0e386f
42 changed files with 12 additions and 21341 deletions

View File

@ -871,7 +871,7 @@ Presné hodnoty LR, finálne aj minimálne eval loss, kroky, training loss a run
# Hruška – hľadanie learning rate na 300k Aya príkladoch # Hruška – hľadanie learning rate na 300k Aya príkladoch
Po skúšobnom hľadaní LR pomocou Optuny na 30k príkladoch nasledovalo **overenie šiestich ručne zvolených hodnôt LR na väčšej, fixnej 300k vzorke**. Cieľom bolo nájsť vhodné východiskové nastavenie pre plánovaný tréning na celej slovenskej Aya množine na **Perune**. Tento 300k experiment ešte nebol tréningom na celej množine. Po skúšobnom hľadaní LR pomocou Optuny na 30k príkladoch nasledovalo **overenie šiestich ručne zvolených hodnôt LR na väčšej, fixnej 300k vzorke**. Cieľom bolo nájsť vhodné východiskové nastavenie pre plánovaný tréning na celej slovenskej Aya množine na **Perune**.
Podklady k tréningu a následným benchmarkom vybraného modelu sú v priečinku [aya_300k_lr_experiments/](aya_300k_lr_experiments/). Postup opakovania a technické podmienky sú v [reproduction.md](aya_300k_lr_experiments/reproduction.md). Podklady k tréningu a následným benchmarkom vybraného modelu sú v priečinku [aya_300k_lr_experiments/](aya_300k_lr_experiments/). Postup opakovania a technické podmienky sú v [reproduction.md](aya_300k_lr_experiments/reproduction.md).
@ -898,7 +898,7 @@ Zo slovenského `train` splitu `CohereLabs/aya_collection_language_split` sa vyf
| Evaluácia / logovanie | každých 1000 / 10 krokov + finálna evaluácia | | Evaluácia / logovanie | každých 1000 / 10 krokov + finálna evaluácia |
| Seed | 42 | | Seed | 42 |
Pôvodné [konfigurácie](aya_300k_lr_experiments/configs/) a [tréningové logy](aya_300k_lr_experiments/logs/) sú zachované. Konfigurácie sa líšia hodnotou LR, výstupnou cestou a prevádzkovým príznakom `overwrite_output_dir`. Archív neobsahuje checksum vstupného datasetu ani identifikátory validačných vzoriek; úplnú identitu dát preto nemožno nezávisle overiť iba z uložených konfigurácií. Pôvodné [konfigurácie](aya_300k_lr_experiments/configs/) a [tréningové logy](aya_300k_lr_experiments/logs/) sú zachované.
## Výsledky a výber LR pre ďalší tréning ## Výsledky a výber LR pre ďalší tréning
@ -913,34 +913,26 @@ Prvá séria obsahovala LR `0.00018`, `0.00020` a `0.00023`. Po jej vyhodnotení
| 0.00020 | 0.897669 | 0.897507 | 18 000 | | 0.00020 | 0.897669 | 0.897507 | 18 000 |
| 0.00023 | 0.903236 | 0.903193 | 18 000 | | 0.00023 | 0.903236 | 0.903193 | 18 000 |
**LR `0.00010` bol vybraný preto, že dosiahol najnižší finálny validačný loss zo všetkých šiestich 300k behov: `0.87261962890625`.** Rozdiel oproti LR `0.00008` je približne 0.002597. Ide o najlepší bodový výsledok v tejto sérii; neprebehli opakovania s viacerými seedmi ani overenie optimálneho LR na celej Aya množine. Pre Perun slúži ako východisko. **LR `0.00010` bol vybraný preto, že dosiahol najnižší finálny validačný loss zo všetkých šiestich 300k behov: `0.87261962890625`.** Rozdiel oproti LR `0.00008` je približne 0.002597. Ide o najlepší bodový výsledok v tejto sérii.
Na 30k skúške bol najlepší skúšaný LR `0.0002`. Výsledky 300k série preto ukazujú význam overenia LR na väčšej vzorke. Absolútne hodnoty eval loss medzi 30k, 100k a 300k sériami nie sú priamym porovnaním kvality modelov, keďže nemožno predpokladať zhodné validačné vzorky. Na 30k skúške bol najlepší skúšaný LR `0.0002`. Výsledky 300k série preto ukazujú význam overenia LR na väčšej vzorke.
Presné údaje sú v [pôvodnom LR súhrne](aya_300k_lr_experiments/results/aya_300k_lr_summary.csv), [rozšírenom súhrne behov](aya_300k_lr_experiments/results/training_run_summary.csv) a [histórii validačného loss](aya_300k_lr_experiments/results/eval_loss_history.csv). Presné údaje sú v [pôvodnom LR súhrne](aya_300k_lr_experiments/results/aya_300k_lr_summary.csv), [rozšírenom súhrne behov](aya_300k_lr_experiments/results/training_run_summary.csv) a [histórii validačného loss](aya_300k_lr_experiments/results/eval_loss_history.csv).
<p align="center">
<img src="aya_300k_lr_experiments/results/lr_vs_final_eval_loss.png" alt="Finálny eval loss podľa learning rate na 300k Aya príkladoch" width="50%">
</p>
<p align="center"> <p align="center">
<img src="aya_300k_lr_experiments/results/eval_loss_over_steps.png" alt="Priebeh validačného loss pre šesť learning rate" width="50%"> <img src="aya_300k_lr_experiments/results/eval_loss_over_steps.png" alt="Priebeh validačného loss pre šesť learning rate" width="50%">
</p> </p>
<p align="center">
<img src="aya_300k_lr_experiments/results/grad_norm_over_steps.png" alt="Priebeh zaznamenaného gradient norm pre šesť learning rate" width="50%">
</p>
## Export vybraného modelu a benchmarky ## Export vybraného modelu a benchmarky
Na následné benchmarky sa vybral model s LR `0.00010`. Jeho LoRA adaptér sa zlúčil s pôvodným základným modelom do samostatného modelu v `bfloat16`. Export nepredstavoval ďalší tréning. [Exportná konfigurácia](aya_300k_lr_experiments/benchmarks/export/export_lr_0p00010.yaml) používa rovnaký snapshot základného modelu a template `alpaca`. Na následné benchmarky sa vybral model s LR `0.00010`. Jeho LoRA adaptér sa zlúčil s pôvodným základným modelom do samostatného modelu v `bfloat16`.
Benchmarky skúmajú schopnosti tohto vybraného modelu. **Ostatných päť LR zatiaľ týmito benchmarkmi nebolo porovnaných**, takže z nich nemožno vyhlásiť LR `0.00010` za najlepší LR podľa downstream metrík. Benchmarky skúmajú schopnosti tohto vybraného modelu. **Ostatných päť LR zatiaľ týmito benchmarkmi nebolo porovnaných**.
### lm-evaluation-harness ### lm-evaluation-harness
Použilo sa pôvodné prostredie `lm_eval_hruska`, HF backend, `bf16`, batch size 1 a zero-shot nastavenie bez aplikovania chat template. Zlúčený model sa načítal samostatne; tokenizer pochádzal z pôvodného modelového snapshotu. Tento postup obchádza nekompatibilitu exportovaného označenia `TokenizersBackend` so starším Transformers 4.48.2.
Vyhodnotenie dokončilo všetkých sedem pôvodných úloh a skončilo s návratovým kódom 0. Zachované sú [výsledky](aya_300k_lr_experiments/benchmarks/lmeval/results/), [log](aya_300k_lr_experiments/benchmarks/lmeval/logs/), custom úlohy a metadáta prostredia. V nasledujúcej tabuľke sú accuracy metriky prevedené na percentá; SKQuad F1 je už v zdroji v škále 0–100. Vyhodnotenie dokončilo všetkých sedem pôvodných úloh a skončilo s návratovým kódom 0. Zachované sú [výsledky](aya_300k_lr_experiments/benchmarks/lmeval/results/), [log](aya_300k_lr_experiments/benchmarks/lmeval/logs/), custom úlohy a metadáta prostredia. V nasledujúcej tabuľke sú accuracy metriky prevedené na percentá; SKQuad F1 je už v zdroji v škále 0–100.
| Model | ARC acc_norm | HellaSwag acc_norm | M-MMLU acc | TQA MC1 | TQA MC2 | SKLegal acc_norm | SKQuad F1 | | Model | ARC acc_norm | HellaSwag acc_norm | M-MMLU acc | TQA MC1 | TQA MC2 | SKLegal acc_norm | SKQuad F1 |
@ -950,19 +942,16 @@ Vyhodnotenie dokončilo všetkých sedem pôvodných úloh a skončilo s návrat
| 100k – experiment 10, r16/a32/LR 0.0001 | 32.93 | 51.57 | 34.48 | 20.57 | 34.80 | 46.18 | 37.76 | | 100k – experiment 10, r16/a32/LR 0.0001 | 32.93 | 51.57 | 34.48 | 20.57 | 34.80 | 46.18 | 37.76 |
| **300k – vybraný LR 0.00010** | 34.73 | 51.64 | 31.03 | 19.67 | 35.07 | 46.10 | 38.73 | | **300k – vybraný LR 0.00010** | 34.73 | 51.64 | 31.03 | 19.67 | 35.07 | 46.10 | 38.73 |
Oproti 100k experimentu 10 dosiahol vybraný 300k model bodovo vyššie ARC acc_norm (+1.80 percentuálneho bodu) a SKQuad F1 (+0.97 bodu), ale nižšie M-MMLU acc (−3.45 percentuálneho bodu). Ostatné zmeny sú menšie. V žiadnej zo siedmich hlavných metrík neprekonal maximum z celej desiatky 100k behov; tieto maximá navyše pochádzajú z rôznych konfigurácií. Výber najnižšieho validačného loss teda neznamená automaticky najlepší výsledok v každej downstream úlohe. Nejde o vyhodnotenie všetkých šiestich 300k LR ani o test štatistickej významnosti rozdielov. Oproti 100k experimentu 10 dosiahol vybraný 300k model bodovo vyššie ARC acc_norm (+1.80 percentuálneho bodu) a SKQuad F1 (+0.97 bodu), ale nižšie M-MMLU acc (−3.45 percentuálneho bodu). Ostatné zmeny sú menšie. V žiadnej zo siedmich hlavných metrík neprekonal maximum z celej desiatky 100k behov; tieto maximá navyše pochádzajú z rôznych konfigurácií. Výber najnižšieho validačného loss teda neznamená automaticky najlepší výsledok v každej downstream úlohe.
Úplné porovnanie so všetkými desiatimi staršími Hruška experimentmi je v [comparison_with_100k.csv](aya_300k_lr_experiments/benchmarks/lmeval/comparison_with_100k.csv). Vo všetkých porovnávaných Hruška behoch sa zhodujú konfigurácie a verzie úloh, počty vzoriek, seeds, evaluator commit `6d2abda4`, Transformers 4.48.2 a nastavenie bez chat template. Pole `task_hashes` je však v zdrojových JSON súboroch prázdne, takže nezávislé overenie obsahu benchmarkových dát pomocou hashov nie je možné. Staršie výsledky používali samostatný PEFT adaptér, nový výsledok zlúčený model v BF16; spôsob načítania a zaokrúhlenie pri zlúčení preto nie sú úplne identické. Podrobnosti sú v [audite porovnateľnosti](aya_300k_lr_experiments/benchmarks/lmeval/provenance/comparability_audit.json).
### SK-bench ### SK-bench
Dokončil sa **čiastkový slovenský zero-shot beh s 222 položkami**. Položka predstavuje kombináciu úlohy, podúlohy a variantu promptu, nie jeden hodnotený príklad. Zahrnuté boli tri slovenské formulácie promptov dostupných úloh. Použila sa Alpaca šablóna zlúčeného modelu, greedy dekódovanie, seed 1234, `bf16`, jedna GPU a maximálny kontext 32 768 tokenov. Dokončil sa **čiastkový slovenský zero-shot beh s 222 položkami**. Zahrnuté boli tri slovenské formulácie promptov dostupných úloh. Použila sa Alpaca šablóna zlúčeného modelu, greedy dekódovanie, seed 1234, `bf16`, jedna GPU a maximálny kontext 32 768 tokenov.
Z pôvodných 412 slovenských položiek sa vynechalo 187 položiek pre 12 nedostupných repozitárov: Chiby, Autoškola, e-testy, IFEval-SK, OneRuler-SK, Scio, Slohry, Slovak school exams, Slovak Trivia, SlovakSum, SME-Sum a slovné analógie. Ich kontrola vracala `RepositoryNotFoundError`; tento stav sám osebe nerozlišuje neexistujúci repozitár od súkromného repozitára bez oprávnenia. Ďalšie tri položky NLI-SK-annotated sa vynechali, pretože prístup vyžadoval schválenie autorkou a pri spúšťaní behu ešte nebol udelený. Ostatné NLI úlohy zo skLEP v behu zostali. Z pôvodných 412 slovenských položiek sa vynechalo 187 položiek pre 12 nedostupných repozitárov: Chiby, Autoškola, e-testy, IFEval-SK, OneRuler-SK, Scio, Slohry, Slovak school exams, Slovak Trivia, SlovakSum, SME-Sum a slovné analógie. Ich kontrola vracala `RepositoryNotFoundError`. Ďalšie tri položky NLI-SK-annotated sa vynechali, pretože prístup vyžadoval schválenie autorkou a pri spúšťaní behu ešte nebol udelený. Ostatné NLI úlohy zo skLEP v behu zostali.
Uložené sú [vykonané úlohy](aya_300k_lr_experiments/benchmarks/skbench/configs/tasks.txt), [vynechané úlohy](aya_300k_lr_experiments/benchmarks/skbench/configs/omitted_tasks.txt), [report dostupnosti](aya_300k_lr_experiments/benchmarks/skbench/configs/dataset_access_report.json), úplný výsledný JSON a úspešný log. Audit 222 detailných parquet výstupov overil **159 426 hodnotení** (53 142 pre každý z troch promptov). **Log zároveň potvrdzuje orezanie príliš dlhého vstupu.** Všetky uložené `model_response.truncated_tokens_count` sú síce nulové, ale tieto počítadlá nezachytili orezanie hlásené enginom. Pri MultiWikiQA má 69 vstupov dĺžku presne na hranici použitého rozpočtu (23 pri každom prompte); ide o kandidátov konzistentných s orezaním, nie o spoľahlivo dokázaný počet orezaných príkladov. Výsledky dlhých QA vstupov preto treba interpretovať s týmto obmedzením. Podrobnosti sú v [audite](aya_300k_lr_experiments/benchmarks/skbench/results/audit_summary.json) a [počítadlách po úlohách](aya_300k_lr_experiments/benchmarks/skbench/results/truncation_audit_per_task.csv). Uložené sú [vykonané úlohy](aya_300k_lr_experiments/benchmarks/skbench/configs/tasks.txt), [vynechané úlohy](aya_300k_lr_experiments/benchmarks/skbench/configs/omitted_tasks.txt), [report dostupnosti](aya_300k_lr_experiments/benchmarks/skbench/configs/dataset_access_report.json), úplný výsledný JSON a úspešný log. Audit 222 detailných parquet výstupov overil **159 426 hodnotení** (53 142 pre každý z troch promptov). **Log zároveň potvrdzuje orezanie príliš dlhého vstupu.**
Výber opisných výsledkov z dostupných úloh. Uvedený priemer je vážený počtom hodnotených príkladov v príslušných variantoch; všetky tri prompty majú v danej úlohe rovnaký počet príkladov. Pri MMLU zahŕňa všetkých 57 predmetov a tri prompty. Toto nie je oficiálna agregácia úplného SK-bench.
| Úloha | Metrika | Počet variantov | Priemer (%) | | Úloha | Metrika | Počet variantov | Priemer (%) |
|---|---|---:|---:| |---|---|---:|---:|
@ -981,14 +970,8 @@ Výber opisných výsledkov z dostupných úloh. Uvedený priemer je vážený p
Úplné metriky sú v [per_task_metrics.csv](aya_300k_lr_experiments/benchmarks/skbench/results/per_task_metrics.csv); rodinné a promptové súhrny vrátane nevážených priemerov sú v [family_summary.csv](aya_300k_lr_experiments/benchmarks/skbench/results/family_summary.csv) a [family_prompt_summary.csv](aya_300k_lr_experiments/benchmarks/skbench/results/family_prompt_summary.csv). Úplné metriky sú v [per_task_metrics.csv](aya_300k_lr_experiments/benchmarks/skbench/results/per_task_metrics.csv); rodinné a promptové súhrny vrátane nevážených priemerov sú v [family_summary.csv](aya_300k_lr_experiments/benchmarks/skbench/results/family_summary.csv) a [family_prompt_summary.csv](aya_300k_lr_experiments/benchmarks/skbench/results/family_prompt_summary.csv).
Výsledky treba čítať spolu s definíciou metriky a promptu. Napríklad pri ARC je priemer presnej metriky `em` približne 2.37 %, zatiaľ čo `em_relaxed` dosahuje 19.08 %. Rozdiel ukazuje citlivosť generatívneho hodnotenia na spôsob zápisu odpovede. Úplný surový JSON zachováva aj agregát `all`, ktorý sa tu neinterpretuje ako celkové skóre: mieša rôzne metriky a pokrýva neúplnú množinu úloh. Samotné MMLU tvorí 171 z 222 položiek, preto jednoduché spriemerovanie všetkých riadkov nie je vyváženým súhrnom schopností modelu.
**Tento výsledok nie je oficiálne celkové skóre úplného SK-bench.** Pri porovnávaní ďalších modelov treba použiť rovnaký zmrazený zoznam úloh a rovnaký protokol. SK-bench používa generovanie a následné porovnávanie textovej odpovede, zatiaľ čo väčšina uvedených lm-eval úloh vyhodnocuje pravdepodobnosti možností. Odlišné sú aj konkrétne datasety, prompty a metriky; hodnoty medzi týmito dvoma frameworkmi preto nie sú priamo zameniteľné. **Tento výsledok nie je oficiálne celkové skóre úplného SK-bench.**
Pri príprave sa sampler FlashInfer pokúšal kompilovať cez starší systémový CUDA toolkit. Úspešný beh používal `VLLM_USE_FLASHINFER_SAMPLER=0` a `--enforce-eager`. Podrobné verzie a parametre sú súčasťou benchmarkových metadát. Pri príprave sa sampler FlashInfer pokúšal kompilovať cez starší systémový CUDA toolkit. Úspešný beh používal `VLLM_USE_FLASHINFER_SAMPLER=0` a `--enforce-eager`.
## Uložené podklady
Priečinok [aya_300k_lr_experiments/](aya_300k_lr_experiments/) obsahuje pôvodné konfigurácie, tréningové a benchmarkové logy, výsledné JSON/CSV súbory, grafy, vybrané metadáta a skripty. Veľké váhy, checkpointy, `trainer_state.json`, kompletné per-sample parquet súbory a duplicitné inference cache zostávajú v pôvodnom archíve. Grafy a odvodené tabuľky tréningu možno obnoviť z malých uložených histórií bez prístupu k váham modelov.
Zdrojový archív a jeho SHA-256 sú zaznamenané v [source_archive.json](aya_300k_lr_experiments/provenance/source_archive.json).

View File

@ -1,9 +0,0 @@
{% set system_message = 'Below is an instruction that describes a task. Write a response that appropriately completes the request.
' %}{% if messages[0]['role'] == 'system' %}{% set loop_messages = messages[1:] %}{% set system_message = messages[0]['content'] %}{% else %}{% set loop_messages = messages %}{% endif %}{% if system_message is defined %}{{ system_message }}{% endif %}{% for message in loop_messages %}{% set content = message['content'] %}{% if message['role'] == 'user' %}{{ '### Instruction:
' + content + '
### Response:
' }}{% elif message['role'] == 'assistant' %}{{ content + '</s>' + '
' }}{% endif %}{% endfor %}

View File

@ -1,30 +0,0 @@
{
"architectures": [
"MistralForCausalLM"
],
"attention_dropout": 0.0,
"bos_token_id": 1,
"dtype": "bfloat16",
"eos_token_id": 2,
"head_dim": 128,
"hidden_act": "silu",
"hidden_size": 4096,
"initializer_range": 0.02,
"intermediate_size": 14336,
"max_position_embeddings": 32768,
"model_type": "mistral",
"num_attention_heads": 32,
"num_hidden_layers": 32,
"num_key_value_heads": 8,
"pad_token_id": 2,
"rms_norm_eps": 1e-05,
"rope_parameters": {
"rope_theta": 10000.0,
"rope_type": "default"
},
"sliding_window": 4096,
"tie_word_embeddings": false,
"transformers_version": "5.5.0",
"use_cache": true,
"vocab_size": 32000
}

View File

@ -1,12 +0,0 @@
model_name_or_path: slovak-nlp/mistral-sk-7b
model_revision: 089497ae0d72018e9591895c54f774bf0b4a83a4
adapter_name_or_path: /home/schwarc/diplomovka/aya_300k_lr_validation/lr_0p00010
template: alpaca
finetuning_type: lora
infer_dtype: bfloat16
export_dir: /home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010
export_size: 5
export_device: cpu
export_legacy_format: false

View File

@ -1,6 +0,0 @@
{
"_from_model_config": true,
"bos_token_id": 1,
"eos_token_id": 2,
"transformers_version": "5.5.0"
}

View File

@ -1,19 +0,0 @@
{
"add_prefix_space": true,
"backend": "tokenizers",
"bos_token": "<s>",
"clean_up_tokenization_spaces": false,
"eos_token": "</s>",
"extra_special_tokens": [],
"is_local": false,
"legacy": true,
"model_max_length": 1000000000000000019884624838656,
"pad_token": "</s>",
"padding_side": "left",
"sp_model_kwargs": {},
"spaces_between_special_tokens": false,
"split_special_tokens": false,
"tokenizer_class": "TokenizersBackend",
"unk_token": "<unk>",
"use_default_system_prompt": false
}

View File

@ -1,18 +0,0 @@
499e639455dc6bb9c79228b54b82c66b509f8fe6f2d33513b482b90dbf990674 comparison_with_100k.csv
b587953b0ce136fea20edf50105005c645a2abfad2cd4f6bfa58ee17cf36b34c full_metrics.csv
fd33cc64e660d4d996bd1b6af966e900c72b0c3b5c4bdb4e6915ac0756814e94 logs/lr_0p00010_20261023_224332.log
2e959d2b2052ecc4dc5f571ac674ccaa39119149c58e6ac0da467aa0335b8248 provenance/comparability_audit.json
f491f734663154901f0b5a4bb44aaed69b5d95448415291107fea0c703b055e8 provenance/custom_tasks/arc_sk.yaml
f2feb3ae7dc6e8ae3db09a91747119d7256d1ef33b9a1e417a40cb2a949ce5b9 provenance/custom_tasks/hellaswag_sk.yaml
d2f8c18839d15d365eed6997564e11aab43173eef91470e8a5834a9471772c2a provenance/custom_tasks/m_mmlu_sk.yaml
9443e2d5e398c82f921d8e714ff01693bfce793eef9bf3b0ad581a8bbf137c4a provenance/custom_tasks/sklegal.yaml
759c8cb35d27e50dd4dc4e81b34932d8bc96e36e309ed666858a904624a61131 provenance/custom_tasks/skquad.yaml
de1b8b08f998ebb3dcdd881c3e2aaba89dd53f6ea2a51b0529eadf7936ef2ed3 provenance/custom_tasks/task.py
fa1e7075c4715a4465be66041d36ef3f9b4dc8a7e41898554078294d2510f525 provenance/custom_tasks/task_configs_from_wandb.json
cf922b04a755762060430ef37a18a860017cc9c79e89cf23ac7465fa97244faa provenance/custom_tasks/truthfulqa_sk_mc1.yaml
b9209889fdf0e38915e29b83911213010f6c49d474836f474491da085ab26e01 provenance/custom_tasks/truthfulqa_sk_mc2.yaml
205bd6b1be478ed9cb2a104bf47214cf75debe485fb43c6b78d6584e638283de provenance/lm_eval_commit.txt
b4dcc9d0c2e7b5f5036ddc38a7aad4111934e39d84019b2122ad6561b780b5a4 provenance/package_versions.json
44d8afff7e8d918ef9e53404a8fa17fe19d6dcfaf782519f01be44a2408da898 provenance/run_settings.txt
f6f8d8470b78daf35d80f5a7315cc9f38d867daaead08df39a165cbcf98afd4e provenance/tasks.txt
5774cad7440ab807be44dc5bfa82ac7cbb4c0281204fc397a10c2bbfe7b8f452 results/results_2026-10-24T02-28-32.987157.json

View File

@ -1,379 +0,0 @@
{
"comparison_scope": "All ten Hruska Aya 100k runs; Titan excluded.",
"units": "Accuracy metrics use 0..1; SKQuad scores use 0..100. N/A remains unavailable.",
"new_result_sha256": "5774cad7440ab807be44dc5bfa82ac7cbb4c0281204fc397a10c2bbfe7b8f452",
"task_hashes_caveat": "task_hashes is empty in all eleven JSONs; equality is not a nonempty content-hash verification.",
"model_loading_difference": "Older runs load base model plus PEFT adapter; 300k loads a merged model with explicit base tokenizer. Model arguments, parameter counts and model SHA therefore differ.",
"new_n_samples": {
"truthfulqa_sk_mc2": {
"original": 778,
"effective": 778
},
"truthfulqa_sk_mc1": {
"original": 778,
"effective": 778
},
"skquad": {
"original": 9583,
"effective": 9583
},
"sklegal": {
"original": 1334,
"effective": 1334
},
"m_mmlu_sk": {
"original": 13062,
"effective": 13062
},
"hellaswag_sk": {
"original": 9485,
"effective": 9485
},
"arc_sk": {
"original": 1169,
"effective": 1169
}
},
"comparisons": [
{
"model_id": "01_baseline_r16_a16_lr5e5_adamw",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_01_baseline_r16_a16_lr5e5_adamw,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "02_optimizer_adamw8bit_r16_a16_lr5e5",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_02_optimizer_adamw8bit_r16_a16_lr5e5,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "03_rank8_a16_lr5e5",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_03_rank8_a16_lr5e5,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7262703616,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "04_rank32_a32_lr5e5",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_04_rank32_a32_lr5e5,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7325618176,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "05_r16_alpha32_lr5e5",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_05_r16_alpha32_lr5e5,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "06_lr1e4_r16_a16",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_06_lr1e4_r16_a16,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "07_lr2e5_r16_a16",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_07_lr2e5_r16_a16,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "08_attention_only_r16_a16_lr5e5",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_08_attention_only_r16_a16_lr5e5,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7255363584,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "09_batch2_accum4_r16_a16_lr5e5",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_09_batch2_accum4_r16_a16_lr5e5,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
},
{
"model_id": "10_r16_a32_lr1e4",
"equal_to_300k": {
"versions": true,
"configs": true,
"task_hashes": true,
"n-samples": true,
"n-shot": true,
"git_hash": true,
"transformers_version": true,
"chat_template": true,
"chat_template_sha": true,
"system_instruction": true,
"fewshot_as_multiturn": true
},
"evaluation_config_differences": {
"model_args": {
"older_100k": "pretrained=slovak-nlp/mistral-sk-7b,peft=/home/schwarc/diplomovka/hruska_compare9_100k_fixed_10_r16_a32_lr1e4,dtype=bfloat16",
"new_300k": "pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16"
},
"model_num_parameters": {
"older_100k": 7283675136,
"new_300k": 7241732096
},
"model_sha": {
"older_100k": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"new_300k": ""
},
"peft_sha": {
"older_100k": "",
"new_300k": null
}
}
}
]
}

View File

@ -1,42 +0,0 @@
tag:
- arc_multilingual
task: arc_sk
repeats: 1
metadata:
version: 2
test_split: test
description: ''
doc_to_text: query
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
- metric: acc_norm
aggregation: mean
higher_is_better: true
num_fewshot: 0
output_type: multiple_choice
unsafe_code: false
dataset_name: sk
dataset_path: alexandrainst/m_arc
process_docs: "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n\
\ def _process_doc(doc):\n # breakpoint()\n out_doc = {\n \
\ \"id\": doc[\"id\"],\n \"query\": \"Question: \" + preprocess(doc[\"\
instruction\"]) + \"\\nAnswer:\",\n \"choices\": [\n preprocess(option)\n\
\ for option in [\n doc[\"option_a\"],\n \
\ doc[\"option_b\"],\n doc[\"option_c\"],\n \
\ doc[\"option_d\"],\n doc[\"option_e\"],\n \
\ ]\n if option\n ],\n \"gold\"\
: [\"A\", \"B\", \"C\", \"D\", \"E\"].index(doc[\"answer\"]),\n }\n \
\ return out_doc\n\n return dataset.map(_process_doc)\n"
doc_to_choice: choices
doc_to_target: gold
training_split: train
target_delimiter: ' '
validation_split: validation
fewshot_delimiter: '
'
should_decontaminate: true
doc_to_decontamination_query: query

View File

@ -1,35 +0,0 @@
tag:
- hellaswag_multilingual
task: hellaswag_sk
repeats: 1
metadata:
version: 1
description: ''
doc_to_text: query
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
- metric: acc_norm
aggregation: mean
higher_is_better: true
num_fewshot: 0
output_type: multiple_choice
unsafe_code: false
dataset_name: sk
dataset_path: alexandrainst/m_hellaswag
process_docs: "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n\
\ def _process_doc(doc):\n ctx = doc[\"ctx_a\"] + \" \" + doc[\"ctx_b\"\
].capitalize()\n out_doc = {\n \"query\": preprocess(doc[\"activity_label\"\
] + \": \" + ctx),\n \"choices\": [preprocess(ending) for ending in doc[\"\
endings\"]],\n \"gold\": int(doc[\"label\"]),\n }\n return\
\ out_doc\n\n return dataset.map(_process_doc)\n"
doc_to_choice: choices
doc_to_target: '{{label.lstrip()}}'
target_delimiter: ' '
validation_split: val
fewshot_delimiter: '
'
should_decontaminate: false

View File

@ -1,43 +0,0 @@
tag:
- m_mmlu
task: m_mmlu_sk
repeats: 1
metadata:
version: 0
test_split: test
description: ''
doc_to_text: '{{instruction.strip()}}
A. {{option_a}}
B. {{option_b}}
C. {{option_c}}
D. {{option_d}}
Answer:'
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
num_fewshot: 0
output_type: multiple_choice
unsafe_code: false
dataset_name: sk
dataset_path: alexandrainst/m_mmlu
doc_to_choice:
- A
- B
- C
- D
doc_to_target: answer
fewshot_split: train
fewshot_config:
sampler: first_n
target_delimiter: ' '
fewshot_delimiter: '
'
should_decontaminate: false

View File

@ -1,23 +0,0 @@
task: sklegal
repeats: 1
metadata:
version: 1
test_split: test
description: ''
doc_to_text: '{{prompt}} '
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
- metric: acc_norm
aggregation: mean
higher_is_better: true
num_fewshot: 0
output_type: multiple_choice
unsafe_code: false
dataset_path: TUKE-KEMT/slovak-legal-exam
doc_to_choice: '{{answers}}'
doc_to_target: label
target_delimiter: ' '
fewshot_delimiter: "\n\n"
should_decontaminate: false

View File

@ -1,2 +0,0 @@
task: skquad
class: !function task.SQuAD2

View File

@ -1,245 +0,0 @@
"""
Know What You Don’t Know: Unanswerable Questions for SQuAD
https://arxiv.org/pdf/1806.03822.pdf
Stanford Question Answering Dataset (SQuAD) is a reading comprehension dataset,
consisting of questions posed by crowdworkers on a set of Wikipedia articles,
where the answer to every question is a segment of text, or span, from the
corresponding reading passage, or the question might be unanswerable.
SQuAD2.0 combines the 100,000 questions in SQuAD1.1 with over 50,000 unanswerable
questions written adversarially by crowdworkers to look similar to answerable ones.
To do well on SQuAD2.0, systems must not only answer questions when possible, but
also determine when no answer is supported by the paragraph and abstain from answering.
Homepage: https://rajpurkar.github.io/SQuAD-explorer/
"""
from functools import partial
from math import exp
import datasets
from packaging import version
from lm_eval.api.instance import Instance
from lm_eval.api.task import ConfigurableTask
_CITATION = """
@misc{rajpurkar2018know,
title={Know What You Don't Know: Unanswerable Questions for SQuAD},
author={Pranav Rajpurkar and Robin Jia and Percy Liang},
year={2018},
eprint={1806.03822},
archivePrefix={arXiv},
primaryClass={cs.CL}
}
"""
def _squad_metric(predictions, references):
import evaluate
squad_metric = evaluate.load("squad_v2")
return squad_metric.compute(predictions=predictions, references=references)
def _squad_agg(key, items):
predictions, references = zip(*items)
return _squad_metric(predictions=predictions, references=references).get(key, 0)
class SQuAD2(ConfigurableTask):
VERSION = 3
DATASET_PATH = "TUKE-DeutscheTelekom/skquad"
DATASET_NAME = None
def __init__(self, config=None):
super().__init__(config={"metadata": {"version": self.VERSION}})
# HF changed squad on us so we have to make sure we aren't running the old one
assert version.parse(datasets.__version__) >= version.parse("1.11.0"), (
"datasets v1.11.0 or later required for SQuAD"
)
def has_training_docs(self):
return True
def has_validation_docs(self):
return True
def has_test_docs(self):
return False
def training_docs(self):
return self.dataset["train"]
def validation_docs(self):
return self.dataset["validation"]
def doc_to_text(self, doc):
return (
"Title: "
+ doc["title"]
+ "\n\n"
+ "Background: "
+ doc["context"]
+ "\n\n"
+ "Question: "
+ doc["question"]
+ "\n\n"
+ "Answer:"
)
def should_decontaminate(self):
return True
def doc_to_decontamination_query(self, doc):
return doc["context"]
def doc_to_target(self, doc):
answer_list = doc["answers"]["text"]
if len(answer_list) > 0:
answer = answer_list[0]
else:
answer = "unanswerable"
return " " + answer
def construct_requests(
self, doc, ctx, chat_template=None, apply_chat_template=False, **kwargs
):
"""Uses RequestFactory to construct Requests and returns an iterable of
Requests which will be sent to the LM.
:param doc:
The document as returned from training_docs, validation_docs, or test_docs.
:param ctx: str
The context string, generated by fewshot_context. This includes the natural
language description, as well as the few shot examples, and the question
part of the document for `doc`.
"""
return [
Instance(
request_type="generate_until",
doc=doc,
arguments=(ctx, {"until": ["\n"]}),
idx=0,
**kwargs,
),
Instance(
request_type="loglikelihood",
doc=doc,
arguments=(ctx, " " + "unanswerable"),
idx=0,
**kwargs,
),
]
def process_results(self, doc, results):
"""Take a single document and the LM results and evaluates, returning a
dict where keys are the names of submetrics and values are the values of
the metric for that one document
:param doc:
The document as returned from training_docs, validation_docs, or test_docs.
:param results:
The results of the requests created in construct_requests.
"""
continuation, (logprob_unanswerable, _) = results
no_answer_probability = exp(logprob_unanswerable)
predictions = {
"id": doc["id"],
"prediction_text": continuation,
"no_answer_probability": no_answer_probability,
}
references = {
"id": doc["id"],
"answers": doc["answers"],
}
return {
"exact": (
predictions,
references,
), # Exact match (the normalized answer exactly match the gold answer)
"f1": (
predictions,
references,
), # The F-score of predicted tokens versus the gold answer
"HasAns_exact": (
predictions,
references,
), # Exact match (the normalized answer exactly match the gold answer)
"HasAns_f1": (
predictions,
references,
), # The F-score of predicted tokens versus the gold answer
"NoAns_exact": (
predictions,
references,
), # Exact match (the normalized answer exactly match the gold answer)
"NoAns_f1": (
predictions,
references,
), # The F-score of predicted tokens versus the gold answer
"best_exact": (
predictions,
references,
), # Best exact match (with varying threshold)
"best_f1": (predictions, references), # Best F1 (with varying threshold)
}
def aggregation(self):
"""
:returns: {str: [float] -> float}
A dictionary where keys are the names of submetrics and values are
functions that aggregate a list of metrics
"""
return {
"exact": partial(
_squad_agg, "exact"
), # Exact match (the normalized answer exactly match the gold answer)
"f1": partial(
_squad_agg, "f1"
), # The F-score of predicted tokens versus the gold answer
"HasAns_exact": partial(
_squad_agg, "HasAns_exact"
), # Exact match (the normalized answer exactly match the gold answer)
"HasAns_f1": partial(
_squad_agg, "HasAns_f1"
), # The F-score of predicted tokens versus the gold answer
"NoAns_exact": partial(
_squad_agg, "NoAns_exact"
), # Exact match (the normalized answer exactly match the gold answer)
"NoAns_f1": partial(
_squad_agg, "NoAns_f1"
), # The F-score of predicted tokens versus the gold answer
"best_exact": partial(
_squad_agg, "best_exact"
), # Best exact match (with varying threshold)
"best_f1": partial(
_squad_agg, "best_f1"
), # Best F1 (with varying threshold)
}
def higher_is_better(self):
"""
:returns: {str: bool}
A dictionary where keys are the names of submetrics and values are
whether a higher value of the submetric is better
"""
return {
"exact": True, # Exact match (the normalized answer exactly match the gold answer)
"f1": True, # The F-score of predicted tokens versus the gold answer
"HasAns_exact": True, # Exact match (the normalized answer exactly match the gold answer)
"HasAns_f1": True, # The F-score of predicted tokens versus the gold answer
"NoAns_exact": True, # Exact match (the normalized answer exactly match the gold answer)
"NoAns_f1": True, # The F-score of predicted tokens versus the gold answer
"best_exact": True, # Best exact match (with varying threshold)
"best_f1": True, # Best F1 (with varying threshold)
}

View File

@ -1,232 +0,0 @@
{
"arc_sk": {
"tag": [
"arc_multilingual"
],
"task": "arc_sk",
"repeats": 1,
"metadata": {
"version": 2
},
"test_split": "test",
"description": "",
"doc_to_text": "query",
"metric_list": [
{
"metric": "acc",
"aggregation": "mean",
"higher_is_better": true
},
{
"metric": "acc_norm",
"aggregation": "mean",
"higher_is_better": true
}
],
"num_fewshot": 0,
"output_type": "multiple_choice",
"unsafe_code": false,
"dataset_name": "sk",
"dataset_path": "alexandrainst/m_arc",
"process_docs": "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n def _process_doc(doc):\n # breakpoint()\n out_doc = {\n \"id\": doc[\"id\"],\n \"query\": \"Question: \" + preprocess(doc[\"instruction\"]) + \"\\nAnswer:\",\n \"choices\": [\n preprocess(option)\n for option in [\n doc[\"option_a\"],\n doc[\"option_b\"],\n doc[\"option_c\"],\n doc[\"option_d\"],\n doc[\"option_e\"],\n ]\n if option\n ],\n \"gold\": [\"A\", \"B\", \"C\", \"D\", \"E\"].index(doc[\"answer\"]),\n }\n return out_doc\n\n return dataset.map(_process_doc)\n",
"doc_to_choice": "choices",
"doc_to_target": "gold",
"training_split": "train",
"target_delimiter": " ",
"validation_split": "validation",
"fewshot_delimiter": "\n\n",
"should_decontaminate": true,
"doc_to_decontamination_query": "query"
},
"skquad": {
"task": "skquad",
"repeats": 1,
"metadata": {
"version": 3
},
"description": "",
"num_fewshot": 0,
"output_type": "generate_until",
"unsafe_code": false,
"target_delimiter": " ",
"fewshot_delimiter": "\n\n",
"generation_kwargs": {
"until": [
"\n\n"
],
"do_sample": false
},
"should_decontaminate": false
},
"sklegal": {
"task": "sklegal",
"repeats": 1,
"metadata": {
"version": 1
},
"test_split": "test",
"description": "",
"doc_to_text": "{{prompt}} ",
"metric_list": [
{
"metric": "acc",
"aggregation": "mean",
"higher_is_better": true
},
{
"metric": "acc_norm",
"aggregation": "mean",
"higher_is_better": true
}
],
"num_fewshot": 0,
"output_type": "multiple_choice",
"unsafe_code": false,
"dataset_path": "TUKE-KEMT/slovak-legal-exam",
"doc_to_choice": "{{answers}}",
"doc_to_target": "label",
"target_delimiter": " ",
"fewshot_delimiter": "\n\n",
"should_decontaminate": false
},
"m_mmlu_sk": {
"tag": [
"m_mmlu"
],
"task": "m_mmlu_sk",
"repeats": 1,
"metadata": {
"version": 0
},
"test_split": "test",
"description": "",
"doc_to_text": "{{instruction.strip()}}\nA. {{option_a}}\nB. {{option_b}}\nC. {{option_c}}\nD. {{option_d}}\nAnswer:",
"metric_list": [
{
"metric": "acc",
"aggregation": "mean",
"higher_is_better": true
}
],
"num_fewshot": 0,
"output_type": "multiple_choice",
"unsafe_code": false,
"dataset_name": "sk",
"dataset_path": "alexandrainst/m_mmlu",
"doc_to_choice": [
"A",
"B",
"C",
"D"
],
"doc_to_target": "answer",
"fewshot_split": "train",
"fewshot_config": {
"sampler": "first_n"
},
"target_delimiter": " ",
"fewshot_delimiter": "\n\n",
"should_decontaminate": false
},
"hellaswag_sk": {
"tag": [
"hellaswag_multilingual"
],
"task": "hellaswag_sk",
"repeats": 1,
"metadata": {
"version": 1
},
"description": "",
"doc_to_text": "query",
"metric_list": [
{
"metric": "acc",
"aggregation": "mean",
"higher_is_better": true
},
{
"metric": "acc_norm",
"aggregation": "mean",
"higher_is_better": true
}
],
"num_fewshot": 0,
"output_type": "multiple_choice",
"unsafe_code": false,
"dataset_name": "sk",
"dataset_path": "alexandrainst/m_hellaswag",
"process_docs": "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n def _process_doc(doc):\n ctx = doc[\"ctx_a\"] + \" \" + doc[\"ctx_b\"].capitalize()\n out_doc = {\n \"query\": preprocess(doc[\"activity_label\"] + \": \" + ctx),\n \"choices\": [preprocess(ending) for ending in doc[\"endings\"]],\n \"gold\": int(doc[\"label\"]),\n }\n return out_doc\n\n return dataset.map(_process_doc)\n",
"doc_to_choice": "choices",
"doc_to_target": "{{label.lstrip()}}",
"target_delimiter": " ",
"validation_split": "val",
"fewshot_delimiter": "\n\n",
"should_decontaminate": false
},
"truthfulqa_sk_mc1": {
"tag": [
"truthfulqa_multilingual"
],
"task": "truthfulqa_sk_mc1",
"repeats": 1,
"metadata": {
"version": 1
},
"description": "",
"doc_to_text": "query",
"metric_list": [
{
"metric": "acc",
"aggregation": "mean",
"higher_is_better": true
}
],
"num_fewshot": 0,
"output_type": "multiple_choice",
"unsafe_code": false,
"dataset_name": "sk",
"dataset_path": "alexandrainst/m_truthfulqa",
"process_docs": "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n def _process_doc(doc):\n out_doc = {\n \"question\": preprocess(doc[\"question\"]),\n \"query\": QA_PROMPT + \"\\n\\nQ: \" + preprocess(doc[\"question\"]) + \"\\nA:\",\n \"mc1_choices\": doc[\"mc1_targets_choices\"],\n \"mc2_choices\": doc[\"mc2_targets_choices\"],\n \"mc2_targets\": {\"labels\": doc[\"mc2_targets_labels\"]},\n \"gold\": \" \",\n }\n return out_doc\n\n return dataset.map(_process_doc)\n",
"doc_to_choice": "mc1_choices",
"doc_to_target": 0,
"target_delimiter": " ",
"validation_split": "val",
"fewshot_delimiter": "\n\n",
"should_decontaminate": true,
"doc_to_decontamination_query": "question"
},
"truthfulqa_sk_mc2": {
"tag": [
"truthfulqa_multilingual"
],
"task": "truthfulqa_sk_mc2",
"repeats": 1,
"metadata": {
"version": 1
},
"description": "",
"doc_to_text": "query",
"metric_list": [
{
"metric": "acc",
"aggregation": "mean",
"higher_is_better": true
}
],
"num_fewshot": 0,
"output_type": "multiple_choice",
"unsafe_code": false,
"dataset_name": "sk",
"dataset_path": "alexandrainst/m_truthfulqa",
"process_docs": "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n def _process_doc(doc):\n out_doc = {\n \"question\": preprocess(doc[\"question\"]),\n \"query\": QA_PROMPT + \"\\n\\nQ: \" + preprocess(doc[\"question\"]) + \"\\nA:\",\n \"mc1_choices\": doc[\"mc1_targets_choices\"],\n \"mc2_choices\": doc[\"mc2_targets_choices\"],\n \"mc2_targets\": {\"labels\": doc[\"mc2_targets_labels\"]},\n \"gold\": \" \",\n }\n return out_doc\n\n return dataset.map(_process_doc)\n",
"doc_to_choice": "mc2_choices",
"doc_to_target": 0,
"process_results": "def process_results_mc2(doc, results):\n lls, is_greedy = zip(*results)\n\n # Split on the first `0` as everything before it is true (`1`).\n split_idx = list(doc[\"mc2_targets\"][\"labels\"]).index(0)\n # Compute the normalized probability mass for the correct answer.\n ll_true, ll_false = lls[:split_idx], lls[split_idx:]\n p_true, p_false = np.exp(np.array(ll_true)), np.exp(np.array(ll_false))\n p_true = p_true / (sum(p_true) + sum(p_false))\n\n return {\"acc\": sum(p_true)}\n",
"target_delimiter": " ",
"validation_split": "val",
"fewshot_delimiter": "\n\n",
"should_decontaminate": true,
"doc_to_decontamination_query": "question"
}
}

View File

@ -1,34 +0,0 @@
tag:
- truthfulqa_multilingual
task: truthfulqa_sk_mc1
repeats: 1
metadata:
version: 1
description: ''
doc_to_text: query
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
num_fewshot: 0
output_type: multiple_choice
unsafe_code: false
dataset_name: sk
dataset_path: alexandrainst/m_truthfulqa
process_docs: "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n\
\ def _process_doc(doc):\n out_doc = {\n \"question\": preprocess(doc[\"\
question\"]),\n \"query\": QA_PROMPT + \"\\n\\nQ: \" + preprocess(doc[\"\
question\"]) + \"\\nA:\",\n \"mc1_choices\": doc[\"mc1_targets_choices\"\
],\n \"mc2_choices\": doc[\"mc2_targets_choices\"],\n \"mc2_targets\"\
: {\"labels\": doc[\"mc2_targets_labels\"]},\n \"gold\": \" \",\n \
\ }\n return out_doc\n\n return dataset.map(_process_doc)\n"
doc_to_choice: mc1_choices
doc_to_target: 0
target_delimiter: ' '
validation_split: val
fewshot_delimiter: '
'
should_decontaminate: true
doc_to_decontamination_query: question

View File

@ -1,40 +0,0 @@
tag:
- truthfulqa_multilingual
task: truthfulqa_sk_mc2
repeats: 1
metadata:
version: 1
description: ''
doc_to_text: query
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
num_fewshot: 0
output_type: multiple_choice
unsafe_code: false
dataset_name: sk
dataset_path: alexandrainst/m_truthfulqa
process_docs: "def process_docs(dataset: datasets.Dataset) -> datasets.Dataset:\n\
\ def _process_doc(doc):\n out_doc = {\n \"question\": preprocess(doc[\"\
question\"]),\n \"query\": QA_PROMPT + \"\\n\\nQ: \" + preprocess(doc[\"\
question\"]) + \"\\nA:\",\n \"mc1_choices\": doc[\"mc1_targets_choices\"\
],\n \"mc2_choices\": doc[\"mc2_targets_choices\"],\n \"mc2_targets\"\
: {\"labels\": doc[\"mc2_targets_labels\"]},\n \"gold\": \" \",\n \
\ }\n return out_doc\n\n return dataset.map(_process_doc)\n"
doc_to_choice: mc2_choices
doc_to_target: 0
process_results: "def process_results_mc2(doc, results):\n lls, is_greedy = zip(*results)\n\
\n # Split on the first `0` as everything before it is true (`1`).\n split_idx\
\ = list(doc[\"mc2_targets\"][\"labels\"]).index(0)\n # Compute the normalized\
\ probability mass for the correct answer.\n ll_true, ll_false = lls[:split_idx],\
\ lls[split_idx:]\n p_true, p_false = np.exp(np.array(ll_true)), np.exp(np.array(ll_false))\n\
\ p_true = p_true / (sum(p_true) + sum(p_false))\n\n return {\"acc\": sum(p_true)}\n"
target_delimiter: ' '
validation_split: val
fewshot_delimiter: '
'
should_decontaminate: true
doc_to_decontamination_query: question

View File

@ -1 +0,0 @@
6d2abda4fd171e68a8789330c4149e37c1ca0bda

View File

@ -1,8 +0,0 @@
{
"lm_eval": "0.4.8",
"transformers": "4.48.2",
"torch": "2.6.0+cu124",
"datasets": "5.0.1",
"peft": "0.14.0",
"evaluate": "0.4.6"
}

View File

@ -1,8 +0,0 @@
model=hf
pretrained=/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010
tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4
dtype=bfloat16
num_fewshot=0
batch_size=1
apply_chat_template=false
CUDA_VISIBLE_DEVICES=1

View File

@ -1 +0,0 @@
arc_sk,hellaswag_sk,m_mmlu_sk,truthfulqa_sk_mc1,truthfulqa_sk_mc2,sklegal,skquad

View File

@ -1,82 +0,0 @@
# Audit úspešného čiastočného SK-bench behu
Vybraný model po tréningu na 300k vzorke Aya s LR `0.00010` dokončil beh `sk_zero_available_without_nli_lr_0p00010_20261022_185255`. Log končí hláškou `Benchmarking completed.` a obsahuje výsledné metriky. Benchmarkovalo sa iba toto LR, vybrané podľa najnižšieho finálneho validačného loss zo šiestich tréningových behov; výsledky preto neporovnávajú benchmarkovú kvalitu šiestich LR ani budúceho tréningu na celej Aya množine.
## Pokrytie a počty
- Zoznam `configs/tasks.txt`, 222 konfigurácií úloh vo výslednom JSON a 222 súborov DETAILS sa zhodujú. Názvy sa pri porovnaní dekódujú z Windows `%3A`/`%7C` a normalizuje sa koncové označenie zero-shot variantu.
- Vyhodnotených bolo **222 zo 412 pôvodných task variantov**: 74 kombinácií úlohy/subtasku, každá s tromi promptmi. Ide o 13 rodín úloh. MMLU tvorí 171 variantov (57 predmetov × 3 prompty).
- DETAILS obsahujú **159 426 vyhodnotených inštancií**, po **53 142 na každý prompt**. Tri prompty opakovane hodnotia tie isté základné testové otázky; 159 426 nie je počet nezávislých otázok ani dôkaz unikátnosti medzi rôznymi datasetmi.
- `configs/omitted_tasks.txt` obsahuje 190 vynechaných variantov. Report dostupnosti eviduje 12 nedostupných repozitárov so 187 variantmi; tri ďalšie vynechané varianty patria samostatnému NLI-SK. Historický access report uvádza NLI-SK ako `OK`, ale jeho tri varianty v konečnom behu nie sú. NLI úlohy z rodiny SKLEP zostali zahrnuté.
- `max_samples: null` znamená, že beh nemal globálny limit vzoriek. Počty sa získali z metadát jednotlivých DETAILS súborov, nie zo zaokrúhlených metrík.
Tento dostupný subset sa nesmie označovať za oficiálne kompletné SK-bench skóre. Chýbajúce úlohy ani chýbajúce rodiny sa neimputovali.
## Zaznamenané nastavenie
Výsledný JSON potvrdzuje `bfloat16`, kontext `32768`, tensor/data/pipeline parallelism `1/1/1`, využitie GPU pamäte `0.85`, seed modelu `1234`, teplotu `0` a `enforce_eager: true`. Pole `generation_parameters.seed` je `null`; konkrétny seed je uložený v `model_config.seed`. Všetky úlohy majú `num_fewshots: 0`.
216 task variantov používa najviac 32 generovaných tokenov a šesť QA variantov 126 tokenov; stop sekvencia je nový riadok. Tieto limity výstupu treba pri porovnaní výsledkov zachovať. Záznam neobsahuje spoľahlivý počet odpovedí ukončených výstupným limitom.
Zmrazený commit SK-bench je `15823bbcc2d995e69441fcb7d34abb61bd8180c5`. Pôvodné `lighteval_sha` vo výslednom JSON je `?`; tento údaj sa dodatočne nevymýšľa. `uv.lock`, commit, modelová konfigurácia, per-task konfigurácie a revízie datasetov sú uchované v `provenance/` a `configs/`. Log zaznamenáva aj runtime patchovanie; samotný commit a lock preto bez rovnakého postupu nie sú úplným dôkazom identického prostredia.
## Orezanie dlhých vstupov
Kontrola projektovala `model_response.truncated_tokens_count` zo **všetkých 222 DETAILS súborov**, bez čítania duplicitného generation cache. Všetkých 159 426 hodnôt existuje, žiadna nie je `null` a všetky sú nula. Aj pôvodné súhrnné počítadlá sú nulové vrátane `non_truncated`, takže samy osebe nepotvrdzujú neprítomnosť orezania.
**Log priamo potvrdzuje orezanie kontextu.** Vyhľadanie `truncat` bez rozlíšenia veľkosti písmen našlo presne jednu hlášku, na LF riadku 16033:
```text
context_size + max_new_tokens=53860 which is greater than self.max_length=32768. Truncating context to 32642 tokens.
```
Následná diagnostika dĺžok zo všetkých DETAILS našla **69 tokenových polí presne na vstupnom limite 32 642 tokenov**, po 23 v každom z troch variantov `multi_wiki_qa`. Vo všetkých troch sa opakujú tie isté indexy riadkov. Žiadne uložené pole neprekročilo príslušný limit `32768 − generation_size`; ostatné úlohy mali vstupy pod limitom. Súvisiace uložené reťazce vstupu mali pri hraničných riadkoch až 121 852 znakov.
Týchto 69 riadkov sú **hraniční kandidáti zodpovedajúci orezaniu**, nie spoľahlivo dokázaný počet orezaných vstupov. Log neuvádza identifikátor konkrétneho tasku ani počet dotknutých vzoriek. Bez opätovnej tokenizácie pôvodných vstupov nemožno z dĺžky uloženého reťazca určiť pôvodnú dĺžku v tokenoch alebo počet odstránených tokenov. Overený záver je: **orezanie nastalo aspoň raz; jeho presný rozsah nie je z dostupných počítadiel známy**.
Strojový súhrn preto obsahuje `context_truncation_observed_in_log: true`, `actual_truncated_sample_count: null` a nulové počítadlá označuje prefixom `details_reported_`. Podrobnosti sú v `results/truncation_audit_per_task.csv`, `results/log_truncation_evidence.json`, `results/input_length_diagnostics_per_task.csv` a `results/input_length_budget_boundary_rows.csv`.
## Metriky a agregácia
`results/per_task_metrics.csv` obsahuje iba 222 reálne vykonaných task variantov, ich skutočné metriky a štandardné chyby priamo z výsledného JSON. Prioritná metrika na čítanie je `em_relaxed`, prípadne `em_norm_relaxed`, ak ju daná úloha skutočne používa. QA má vlastné metriky `exact_match_slk_prefix` a `f1_slk`; nepremenúvajú sa na všeobecnú accuracy.
Odvodené súhrny nikdy nemiešajú odlišné metriky do jedného skóre:
- `family_summary.csv`: priemer v rodine, vždy osobitne pre konkrétnu metriku, cez všetky dostupné subtasky a tri prompty.
- `family_prompt_summary.csv`: tá istá agregácia osobitne pre prompt 1, 2 a 3.
- `three_prompt_summary.csv`: priemer troch promptov pre každú zo 74 konkrétnych kombinácií úlohy/subtasku, opäť pre každú metriku osobitne.
- `task_macro_mean` je aritmetický priemer task metrík s rovnakou váhou každého variantu. `sample_weighted_mean` váži tieto metriky počtom riadkov v DETAILS. Prompty sa v oboch prípadoch považujú za opakované vyhodnotenia, nie za nové nezávislé otázky. Súhrnné intervaly spoľahlivosti sa z per-task chýb nevymýšľajú.
Pôvodný JSON má 226 kľúčov výsledkov: 222 úloh, tri vstavané MMLU promptové priemery a `all`. Štyri agregované riadky sú zachované v pôvodnom JSON, ale v odvodených súhrnoch sa znovu nepripočítavajú. `all` obsahuje viac metrík s rôznymi sadami úloh a netvorí oficiálne celkové skóre.
Napríklad MMLU `em_relaxed` má task macro priemer `0.1600941253` a sample-weighted priemer `0.1572245190`. Rozdiel vzniká rôznou veľkosťou 57 predmetov. SKLEP klasifikačné úlohy s `em_norm_relaxed` majú macro `0.3507994510`, ale sample-weighted `0.2144044321`; výber váh tu zásadne mení opisný výsledok.
## Obnovenie auditu
Audit používa Python a `pyarrow==26.0.0`. Knižnica sa pri spracovaní nainštalovala len do pomocného priečinka pracovného projektu; nie je súčasťou tohto stromu. Pôvodné parquety, cache ani váhy sa do Git podkladov nekopírujú. Na opätovný audit treba samostatne rozbalený zdrojový archív a jeho `archive_manifest.json`.
Archív treba najprv rozbaliť pomocou uloženého pomocného skriptu (Python 3.11+), ktorý vytvorí aj `archive_manifest.json` a `archive_summary.json`. Názvy s `:` a `|` prevedie na prenosné percent-encoded názvy a zachová mapovanie na originál. Priečinok určený cez `--output` musí byť nový alebo prázdny:
```bash
python scripts/unpack_results_archive.py \
--archive /path/to/aya_300k_benchmarky_20261024_215708.tar.gz \
--output /path/to/extracted/archive
```
Z koreňa experimentu možno potom spustiť:
```bash
python -m pip install --target .audit-deps -r benchmarks/skbench/provenance/requirements-audit.txt
python benchmarks/skbench/provenance/audit_skbench.py \
--source /path/to/extracted/archive \
--output benchmarks/skbench \
--pyarrow-path .audit-deps
python benchmarks/skbench/provenance/input_length_diagnostics.py \
--source /path/to/extracted/archive \
--output benchmarks/skbench/results \
--pyarrow-path .audit-deps
```
Prvý skript kontroluje pokrytie, kopíruje malé pôvodné artefakty, počíta metrikové súhrny a overuje truncation counter projekciou jediného stĺpca. Druhý skript projektuje uložené tokenové polia a vstupné reťazce, ale exportuje iba ich dĺžky a indexy hraničných riadkov. Texty otázok a odpovedí v týchto odvodených diagnostikách nie sú.
SHA-256 presných kópií pôvodných súborov je v `provenance/copied_files_sha256.csv`; zdrojový archív identifikuje `provenance/archive_summary.json`.

View File

@ -1,87 +0,0 @@
{
"source": "C:\\Users\\Jakub\\Desktop\\aya_300k_benchmarky_20261024_215708.tar.gz",
"compressed_bytes": 349555561,
"sha256": "b45e431cbc63bc73ef953f8aa3837695ccec43783e3da2dfccb0d99f7d1fe79c",
"files": 581,
"uncompressed_bytes": 1782181826,
"skipped_special": [],
"top_level_files": {
"aya_300k_lr_validation": 110,
"skbench_evaluation": 464,
"scripts": 7
},
"largest_files": [
{
"original": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_multi_wiki_qa.prompt2_qa_sk|0_2026-10-22T21-55-04.268099.parquet",
"local": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_multi_wiki_qa.prompt2_qa_sk%7C0_2026-10-22T21-55-04.268099.parquet",
"size": 127542209,
"type": "file"
},
{
"original": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_multi_wiki_qa.prompt1_qa_sk|0_2026-10-22T21-55-04.268099.parquet",
"local": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_multi_wiki_qa.prompt1_qa_sk%7C0_2026-10-22T21-55-04.268099.parquet",
"size": 127233608,
"type": "file"
},
{
"original": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_multi_wiki_qa.prompt3_qa_sk|0_2026-10-22T21-55-04.268099.parquet",
"local": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_multi_wiki_qa.prompt3_qa_sk%7C0_2026-10-22T21-55-04.268099.parquet",
"size": 125437876,
"type": "file"
},
{
"original": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/multi_wiki_qa.prompt2_qa_sk|0/82e1a28fce479a47/GENERATIVE.parquet",
"local": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/multi_wiki_qa.prompt2_qa_sk%7C0/82e1a28fce479a47/GENERATIVE.parquet",
"size": 103508951,
"type": "file"
},
{
"original": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/multi_wiki_qa.prompt1_qa_sk|0/f0737eb9e82c262f/GENERATIVE.parquet",
"local": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/multi_wiki_qa.prompt1_qa_sk%7C0/f0737eb9e82c262f/GENERATIVE.parquet",
"size": 103246110,
"type": "file"
},
{
"original": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/multi_wiki_qa.prompt3_qa_sk|0/579d61d41168b7f2/GENERATIVE.parquet",
"local": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/multi_wiki_qa.prompt3_qa_sk%7C0/579d61d41168b7f2/GENERATIVE.parquet",
"size": 101814277,
"type": "file"
},
{
"original": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_sklep.prompt2_qa_sk:question-answering|0_2026-10-22T21-55-04.268099.parquet",
"local": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_sklep.prompt2_qa_sk%3Aquestion-answering%7C0_2026-10-22T21-55-04.268099.parquet",
"size": 66791884,
"type": "file"
},
{
"original": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_sklep.prompt1_qa_sk:question-answering|0_2026-10-22T21-55-04.268099.parquet",
"local": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_sklep.prompt1_qa_sk%3Aquestion-answering%7C0_2026-10-22T21-55-04.268099.parquet",
"size": 66012897,
"type": "file"
},
{
"original": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_sklep.prompt3_qa_sk:question-answering|0_2026-10-22T21-55-04.268099.parquet",
"local": "skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/details/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/2026-10-22T21-55-04.268099/details_sklep.prompt3_qa_sk%3Aquestion-answering%7C0_2026-10-22T21-55-04.268099.parquet",
"size": 64169583,
"type": "file"
},
{
"original": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/sklep.prompt2_qa_sk:question-answering|0/46d75c2a99a95ed9/GENERATIVE.parquet",
"local": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/sklep.prompt2_qa_sk%3Aquestion-answering%7C0/46d75c2a99a95ed9/GENERATIVE.parquet",
"size": 53746461,
"type": "file"
},
{
"original": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/sklep.prompt1_qa_sk:question-answering|0/b09ec46c034c8de4/GENERATIVE.parquet",
"local": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/sklep.prompt1_qa_sk%3Aquestion-answering%7C0/b09ec46c034c8de4/GENERATIVE.parquet",
"size": 53089807,
"type": "file"
},
{
"original": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/sklep.prompt3_qa_sk:question-answering|0/06ebedbab75fe49b/GENERATIVE.parquet",
"local": "skbench_evaluation/models/aya_300k_lr_0p00010/d0e7048bfa3b2274/sklep.prompt3_qa_sk%3Aquestion-answering%7C0/06ebedbab75fe49b/GENERATIVE.parquet",
"size": 51637093,
"type": "file"
}
]
}

View File

@ -1,234 +0,0 @@
"""Curate the completed 300k learning-rate SK-bench run without copying raw data.
Requires Python 3.10+ and pyarrow (installed separately). The only read of the
large details parquets projects model_response.truncated_tokens_count; row counts
come from Parquet metadata. Cached GENERATIVE.parquet files are never read.
"""
from __future__ import annotations
import argparse
import collections
import csv
import hashlib
import json
import pathlib
import re
import shutil
import statistics
import sys
from urllib.parse import unquote
def write_csv(path, rows):
if not rows:
return
columns = list(dict.fromkeys(k for row in rows for k in row))
with path.open('w', newline='', encoding='utf-8') as stream:
writer = csv.DictWriter(stream, fieldnames=columns)
writer.writeheader()
writer.writerows(rows)
def normalize(name):
name = unquote(name.strip())
return re.sub(r'\|([0-9]+)$', r':\1', name)
def get_lines(path):
return [line.strip() for line in path.read_text(encoding='utf-8').splitlines() if line.strip() and not line.startswith('#')]
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--source', type=pathlib.Path, required=True, help='Extracted archive root containing skbench_evaluation/')
parser.add_argument('--output', type=pathlib.Path, required=True)
parser.add_argument('--pyarrow-path', type=pathlib.Path, help='Optional project-local pip --target directory')
args = parser.parse_args()
if args.pyarrow_path:
sys.path.insert(0, str(args.pyarrow_path.resolve()))
import pyarrow
import pyarrow.parquet as pq
source = args.source.resolve()
out = args.output.resolve()
base = source / 'skbench_evaluation'
run_name = 'sk_zero_available_without_nli_lr_0p00010_20261022_185255'
run = base / 'results' / run_name
for name in ['results', 'logs', 'configs', 'provenance']:
(out/name).mkdir(parents=True, exist_ok=True)
result_path = run/'results/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/results_2026-10-22T21-55-04.268099.json'
d = json.loads(result_path.read_text(encoding='utf-8'))
tasks = get_lines(run/'tasks.txt')
omitted = get_lines(run/'omitted_tasks.txt')
configs = d['config_tasks']
normalized_expected = {normalize(x) for x in tasks}
assert len(tasks) == len(normalized_expected) == 222
assert normalized_expected == {normalize(x) for x in configs}, 'Config task coverage mismatch'
assert normalized_expected <= {normalize(x) for x in d['results']}, 'Result task coverage mismatch'
assert len(omitted) == 190
all_tasks = get_lines(base/'configs/tasks_sk_zero.txt')
assert normalized_expected.isdisjoint({normalize(x) for x in omitted})
assert normalized_expected | {normalize(x) for x in omitted} == {normalize(x) for x in all_tasks}
copies = {result_path: out/'results'/result_path.name,
base/'logs'/f'{run_name}.log': out/'logs'/f'{run_name}.log',
run/'tasks.txt': out/'configs/tasks.txt',
run/'omitted_tasks.txt': out/'configs/omitted_tasks.txt',
run/'uv.lock': out/'provenance/uv.lock',
run/'skbench_commit.txt': out/'provenance/skbench_commit.txt',
source/'archive_summary.json': out/'provenance/archive_summary.json'}
for path in sorted((base/'configs').iterdir()):
if path.is_file():
copies[path] = out/'configs'/path.name
provenance = []
for src, dst in copies.items():
shutil.copyfile(src, dst)
data = src.read_bytes()
provenance.append({'source_archive_member': src.relative_to(source).as_posix(),
'curated_path': dst.relative_to(out).as_posix(),
'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()})
write_csv(out/'provenance/copied_files_sha256.csv', provenance)
(out/'configs/model_config.json').write_text(json.dumps(d['config_general'], indent=2, ensure_ascii=False)+'\n', encoding='utf-8')
(out/'configs/task_configs.json').write_text(json.dumps(configs, indent=2, ensure_ascii=False)+'\n', encoding='utf-8')
# Resolve the original names from the extraction manifest; Windows paths
# encode ':' and '|' as %3A and %7C, while payload bytes were unchanged.
manifest = json.loads((source/'archive_manifest.json').read_text(encoding='utf-8'))
if isinstance(manifest, dict):
manifest = manifest.get('entries', manifest.get('files', []))
original_paths = {x['local']: x['original'] for x in manifest if isinstance(x, dict) and 'local' in x}
details = []
lookup = {}
files = sorted((run/'details').rglob('*.parquet'))
assert len(files) == 222, f'Expected 222 DETAILS files, got {len(files)}'
for file in files:
decoded = unquote(file.name)
task = re.match(r'^details_(.+)_2026-10-22T21-55-04\.268099\.parquet$', decoded).group(1)
pf = pq.ParquetFile(file)
projected = pf.read(columns=['model_response.truncated_tokens_count'])
values = projected.column('model_response').combine_chunks().field('truncated_tokens_count').to_pylist()
assert len(values) == pf.metadata.num_rows
assert all(v is None or (isinstance(v, int) and v >= 0) for v in values)
row = {'task': task, 'sample_count': pf.metadata.num_rows,
'truncation_values_present': sum(v is not None for v in values),
'truncation_null_values': sum(v is None for v in values),
'samples_with_truncation': sum(v is not None and v > 0 for v in values),
'truncated_tokens_total': sum(v or 0 for v in values),
'max_truncated_tokens_per_sample': max((v or 0 for v in values), default=0),
'parquet_bytes': file.stat().st_size,
'source_archive_member': original_paths.get(file.relative_to(source).as_posix(), file.relative_to(source).as_posix()),
'extracted_relative_path': file.relative_to(source).as_posix()}
assert normalize(task) not in lookup
lookup[normalize(task)] = row
details.append(row)
assert set(lookup) == normalized_expected, 'DETAILS task coverage mismatch'
write_csv(out/'results/truncation_audit_per_task.csv', details)
metric_names = sorted({key for task in configs for key in d['results'][task]})
per_task = []
for task in sorted(configs):
metric = d['results'][task]
config = configs[task]
detail = lookup[normalize(task)]
primary = next((name for name in ['em_relaxed', 'em_norm_relaxed', 'exact_match_slk_prefix'] if name in metric), None)
family = task.split('.prompt')[0]
prompt = int(re.search(r'\.prompt([123])_', task).group(1))
task_group = re.sub(r'\.prompt[123]_', '.', task).removesuffix('|0')
row = {'task': task, 'family': family, 'task_group_without_prompt': task_group,
'prompt': prompt, 'num_fewshots': config['num_fewshots'], 'sample_count': detail['sample_count'],
'primary_metric': primary, 'primary_value': metric[primary],
'generation_size': config['generation_size'], 'evaluation_splits': '|'.join(config['evaluation_splits']),
'hf_repo': config['hf_repo'], 'hf_subset': config['hf_subset'], 'hf_revision': config['hf_revision']}
row.update({key: metric.get(key, '') for key in metric_names})
per_task.append(row)
write_csv(out/'results/per_task_metrics.csv', per_task)
# Each summary groups only identical metrics; values remain 0..1.
# Macro means weight task variants equally. Sample-weighted means weight
# their actual DETAILS rows. Repeated prompts are evaluation instances,
# never additional independent underlying test questions.
def summarize(group_columns, filename):
groups = collections.defaultdict(list)
for row in per_task:
for metric_name in metric_names:
if not metric_name.endswith('_stderr') and row[metric_name] != '':
groups[tuple(row[x] for x in group_columns)+(metric_name,)].append(row)
result = []
for key, rows in sorted(groups.items()):
metric_name = key[-1]
total = sum(x['sample_count'] for x in rows)
item = dict(zip(group_columns, key[:-1]))
item.update({'metric': metric_name, 'task_variants': len(rows),
'prompt_count': len({x['prompt'] for x in rows}),
'evaluated_instances': total,
'task_macro_mean': statistics.mean(x[metric_name] for x in rows),
'sample_weighted_mean': sum(x['sample_count']*x[metric_name] for x in rows)/total,
'min_task_value': min(x[metric_name] for x in rows),
'max_task_value': max(x[metric_name] for x in rows)})
result.append(item)
write_csv(out/'results'/filename, result)
return result
family_summary = summarize(['family'], 'family_summary.csv')
summarize(['family', 'prompt'], 'family_prompt_summary.csv')
three_prompt = summarize(['family', 'task_group_without_prompt'], 'three_prompt_summary.csv')
assert all(x['task_variants'] == x['prompt_count'] == 3 for x in three_prompt)
access = json.loads((base/'configs/dataset_access_report.json').read_text(encoding='utf-8'))
inaccessible = [x for x in access if x['status'] != 'OK']
with (base/'logs'/f'{run_name}.log').open(encoding='utf-8', newline='') as stream:
log_text = stream.read()
truncation_warnings = re.findall(r'context_size \+ max_new_tokens=\d+[^\r\n]*Truncating context to \d+ tokens\.', log_text)
warning_evidence = []
for line_number, line in enumerate(log_text.split('\n'), 1):
if 'Truncating context' in line:
warning_evidence.append({'line_number': line_number, 'message': line[line.index('context_size'):], 'source': f'logs/{run_name}.log'})
(out/'results/log_truncation_evidence.json').write_text(json.dumps(warning_evidence, indent=2, ensure_ascii=False)+'\n', encoding='utf-8')
summary = {'run_name': run_name, 'result_file': result_path.name,
'task_list_count': len(tasks), 'configured_tasks': len(configs), 'scored_task_variants': len(per_task),
'result_json_keys': len(d['results']),
'extra_result_keys_excluded_from_task_summaries': sorted(set(d['results'])-set(configs)),
'all_original_task_variants': len(all_tasks),
'omitted_task_variants': len(omitted), 'inaccessible_repositories': len(inaccessible),
'inaccessible_task_variants': sum(len(x['tasks']) for x in inaccessible),
'additionally_excluded_nli_task_variants': 3,
'families': dict(sorted(collections.Counter(row['family'] for row in per_task).items())),
'prompt_counts': dict(sorted(collections.Counter(row['prompt'] for row in per_task).items())),
'evaluated_instances': sum(row['sample_count'] for row in per_task),
'instances_by_prompt': {str(prompt): sum(x['sample_count'] for x in per_task if x['prompt'] == prompt) for prompt in [1,2,3]},
'details_files_audited': len(details), 'truncation_column': 'model_response.truncated_tokens_count',
'truncation_values_present': sum(x['truncation_values_present'] for x in details),
'truncation_null_values': sum(x['truncation_null_values'] for x in details),
'details_reported_samples_with_truncation': sum(x['samples_with_truncation'] for x in details),
'details_reported_truncated_tokens_total': sum(x['truncated_tokens_total'] for x in details),
'details_reported_max_truncated_tokens_per_sample': max(x['max_truncated_tokens_per_sample'] for x in details),
'context_truncation_observed_in_log': bool(truncation_warnings),
'actual_truncated_sample_count': None,
'console_context_truncation_warning_count': len(truncation_warnings),
'console_context_truncation_warnings': truncation_warnings,
'truncation_interpretation': 'All DETAILS counters are zero, but the console explicitly reports context truncation. Do not infer no truncation or an affected-sample count from these counters.',
'model_config': d['config_general']['model_config'],
'max_samples': d['config_general']['max_samples'],
'generation_size_counts': dict(collections.Counter(str(x['generation_size']) for x in per_task)),
'original_summary_general': d['summary_general'],
'pyarrow_version': pyarrow.__version__, 'python_version': sys.version,
'aggregation': 'Descriptive metric-specific task macro means and sample-weighted means; no official full-SK-bench overall score.',
'limitations': ['Partial available zero-shot subset: 222 of 412 task variants.',
'Only the validation-selected LR=0.00010 was benchmarked.',
'Sample counts are evaluation instances; prompt variants reuse underlying questions.',
'One console warning reports context truncation; all DETAILS counters are zero, so the recorded counters do not reliably enumerate affected inputs.',
'The audit cannot recover the number of affected tasks/samples or quantify output generation-size termination.',
'All-zero summary counters include non_truncated=0 and cannot prove absence of truncation.',
'Raw DETAILS and generation-cache parquets are excluded from this curated tree.']}
(out/'results/audit_summary.json').write_text(json.dumps(summary, indent=2, ensure_ascii=False)+'\n', encoding='utf-8')
script_destination = out/'provenance/audit_skbench.py'
if pathlib.Path(__file__).resolve() != script_destination.resolve():
shutil.copyfile(pathlib.Path(__file__), script_destination)
print(json.dumps({key: summary[key] for key in ['scored_task_variants', 'evaluated_instances', 'instances_by_prompt', 'details_reported_samples_with_truncation', 'context_truncation_observed_in_log', 'actual_truncated_sample_count', 'truncation_null_values', 'families']}, indent=2))
print('Primary family macro means (metrics kept separate):')
for row in family_summary:
if row['metric'] in ['em_relaxed', 'em_norm_relaxed', 'exact_match_slk_prefix', 'f1_slk']:
print(row)
if __name__ == '__main__':
main()

View File

@ -1,14 +0,0 @@
source_archive_member,curated_path,bytes,sha256
skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/results/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/results_2026-10-22T21-55-04.268099.json,results/results_2026-10-22T21-55-04.268099.json,638180,966123dc20b547860d04f3434f65752c681ca2d83baebee22873e553161ff0df
skbench_evaluation/logs/sk_zero_available_without_nli_lr_0p00010_20261022_185255.log,logs/sk_zero_available_without_nli_lr_0p00010_20261022_185255.log,4537535,23a857210201913c5506ac39553a86fd803ed0c057e1226fcd978030a40b6c78
skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/tasks.txt,configs/tasks.txt,11415,297c7185d8ddea6899d20287ed5cffb895116cf756121252a0e76070b248db76
skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/omitted_tasks.txt,configs/omitted_tasks.txt,8629,613b78472e6788eab826f31da1100c00b597ed9bbc8151af38ebb8ef5bf830af
skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/uv.lock,provenance/uv.lock,690556,045d2840fda141981afba93bd4a1b9ddb59f0f0791c162cf66b2c88e6491fb41
skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/skbench_commit.txt,provenance/skbench_commit.txt,41,12655509d516c6a57225a072f708e5ca854600e7daa3bf5cdc95e6b36e94fe70
archive_summary.json,provenance/archive_summary.json,6529,535390044cd67477ea1631527ac736f72108935f25a11a613b1709caf8154957
skbench_evaluation/configs/dataset_access_report.json,configs/dataset_access_report.json,29828,8eea8c082d1eb914850128d48021a39c7e1fb7189578c5f1e496004af6ff593b
skbench_evaluation/configs/export_lr_0p00010.yaml,configs/export_lr_0p00010.yaml,391,bff3e0b8abd130122c8d88be71647e0ea67e4a836b3caaed4e3bc307ef267dca
skbench_evaluation/configs/tasks_sk_zero.txt,configs/tasks_sk_zero.txt,20044,25c3cdfeb1f46adb86b68be24a9d8e22439733501e2fffda1ce5034e610660a4
skbench_evaluation/configs/tasks_sk_zero_available.txt,configs/tasks_sk_zero_available.txt,11517,5ce7f1666b2073afd93aab03a116937f48954cf51d313c567c198b31f0dfcaf2
skbench_evaluation/configs/tasks_sk_zero_available_without_nli.txt,configs/tasks_sk_zero_available_without_nli.txt,11415,297c7185d8ddea6899d20287ed5cffb895116cf756121252a0e76070b248db76
skbench_evaluation/configs/tasks_sk_zero_unavailable.txt,configs/tasks_sk_zero_unavailable.txt,8527,0071cffec8ab2446a5594d0b3a3116151e7fc375bb300394e9ea7cb91ed7df10
1 source_archive_member curated_path bytes sha256
2 skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/results/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010/results_2026-10-22T21-55-04.268099.json results/results_2026-10-22T21-55-04.268099.json 638180 966123dc20b547860d04f3434f65752c681ca2d83baebee22873e553161ff0df
3 skbench_evaluation/logs/sk_zero_available_without_nli_lr_0p00010_20261022_185255.log logs/sk_zero_available_without_nli_lr_0p00010_20261022_185255.log 4537535 23a857210201913c5506ac39553a86fd803ed0c057e1226fcd978030a40b6c78
4 skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/tasks.txt configs/tasks.txt 11415 297c7185d8ddea6899d20287ed5cffb895116cf756121252a0e76070b248db76
5 skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/omitted_tasks.txt configs/omitted_tasks.txt 8629 613b78472e6788eab826f31da1100c00b597ed9bbc8151af38ebb8ef5bf830af
6 skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/uv.lock provenance/uv.lock 690556 045d2840fda141981afba93bd4a1b9ddb59f0f0791c162cf66b2c88e6491fb41
7 skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255/skbench_commit.txt provenance/skbench_commit.txt 41 12655509d516c6a57225a072f708e5ca854600e7daa3bf5cdc95e6b36e94fe70
8 archive_summary.json provenance/archive_summary.json 6529 535390044cd67477ea1631527ac736f72108935f25a11a613b1709caf8154957
9 skbench_evaluation/configs/dataset_access_report.json configs/dataset_access_report.json 29828 8eea8c082d1eb914850128d48021a39c7e1fb7189578c5f1e496004af6ff593b
10 skbench_evaluation/configs/export_lr_0p00010.yaml configs/export_lr_0p00010.yaml 391 bff3e0b8abd130122c8d88be71647e0ea67e4a836b3caaed4e3bc307ef267dca
11 skbench_evaluation/configs/tasks_sk_zero.txt configs/tasks_sk_zero.txt 20044 25c3cdfeb1f46adb86b68be24a9d8e22439733501e2fffda1ce5034e610660a4
12 skbench_evaluation/configs/tasks_sk_zero_available.txt configs/tasks_sk_zero_available.txt 11517 5ce7f1666b2073afd93aab03a116937f48954cf51d313c567c198b31f0dfcaf2
13 skbench_evaluation/configs/tasks_sk_zero_available_without_nli.txt configs/tasks_sk_zero_available_without_nli.txt 11415 297c7185d8ddea6899d20287ed5cffb895116cf756121252a0e76070b248db76
14 skbench_evaluation/configs/tasks_sk_zero_unavailable.txt configs/tasks_sk_zero_unavailable.txt 8527 0071cffec8ab2446a5594d0b3a3116151e7fc375bb300394e9ea7cb91ed7df10

View File

@ -1,62 +0,0 @@
"""Inspect token-array and raw-prompt lengths; never export prompt content."""
import argparse, csv, json, pathlib, re, shutil, statistics, sys
from urllib.parse import unquote
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--source',type=pathlib.Path,required=True)
parser.add_argument('--output',type=pathlib.Path,required=True)
parser.add_argument('--pyarrow-path',type=pathlib.Path)
args=parser.parse_args()
if args.pyarrow_path: sys.path.insert(0,str(args.pyarrow_path.resolve()))
import pyarrow.parquet as pq
run=args.source/'skbench_evaluation/results/sk_zero_available_without_nli_lr_0p00010_20261022_185255'
d=json.loads(next((run/'results').rglob('*.json')).read_text())
limit=d['config_general']['model_config']['max_model_length']
rows=[]
outliers=[]
for file in sorted((run/'details').rglob('*.parquet')):
task=re.match(r'details_(.+)_2026-10-22T21-55-04\.268099\.parquet',unquote(file.name)).group(1)
cfg=d['config_tasks'][task]
budget=limit-cfg['generation_size']
data=pq.ParquetFile(file).read(columns=['model_response.input_tokens','model_response.input'])
data=data.column('model_response').combine_chunks()
tokens=data.field('input_tokens').to_pylist()
texts=data.field('input').to_pylist()
lens=[None if value is None else len(value) for value in tokens]
chars=[None if value is None else len(value) for value in texts]
row={'task':task,'generation_size':cfg['generation_size'],'context_limit':limit,'input_budget':budget,
'samples':len(lens),'null_token_arrays':sum(x is None for x in lens),'null_input_strings':sum(x is None for x in chars),
'min_recorded_input_tokens':min(x for x in lens if x is not None),
'max_recorded_input_tokens':max(x for x in lens if x is not None),
'mean_recorded_input_tokens':statistics.mean(x for x in lens if x is not None),
'arrays_at_input_budget':sum(x==budget for x in lens),
'arrays_over_input_budget':sum(x is not None and x>budget for x in lens),
'max_recorded_input_characters':max(x for x in chars if x is not None)}
rows.append(row)
for index,length in enumerate(lens):
if length is not None and length>=budget:
outliers.append({'task':task,'details_row_index_zero_based':index,'input_token_array_length':length,
'generation_size':cfg['generation_size'],'input_budget':budget,
'recorded_input_characters':chars[index]})
for name,values in [('input_length_diagnostics_per_task.csv',rows),('input_length_budget_boundary_rows.csv',outliers)]:
with (args.output/name).open('w',newline='',encoding='utf-8') as f:
writer=csv.DictWriter(f,fieldnames=list(values[0]) if values else ['task'])
writer.writeheader();writer.writerows(values)
with (args.source/'skbench_evaluation/logs/sk_zero_available_without_nli_lr_0p00010_20261022_185255.log').open(encoding='utf-8',newline='') as stream:
log=stream.read()
messages=[]
for number,line in enumerate(log.split('\n'),1):
if re.search(r'truncat',line,re.I):
messages.append({'log_lf_line_number':number,'message':re.sub(r'\x1b\[[0-9;]*[A-Za-z]','',line).strip()[-1500:]})
summary={'task_count':len(rows),'evaluated_instances':sum(x['samples'] for x in rows),
'max_recorded_input_tokens':max(x['max_recorded_input_tokens'] for x in rows),
'arrays_at_input_budget':sum(x['arrays_at_input_budget'] for x in rows),
'arrays_over_input_budget':sum(x['arrays_over_input_budget'] for x in rows),
'log_messages_matching_truncat_case_insensitive':messages,
'limitation':'Input strings and token arrays are recorded artifacts, not a separately tokenized original source prompt. Their lengths cannot recover how much text was discarded or establish the number of truly truncated inputs.'}
(args.output/'input_length_diagnostics_summary.json').write_text(json.dumps(summary,indent=2,ensure_ascii=False)+'\n',encoding='utf-8')
print(json.dumps(summary,indent=2,ensure_ascii=False))
print('BOUNDARY TASK COUNTS',json.dumps({task:sum(row['task']==task for row in outliers) for task in sorted({row['task'] for row in outliers})}))
script_destination=args.output.parent/'provenance/input_length_diagnostics.py'
if pathlib.Path(__file__).resolve()!=script_destination.resolve():
shutil.copyfile(pathlib.Path(__file__),script_destination)

View File

@ -1 +0,0 @@
15823bbcc2d995e69441fcb7d34abb61bd8180c5

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
{
"source_archive": "aya_300k_benchmarky_20261024_215708.tar.gz",
"sha256": "b45e431cbc63bc73ef953f8aa3837695ccec43783e3da2dfccb0d99f7d1fe79c",
"compressed_bytes": 349555561,
"scope": "Hruska Aya 300k learning-rate selection and evaluation of selected LR 0.00010; Titan excluded",
"base_model": "slovak-nlp/mistral-sk-7b",
"base_model_revision": "089497ae0d72018e9591895c54f774bf0b4a83a4",
"selection_criterion": "lowest final validation loss among the six completed 300k runs",
"intended_next_stage": "planned training on the full Aya dataset on Perun; not executed in this experiment",
"data_reproducibility_limit": "No source dataset revision, data-file checksum, or held-out sample IDs were included in this archive",
"curation": "Model weights, checkpoints, trainer_state.json, duplicated inference caches and full parquet details excluded from the Git subset. Original archive retained separately."
}

View File

@ -1,115 +0,0 @@
learning_rate,run,step,eval_loss
8e-05,lr_0p00008,1000,1.0020490884780884
8e-05,lr_0p00008,2000,0.9672194719314575
8e-05,lr_0p00008,3000,0.9505742192268372
8e-05,lr_0p00008,4000,0.9352602362632751
8e-05,lr_0p00008,5000,0.9294734597206116
8e-05,lr_0p00008,6000,0.9264867305755615
8e-05,lr_0p00008,7000,0.9184143543243408
8e-05,lr_0p00008,8000,0.9120934009552002
8e-05,lr_0p00008,9000,0.9065558910369873
8e-05,lr_0p00008,10000,0.9004696011543274
8e-05,lr_0p00008,11000,0.8929902911186218
8e-05,lr_0p00008,12000,0.8897570371627808
8e-05,lr_0p00008,13000,0.8844991326332092
8e-05,lr_0p00008,14000,0.8800909519195557
8e-05,lr_0p00008,15000,0.8777939677238464
8e-05,lr_0p00008,16000,0.8767354488372803
8e-05,lr_0p00008,17000,0.875752329826355
8e-05,lr_0p00008,18000,0.875270426273346
8e-05,lr_0p00008,18688,0.875216543674469
0.0001,lr_0p00010,1000,1.0004310607910156
0.0001,lr_0p00010,2000,0.9658941626548767
0.0001,lr_0p00010,3000,0.9526628255844116
0.0001,lr_0p00010,4000,0.9393344521522522
0.0001,lr_0p00010,5000,0.9336668848991394
0.0001,lr_0p00010,6000,0.931794285774231
0.0001,lr_0p00010,7000,0.9227241277694702
0.0001,lr_0p00010,8000,0.9158084392547607
0.0001,lr_0p00010,9000,0.9100468158721924
0.0001,lr_0p00010,10000,0.9019826650619507
0.0001,lr_0p00010,11000,0.8941853642463684
0.0001,lr_0p00010,12000,0.8896107077598572
0.0001,lr_0p00010,13000,0.8851001262664795
0.0001,lr_0p00010,14000,0.8795706033706665
0.0001,lr_0p00010,15000,0.8770407438278198
0.0001,lr_0p00010,16000,0.8748454451560974
0.0001,lr_0p00010,17000,0.8731834888458252
0.0001,lr_0p00010,18000,0.8727287650108337
0.0001,lr_0p00010,18688,0.87261962890625
0.00015,lr_0p00015,1000,1.0024861097335815
0.00015,lr_0p00015,2000,0.9763674139976501
0.00015,lr_0p00015,3000,0.97147536277771
0.00015,lr_0p00015,4000,0.9657827019691467
0.00015,lr_0p00015,5000,0.9659448266029358
0.00015,lr_0p00015,6000,0.9597828388214111
0.00015,lr_0p00015,7000,0.951335608959198
0.00015,lr_0p00015,8000,0.9469588994979858
0.00015,lr_0p00015,9000,0.9383289813995361
0.00015,lr_0p00015,10000,0.9309172630310059
0.00015,lr_0p00015,11000,0.9210461974143982
0.00015,lr_0p00015,12000,0.9106600284576416
0.00015,lr_0p00015,13000,0.9036438465118408
0.00015,lr_0p00015,14000,0.8952069878578186
0.00015,lr_0p00015,15000,0.8909939527511597
0.00015,lr_0p00015,16000,0.8871906995773315
0.00015,lr_0p00015,17000,0.8851967453956604
0.00015,lr_0p00015,18000,0.8842737674713135
0.00015,lr_0p00015,18688,0.8842697143554688
0.00018,lr_0p00018,1000,0.9958739280700684
0.00018,lr_0p00018,2000,0.9904810786247253
0.00018,lr_0p00018,3000,0.9867064356803894
0.00018,lr_0p00018,4000,0.9833324551582336
0.00018,lr_0p00018,5000,0.9868490099906921
0.00018,lr_0p00018,6000,0.9755926728248596
0.00018,lr_0p00018,7000,0.9768977761268616
0.00018,lr_0p00018,8000,0.9687609076499939
0.00018,lr_0p00018,9000,0.9562658071517944
0.00018,lr_0p00018,10000,0.9435049891471863
0.00018,lr_0p00018,11000,0.9342814683914185
0.00018,lr_0p00018,12000,0.922635018825531
0.00018,lr_0p00018,13000,0.9130367636680603
0.00018,lr_0p00018,14000,0.904951810836792
0.00018,lr_0p00018,15000,0.8994976878166199
0.00018,lr_0p00018,16000,0.8953551650047302
0.00018,lr_0p00018,17000,0.8925029039382935
0.00018,lr_0p00018,18000,0.891387939453125
0.00018,lr_0p00018,18688,0.8914602994918823
0.0002,lr_0p00020,1000,0.9974449276924133
0.0002,lr_0p00020,2000,0.9973769783973694
0.0002,lr_0p00020,3000,1.0056378841400146
0.0002,lr_0p00020,4000,0.9973607063293457
0.0002,lr_0p00020,5000,1.0010013580322266
0.0002,lr_0p00020,6000,1.000449776649475
0.0002,lr_0p00020,7000,0.9865806698799133
0.0002,lr_0p00020,8000,0.9824715852737427
0.0002,lr_0p00020,9000,0.9666008353233337
0.0002,lr_0p00020,10000,0.9573416709899902
0.0002,lr_0p00020,11000,0.9432744383811951
0.0002,lr_0p00020,12000,0.9326162338256836
0.0002,lr_0p00020,13000,0.9201604127883911
0.0002,lr_0p00020,14000,0.9126585721969604
0.0002,lr_0p00020,15000,0.907073438167572
0.0002,lr_0p00020,16000,0.9014313817024231
0.0002,lr_0p00020,17000,0.8986518979072571
0.0002,lr_0p00020,18000,0.897506594657898
0.0002,lr_0p00020,18688,0.8976690173149109
0.00023,lr_0p00023,1000,1.0002912282943726
0.00023,lr_0p00023,2000,1.0145149230957031
0.00023,lr_0p00023,3000,1.0228914022445679
0.00023,lr_0p00023,4000,1.0323290824890137
0.00023,lr_0p00023,5000,1.0345656871795654
0.00023,lr_0p00023,6000,1.0246530771255493
0.00023,lr_0p00023,7000,1.0160919427871704
0.00023,lr_0p00023,8000,1.0105783939361572
0.00023,lr_0p00023,9000,0.9934014678001404
0.00023,lr_0p00023,10000,0.980603039264679
0.00023,lr_0p00023,11000,0.963624119758606
0.00023,lr_0p00023,12000,0.951417088508606
0.00023,lr_0p00023,13000,0.9340505599975586
0.00023,lr_0p00023,14000,0.9227956533432007
0.00023,lr_0p00023,15000,0.9158667325973511
0.00023,lr_0p00023,16000,0.908878743648529
0.00023,lr_0p00023,17000,0.9046502709388733
0.00023,lr_0p00023,18000,0.9031931161880493
0.00023,lr_0p00023,18688,0.9032362699508667
1 learning_rate run step eval_loss
2 8e-05 lr_0p00008 1000 1.0020490884780884
3 8e-05 lr_0p00008 2000 0.9672194719314575
4 8e-05 lr_0p00008 3000 0.9505742192268372
5 8e-05 lr_0p00008 4000 0.9352602362632751
6 8e-05 lr_0p00008 5000 0.9294734597206116
7 8e-05 lr_0p00008 6000 0.9264867305755615
8 8e-05 lr_0p00008 7000 0.9184143543243408
9 8e-05 lr_0p00008 8000 0.9120934009552002
10 8e-05 lr_0p00008 9000 0.9065558910369873
11 8e-05 lr_0p00008 10000 0.9004696011543274
12 8e-05 lr_0p00008 11000 0.8929902911186218
13 8e-05 lr_0p00008 12000 0.8897570371627808
14 8e-05 lr_0p00008 13000 0.8844991326332092
15 8e-05 lr_0p00008 14000 0.8800909519195557
16 8e-05 lr_0p00008 15000 0.8777939677238464
17 8e-05 lr_0p00008 16000 0.8767354488372803
18 8e-05 lr_0p00008 17000 0.875752329826355
19 8e-05 lr_0p00008 18000 0.875270426273346
20 8e-05 lr_0p00008 18688 0.875216543674469
21 0.0001 lr_0p00010 1000 1.0004310607910156
22 0.0001 lr_0p00010 2000 0.9658941626548767
23 0.0001 lr_0p00010 3000 0.9526628255844116
24 0.0001 lr_0p00010 4000 0.9393344521522522
25 0.0001 lr_0p00010 5000 0.9336668848991394
26 0.0001 lr_0p00010 6000 0.931794285774231
27 0.0001 lr_0p00010 7000 0.9227241277694702
28 0.0001 lr_0p00010 8000 0.9158084392547607
29 0.0001 lr_0p00010 9000 0.9100468158721924
30 0.0001 lr_0p00010 10000 0.9019826650619507
31 0.0001 lr_0p00010 11000 0.8941853642463684
32 0.0001 lr_0p00010 12000 0.8896107077598572
33 0.0001 lr_0p00010 13000 0.8851001262664795
34 0.0001 lr_0p00010 14000 0.8795706033706665
35 0.0001 lr_0p00010 15000 0.8770407438278198
36 0.0001 lr_0p00010 16000 0.8748454451560974
37 0.0001 lr_0p00010 17000 0.8731834888458252
38 0.0001 lr_0p00010 18000 0.8727287650108337
39 0.0001 lr_0p00010 18688 0.87261962890625
40 0.00015 lr_0p00015 1000 1.0024861097335815
41 0.00015 lr_0p00015 2000 0.9763674139976501
42 0.00015 lr_0p00015 3000 0.97147536277771
43 0.00015 lr_0p00015 4000 0.9657827019691467
44 0.00015 lr_0p00015 5000 0.9659448266029358
45 0.00015 lr_0p00015 6000 0.9597828388214111
46 0.00015 lr_0p00015 7000 0.951335608959198
47 0.00015 lr_0p00015 8000 0.9469588994979858
48 0.00015 lr_0p00015 9000 0.9383289813995361
49 0.00015 lr_0p00015 10000 0.9309172630310059
50 0.00015 lr_0p00015 11000 0.9210461974143982
51 0.00015 lr_0p00015 12000 0.9106600284576416
52 0.00015 lr_0p00015 13000 0.9036438465118408
53 0.00015 lr_0p00015 14000 0.8952069878578186
54 0.00015 lr_0p00015 15000 0.8909939527511597
55 0.00015 lr_0p00015 16000 0.8871906995773315
56 0.00015 lr_0p00015 17000 0.8851967453956604
57 0.00015 lr_0p00015 18000 0.8842737674713135
58 0.00015 lr_0p00015 18688 0.8842697143554688
59 0.00018 lr_0p00018 1000 0.9958739280700684
60 0.00018 lr_0p00018 2000 0.9904810786247253
61 0.00018 lr_0p00018 3000 0.9867064356803894
62 0.00018 lr_0p00018 4000 0.9833324551582336
63 0.00018 lr_0p00018 5000 0.9868490099906921
64 0.00018 lr_0p00018 6000 0.9755926728248596
65 0.00018 lr_0p00018 7000 0.9768977761268616
66 0.00018 lr_0p00018 8000 0.9687609076499939
67 0.00018 lr_0p00018 9000 0.9562658071517944
68 0.00018 lr_0p00018 10000 0.9435049891471863
69 0.00018 lr_0p00018 11000 0.9342814683914185
70 0.00018 lr_0p00018 12000 0.922635018825531
71 0.00018 lr_0p00018 13000 0.9130367636680603
72 0.00018 lr_0p00018 14000 0.904951810836792
73 0.00018 lr_0p00018 15000 0.8994976878166199
74 0.00018 lr_0p00018 16000 0.8953551650047302
75 0.00018 lr_0p00018 17000 0.8925029039382935
76 0.00018 lr_0p00018 18000 0.891387939453125
77 0.00018 lr_0p00018 18688 0.8914602994918823
78 0.0002 lr_0p00020 1000 0.9974449276924133
79 0.0002 lr_0p00020 2000 0.9973769783973694
80 0.0002 lr_0p00020 3000 1.0056378841400146
81 0.0002 lr_0p00020 4000 0.9973607063293457
82 0.0002 lr_0p00020 5000 1.0010013580322266
83 0.0002 lr_0p00020 6000 1.000449776649475
84 0.0002 lr_0p00020 7000 0.9865806698799133
85 0.0002 lr_0p00020 8000 0.9824715852737427
86 0.0002 lr_0p00020 9000 0.9666008353233337
87 0.0002 lr_0p00020 10000 0.9573416709899902
88 0.0002 lr_0p00020 11000 0.9432744383811951
89 0.0002 lr_0p00020 12000 0.9326162338256836
90 0.0002 lr_0p00020 13000 0.9201604127883911
91 0.0002 lr_0p00020 14000 0.9126585721969604
92 0.0002 lr_0p00020 15000 0.907073438167572
93 0.0002 lr_0p00020 16000 0.9014313817024231
94 0.0002 lr_0p00020 17000 0.8986518979072571
95 0.0002 lr_0p00020 18000 0.897506594657898
96 0.0002 lr_0p00020 18688 0.8976690173149109
97 0.00023 lr_0p00023 1000 1.0002912282943726
98 0.00023 lr_0p00023 2000 1.0145149230957031
99 0.00023 lr_0p00023 3000 1.0228914022445679
100 0.00023 lr_0p00023 4000 1.0323290824890137
101 0.00023 lr_0p00023 5000 1.0345656871795654
102 0.00023 lr_0p00023 6000 1.0246530771255493
103 0.00023 lr_0p00023 7000 1.0160919427871704
104 0.00023 lr_0p00023 8000 1.0105783939361572
105 0.00023 lr_0p00023 9000 0.9934014678001404
106 0.00023 lr_0p00023 10000 0.980603039264679
107 0.00023 lr_0p00023 11000 0.963624119758606
108 0.00023 lr_0p00023 12000 0.951417088508606
109 0.00023 lr_0p00023 13000 0.9340505599975586
110 0.00023 lr_0p00023 14000 0.9227956533432007
111 0.00023 lr_0p00023 15000 0.9158667325973511
112 0.00023 lr_0p00023 16000 0.908878743648529
113 0.00023 lr_0p00023 17000 0.9046502709388733
114 0.00023 lr_0p00023 18000 0.9031931161880493
115 0.00023 lr_0p00023 18688 0.9032362699508667

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

View File

@ -1,338 +0,0 @@
from pathlib import Path
import csv
import json
import math
ROOT = Path(
"/home/schwarc/diplomovka/"
"aya_300k_lr_validation"
)
RESULT_DIR = ROOT / "results"
RESULT_DIR.mkdir(
parents=True,
exist_ok=True
)
RUNS = [
("0.00018", ROOT / "lr_0p00018"),
("0.00020", ROOT / "lr_0p00020"),
("0.00023", ROOT / "lr_0p00023"),
]
def load_best_state(output):
files = list(
output.rglob(
"trainer_state.json"
)
)
if not files:
return None
candidates = []
for p in files:
try:
data = json.loads(
p.read_text(
encoding="utf-8"
)
)
candidates.append(
(
int(
data.get(
"global_step",
0
)
),
data,
p,
)
)
except Exception:
pass
if not candidates:
return None
return max(
candidates,
key=lambda x: x[0]
)
rows = []
eval_curves = {}
grad_curves = {}
for lr, output in RUNS:
result = load_best_state(
output
)
if result is None:
continue
global_step, state, state_file = result
history = state.get(
"log_history",
[]
)
evals = []
grads = []
for item in history:
step = int(
item.get("step", 0)
)
if "eval_loss" in item:
try:
value = float(
item["eval_loss"]
)
if math.isfinite(value):
evals.append(
(step, value)
)
except Exception:
pass
if "grad_norm" in item:
try:
value = float(
item["grad_norm"]
)
if math.isfinite(value):
grads.append(
(step, value)
)
except Exception:
pass
if evals:
final_eval_step, final_eval = (
evals[-1]
)
min_eval_step, min_eval = min(
evals,
key=lambda x: x[1]
)
else:
final_eval_step = ""
final_eval = ""
min_eval_step = ""
min_eval = ""
grad_values = [
value
for _, value in grads
]
if grad_values:
max_grad = max(
grad_values
)
ordered = sorted(
grad_values
)
p95_index = int(
0.95
* (len(ordered) - 1)
)
p95_grad = (
ordered[p95_index]
)
else:
max_grad = ""
p95_grad = ""
rows.append(
{
"learning_rate": lr,
"global_step": global_step,
"final_eval_step":
final_eval_step,
"final_eval_loss":
final_eval,
"min_eval_step":
min_eval_step,
"min_eval_loss":
min_eval,
"max_grad_norm":
max_grad,
"p95_grad_norm":
p95_grad,
"trainer_state":
str(state_file),
}
)
eval_curves[lr] = evals
grad_curves[lr] = grads
csv_path = (
RESULT_DIR
/ "aya_300k_lr_summary.csv"
)
with csv_path.open(
"w",
encoding="utf-8",
newline=""
) as f:
fields = [
"learning_rate",
"global_step",
"final_eval_step",
"final_eval_loss",
"min_eval_step",
"min_eval_loss",
"max_grad_norm",
"p95_grad_norm",
"trainer_state",
]
writer = csv.DictWriter(
f,
fieldnames=fields
)
writer.writeheader()
writer.writerows(rows)
print()
print("===== 300K LR SUMMARY =====")
for row in rows:
print(
f"LR={row['learning_rate']} | "
f"step={row['global_step']} | "
f"final_eval={row['final_eval_loss']} | "
f"min_eval={row['min_eval_loss']} "
f"@ {row['min_eval_step']} | "
f"max_grad={row['max_grad_norm']} | "
f"p95_grad={row['p95_grad_norm']}"
)
print()
print("CSV:", csv_path)
try:
import matplotlib.pyplot as plt
if eval_curves:
plt.figure(
figsize=(12, 7)
)
for lr, points in (
eval_curves.items()
):
if not points:
continue
plt.plot(
[x for x, _ in points],
[y for _, y in points],
marker="o",
label=f"LR {lr}",
)
plt.xlabel(
"optimizer step"
)
plt.ylabel(
"eval loss"
)
plt.title(
"Aya 300k - eval loss"
)
plt.legend()
plt.grid(alpha=0.25)
plt.tight_layout()
plt.savefig(
RESULT_DIR
/ "eval_loss_over_steps.png",
dpi=200,
bbox_inches="tight"
)
plt.close()
if grad_curves:
plt.figure(
figsize=(12, 7)
)
for lr, points in (
grad_curves.items()
):
if not points:
continue
plt.plot(
[x for x, _ in points],
[y for _, y in points],
label=f"LR {lr}",
)
plt.xlabel(
"optimizer step"
)
plt.ylabel(
"grad norm"
)
plt.title(
"Aya 300k - gradient norm"
)
plt.yscale("log")
plt.legend()
plt.grid(alpha=0.25)
plt.tight_layout()
plt.savefig(
RESULT_DIR
/ "grad_norm_over_steps.png",
dpi=200,
bbox_inches="tight"
)
plt.close()
except Exception as exc:
print(
"Grafy sa nepodarilo vytvorit:",
exc
)

View File

@ -1,341 +0,0 @@
from pathlib import Path
import csv
import json
import math
ROOT = Path(
"/home/schwarc/diplomovka/"
"aya_300k_lr_validation"
)
RESULT_DIR = ROOT / "results"
RESULT_DIR.mkdir(
parents=True,
exist_ok=True
)
RUNS = [
("0.00008", ROOT / "lr_0p00008"),
("0.00010", ROOT / "lr_0p00010"),
("0.00015", ROOT / "lr_0p00015"),
("0.00018", ROOT / "lr_0p00018"),
("0.00020", ROOT / "lr_0p00020"),
("0.00023", ROOT / "lr_0p00023"),
]
def load_best_state(output):
files = list(
output.rglob(
"trainer_state.json"
)
)
if not files:
return None
candidates = []
for p in files:
try:
data = json.loads(
p.read_text(
encoding="utf-8"
)
)
candidates.append(
(
int(
data.get(
"global_step",
0
)
),
data,
p,
)
)
except Exception:
pass
if not candidates:
return None
return max(
candidates,
key=lambda x: x[0]
)
rows = []
eval_curves = {}
grad_curves = {}
for lr, output in RUNS:
result = load_best_state(
output
)
if result is None:
continue
global_step, state, state_file = result
history = state.get(
"log_history",
[]
)
evals = []
grads = []
for item in history:
step = int(
item.get("step", 0)
)
if "eval_loss" in item:
try:
value = float(
item["eval_loss"]
)
if math.isfinite(value):
evals.append(
(step, value)
)
except Exception:
pass
if "grad_norm" in item:
try:
value = float(
item["grad_norm"]
)
if math.isfinite(value):
grads.append(
(step, value)
)
except Exception:
pass
if evals:
final_eval_step, final_eval = (
evals[-1]
)
min_eval_step, min_eval = min(
evals,
key=lambda x: x[1]
)
else:
final_eval_step = ""
final_eval = ""
min_eval_step = ""
min_eval = ""
grad_values = [
value
for _, value in grads
]
if grad_values:
max_grad = max(
grad_values
)
ordered = sorted(
grad_values
)
p95_index = int(
0.95
* (len(ordered) - 1)
)
p95_grad = (
ordered[p95_index]
)
else:
max_grad = ""
p95_grad = ""
rows.append(
{
"learning_rate": lr,
"global_step": global_step,
"final_eval_step":
final_eval_step,
"final_eval_loss":
final_eval,
"min_eval_step":
min_eval_step,
"min_eval_loss":
min_eval,
"max_grad_norm":
max_grad,
"p95_grad_norm":
p95_grad,
"trainer_state":
str(state_file),
}
)
eval_curves[lr] = evals
grad_curves[lr] = grads
csv_path = (
RESULT_DIR
/ "aya_300k_lr_summary.csv"
)
with csv_path.open(
"w",
encoding="utf-8",
newline=""
) as f:
fields = [
"learning_rate",
"global_step",
"final_eval_step",
"final_eval_loss",
"min_eval_step",
"min_eval_loss",
"max_grad_norm",
"p95_grad_norm",
"trainer_state",
]
writer = csv.DictWriter(
f,
fieldnames=fields
)
writer.writeheader()
writer.writerows(rows)
print()
print("===== 300K LR SUMMARY =====")
for row in rows:
print(
f"LR={row['learning_rate']} | "
f"step={row['global_step']} | "
f"final_eval={row['final_eval_loss']} | "
f"min_eval={row['min_eval_loss']} "
f"@ {row['min_eval_step']} | "
f"max_grad={row['max_grad_norm']} | "
f"p95_grad={row['p95_grad_norm']}"
)
print()
print("CSV:", csv_path)
try:
import matplotlib.pyplot as plt
if eval_curves:
plt.figure(
figsize=(12, 7)
)
for lr, points in (
eval_curves.items()
):
if not points:
continue
plt.plot(
[x for x, _ in points],
[y for _, y in points],
marker="o",
label=f"LR {lr}",
)
plt.xlabel(
"optimizer step"
)
plt.ylabel(
"eval loss"
)
plt.title(
"Aya 300k - eval loss"
)
plt.legend()
plt.grid(alpha=0.25)
plt.tight_layout()
plt.savefig(
RESULT_DIR
/ "eval_loss_over_steps.png",
dpi=200,
bbox_inches="tight"
)
plt.close()
if grad_curves:
plt.figure(
figsize=(12, 7)
)
for lr, points in (
grad_curves.items()
):
if not points:
continue
plt.plot(
[x for x, _ in points],
[y for _, y in points],
label=f"LR {lr}",
)
plt.xlabel(
"optimizer step"
)
plt.ylabel(
"grad norm"
)
plt.title(
"Aya 300k - gradient norm"
)
plt.yscale("log")
plt.legend()
plt.grid(alpha=0.25)
plt.tight_layout()
plt.savefig(
RESULT_DIR
/ "grad_norm_over_steps.png",
dpi=200,
bbox_inches="tight"
)
plt.close()
except Exception as exc:
print(
"Grafy sa nepodarilo vytvorit:",
exc
)

View File

@ -1,119 +0,0 @@
#!/usr/bin/env python3
"""Recompute run summaries and the LR comparison from compact curated evidence.
Run with no arguments from any directory. The standard library produces the CSV
and JSON summaries; matplotlib is required only for the PNG chart. No trainer
state, checkpoints, model weights, or tokenizers are needed.
The gradient P95 matches the archived summary: sort N observed norms and choose
the zero-based index floor(0.95 * (N - 1)), without interpolation.
"""
import csv
import json
import math
from collections import defaultdict
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
RESULTS = ROOT / "results"
def read_rows(filename):
with (RESULTS / filename).open(newline="", encoding="utf-8") as handle:
return list(csv.DictReader(handle))
def summarize():
evaluations = defaultdict(list)
gradients = defaultdict(list)
for row in read_rows("eval_loss_history.csv"):
evaluations[row["run"]].append(row)
for row in read_rows("gradient_history.csv"):
gradients[row["run"]].append(float(row["grad_norm"]))
raw_summary = {float(row["learning_rate"]): row for row in read_rows("aya_300k_lr_summary.csv")}
summaries = []
for run, rows in sorted(evaluations.items()):
rows.sort(key=lambda row: int(row["step"]))
lr = float(rows[0]["learning_rate"])
if any(float(row["learning_rate"]) != lr for row in rows):
raise ValueError(f"Inconsistent learning rate in {run}")
trial = ROOT / "trials" / run
train = json.loads((trial / "train_results.json").read_text(encoding="utf-8"))
final_eval = json.loads((trial / "eval_results.json").read_text(encoding="utf-8"))
norms = sorted(gradients[run])
if not norms or not (trial / "TRAINING_COMPLETE").is_file():
raise ValueError(f"Incomplete evidence for {run}")
final = rows[-1]
best = min(rows, key=lambda row: float(row["eval_loss"]))
summary = {
"learning_rate": lr, "run": run,
"global_step": int(raw_summary[lr]["global_step"]),
"epoch": float(train["epoch"]),
"final_eval_step": int(final["step"]),
"final_eval_loss": float(final["eval_loss"]),
"min_eval_step": int(best["step"]),
"min_eval_loss": float(best["eval_loss"]),
"max_grad_norm": max(norms),
"p95_grad_norm": norms[math.floor(0.95 * (len(norms) - 1))],
"train_runtime": float(train["train_runtime"]),
"eval_observations": len(rows),
"gradient_observations": len(norms),
}
if summary["final_eval_loss"] != float(final_eval["eval_loss"]):
raise ValueError(f"Final evaluation disagrees with eval_results.json: {run}")
for field in ("global_step", "final_eval_step", "final_eval_loss", "min_eval_step",
"min_eval_loss", "max_grad_norm", "p95_grad_norm"):
if float(summary[field]) != float(raw_summary[lr][field]):
raise ValueError(f"Archived summary disagrees at {run}: {field}")
summaries.append(summary)
if len(summaries) != 6 or any(row["global_step"] != 18688 or row["epoch"] != 1.0
or row["eval_observations"] != 19 or row["gradient_observations"] != 1868
for row in summaries):
raise ValueError("Expected six completed one-epoch runs with 19 eval and 1,868 gradient observations each")
with (RESULTS / "training_run_summary.csv").open("w", newline="", encoding="utf-8") as handle:
writer = csv.DictWriter(handle, fieldnames=list(summaries[0]))
writer.writeheader()
writer.writerows(summaries)
(RESULTS / "training_run_summary.json").write_text(json.dumps(summaries, indent=2) + "\n", encoding="utf-8")
return summaries
def plot(summaries):
try:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
except ImportError as exc:
raise SystemExit("Summaries recomputed. Install matplotlib to regenerate the PNG chart.") from exc
plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 11})
fig, ax = plt.subplots(figsize=(8, 4.8), layout="constrained")
x = [row["learning_rate"] * 1e4 for row in summaries]
y = [row["final_eval_loss"] for row in summaries]
ax.plot(x, y, color="#335c81", marker="o", linewidth=1.6, markersize=6)
selected = min(summaries, key=lambda row: row["final_eval_loss"])
sx, sy = selected["learning_rate"] * 1e4, selected["final_eval_loss"]
ax.scatter([sx], [sy], color="#ba4a00", s=75, zorder=3)
for xi, yi in zip(x, y):
ax.annotate(f"{yi:.5f}", (xi, yi), xytext=(0, 10), textcoords="offset points", ha="center", fontsize=9)
ax.annotate("Selected LR = 0.00010", (sx, sy), xytext=(20, -24),
textcoords="offset points", color="#8a3700", fontsize=10)
ax.set(title="Aya 300k: final validation loss by learning rate",
xlabel="Learning rate (×10⁻⁴)", ylabel="Final validation loss (lower is better)")
ax.set_xticks(x, [f"{value:.1f}" for value in x])
ax.set_ylim(min(y) - 0.009, max(y) + 0.012)
ax.grid(axis="y", color="#d8dee5", linewidth=0.7)
ax.spines[["top", "right"]].set_visible(False)
fig.savefig(RESULTS / "lr_vs_final_eval_loss.png", dpi=200, metadata={"Description": "Six manually chosen learning rates; final evaluation at step 18688 after one epoch."})
plt.close(fig)
def main():
summaries = summarize()
plot(summaries)
best = min(summaries, key=lambda row: row["final_eval_loss"])
print(f"Verified {len(summaries)} runs. Selected {best['run']}: final eval loss {best['final_eval_loss']:.15g}")
print(f"Saved summaries and chart in {RESULTS}")
if __name__ == "__main__":
main()

View File

@ -1,37 +0,0 @@
#!/usr/bin/env bash
# Reconstructed from the completed run's saved parameters and frozen task list.
set -euo pipefail
PROJECT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
SKBENCH_DIR=${SKBENCH_DIR:-/home/schwarc/diplomovka/sk-bench}
MODEL_DIR=${MODEL_DIR:-/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010}
OUTPUT_ROOT=${OUTPUT_ROOT:-/home/schwarc/diplomovka/skbench_evaluation/results}
GPU_ID=${GPU_ID:-1}
TASKS="$PROJECT/benchmarks/skbench/configs/tasks.txt"
OMITTED="$PROJECT/benchmarks/skbench/configs/omitted_tasks.txt"
test -f "$MODEL_DIR/config.json"
test -f "$TASKS"
test -f "$OMITTED"
cd "$SKBENCH_DIR"
RUN="$OUTPUT_ROOT/sk_zero_available_without_nli_lr_0p00010_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$RUN"
cp "$TASKS" "$RUN/tasks.txt"
cp "$OMITTED" "$RUN/omitted_tasks.txt"
cp uv.lock "$RUN/uv.lock"
git rev-parse HEAD > "$RUN/skbench_commit.txt"
CUDA_VISIBLE_DEVICES="$GPU_ID" VLLM_USE_FLASHINFER_SAMPLER=0 \
uv run --locked python eval_vllm.py \
--model-name "$MODEL_DIR" \
--tasks-file "$RUN/tasks.txt" \
--output-dir "$RUN" \
--tensor-parallel-size 1 \
--dtype bfloat16 \
--gpu-memory-utilization 0.85 \
--max-model-length 32768 \
--max-batched-tokens 2048 \
--enforce-eager \
--save-details \
2>&1 | tee "$RUN/run.log"

View File

@ -1,76 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
source /home/schwarc/miniconda3/etc/profile.d/conda.sh
conda activate llama_factory_unsloth
ROOT="/home/schwarc/diplomovka"
EXP="$ROOT/aya_300k_lr_validation"
cd /home/schwarc/LLaMA-Factory
export CUDA_VISIBLE_DEVICES=0
unset FORCE_TORCHRUN || true
export PYTHONUNBUFFERED=1
RUNS=(
"lr_0p00018"
"lr_0p00020"
"lr_0p00023"
)
for NAME in "${RUNS[@]}"; do
CFG="$EXP/configs/$NAME.yaml"
OUT="$EXP/$NAME"
LOG="$EXP/logs/$NAME.log"
DONE="$OUT/TRAINING_COMPLETE"
echo
echo "========================================"
echo "RUN: $NAME"
echo "========================================"
if [ -f "$DONE" ]; then
echo "Uz dokoncene - preskakujem."
continue
fi
# Ak existuje checkpoint po predoslom pade servera,
# radsej automaticky nic neprepiseme.
if [ -d "$OUT" ] && \
find "$OUT" -maxdepth 1 -type d \
-name 'checkpoint-*' | grep -q .; then
echo
echo "POZOR:"
echo "Nasiel som nedokonceny run s checkpointom:"
echo "$OUT"
echo
echo "Nebudem ho automaticky prepisovat."
echo "Treba ho najprv resume-nut."
exit 2
fi
llamafactory-cli train "$CFG" \
2>&1 | tee "$LOG"
mkdir -p "$OUT"
touch "$DONE"
python \
"$ROOT/scripts/analyze_aya_300k_lr.py"
done
echo
echo "========================================"
echo "VSETKY 300K LR BEHY HOTOVE"
echo "========================================"
python \
"$ROOT/scripts/analyze_aya_300k_lr.py"

View File

@ -1,76 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
source /home/schwarc/miniconda3/etc/profile.d/conda.sh
conda activate llama_factory_unsloth
ROOT="/home/schwarc/diplomovka"
EXP="$ROOT/aya_300k_lr_validation"
cd /home/schwarc/LLaMA-Factory
export CUDA_VISIBLE_DEVICES=0
unset FORCE_TORCHRUN || true
export PYTHONUNBUFFERED=1
RUNS=(
"lr_0p00015"
"lr_0p00010"
"lr_0p00008"
)
for NAME in "${RUNS[@]}"; do
CFG="$EXP/configs/$NAME.yaml"
OUT="$EXP/$NAME"
LOG="$EXP/logs/$NAME.log"
DONE="$OUT/TRAINING_COMPLETE"
echo
echo "========================================"
echo "RUN: $NAME"
echo "========================================"
if [ -f "$DONE" ]; then
echo "Uz dokoncene - preskakujem."
continue
fi
# Ak existuje checkpoint po predoslom pade servera,
# radsej automaticky nic neprepiseme.
if [ -d "$OUT" ] && \
find "$OUT" -maxdepth 1 -type d \
-name 'checkpoint-*' | grep -q .; then
echo
echo "POZOR:"
echo "Nasiel som nedokonceny run s checkpointom:"
echo "$OUT"
echo
echo "Nebudem ho automaticky prepisovat."
echo "Treba ho najprv resume-nut."
exit 2
fi
llamafactory-cli train "$CFG" \
2>&1 | tee "$LOG"
mkdir -p "$OUT"
touch "$DONE"
python \
"$ROOT/scripts/analyze_aya_300k_lr_all.py"
done
echo
echo "========================================"
echo "VSETKY 300K LR BEHY HOTOVE"
echo "========================================"
python \
"$ROOT/scripts/analyze_aya_300k_lr_all.py"

View File

@ -1,74 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
eval "$(/home/schwarc/miniconda3/bin/conda shell.bash hook)"
conda activate lm_eval_hruska
cd /home/schwarc/lm-evaluation-harness
# This directory already contains the base model merged with the Aya adapter.
MODEL="/home/schwarc/diplomovka/skbench_evaluation/models/aya_300k_lr_0p00010"
TASKS="arc_sk,hellaswag_sk,m_mmlu_sk,truthfulqa_sk_mc1,truthfulqa_sk_mc2,sklegal,skquad"
INCLUDE_PATH="/home/schwarc/diplomovka/lmeval_slovak_tasks"
ROOT="/home/schwarc/diplomovka/aya_300k_lr_validation/lmeval"
NAME="lr_0p00010_$(date +%Y%m%d_%H%M%S)"
OUT="$ROOT/results/$NAME"
LOG="$ROOT/logs/$NAME.log"
SUMMARY="$ROOT/summary.csv"
test -f "$MODEL/config.json"
test -f "$MODEL/model.safetensors.index.json"
test -d "$INCLUDE_PATH"
mkdir -p "$OUT" "$ROOT/logs"
cp -a "$INCLUDE_PATH" "$OUT/custom_tasks"
git rev-parse HEAD > "$OUT/lm_eval_commit.txt"
printf '%s\n' "$TASKS" > "$OUT/tasks.txt"
printf '%s\n' "model=hf" "pretrained=$MODEL" "tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4" "dtype=bfloat16" \
"num_fewshot=0" "batch_size=1" "apply_chat_template=false" \
"CUDA_VISIBLE_DEVICES=1" > "$OUT/run_settings.txt"
python - <<'PY' > "$OUT/package_versions.json"
import importlib.metadata as md
import json
versions = {}
for package in ("lm_eval", "transformers", "torch", "datasets", "peft", "evaluate"):
try:
versions[package] = md.version(package)
except md.PackageNotFoundError:
versions[package] = None
print(json.dumps(versions, indent=2))
PY
if [[ ! -f "$SUMMARY" ]]; then
printf '%s\n' 'model,exit_code,start_time,end_time,log_file' > "$SUMMARY"
fi
START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
printf 'Model: %s\nResults: %s\nLog: %s\n' "$MODEL" "$OUT" "$LOG"
set +e
CUDA_VISIBLE_DEVICES=1 lm_eval \
--model hf \
--model_args "pretrained=$MODEL,tokenizer=/home/schwarc/.cache/huggingface/hub/models--slovak-nlp--mistral-sk-7b/snapshots/089497ae0d72018e9591895c54f774bf0b4a83a4,dtype=bfloat16" \
--tasks "$TASKS" \
--include_path "$INCLUDE_PATH" \
--device cuda:0 \
--batch_size 1 \
--num_fewshot 0 \
--output_path "$OUT" \
2>&1 | tee "$LOG"
EXIT_CODES=("${PIPESTATUS[@]}")
set -e
EXIT_CODE=${EXIT_CODES[0]}
if (( EXIT_CODE == 0 )); then
EXIT_CODE=${EXIT_CODES[1]}
fi
END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
printf '%s,%s,%s,%s,%s\n' "$NAME" "$EXIT_CODE" "$START_TIME" "$END_TIME" "$LOG" >> "$SUMMARY"
if (( EXIT_CODE == 0 )); then
printf 'Evaluation completed: %s\n' "$OUT"
else
printf 'Evaluation failed (exit code %s). Log: %s\n' "$EXIT_CODE" "$LOG" >&2
fi
exit "$EXIT_CODE"

View File

@ -1,899 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="/home/schwarc/diplomovka"
LF="/home/schwarc/LLaMA-Factory"
EXP="$ROOT/aya_300k_lr_validation"
CONFIG_DIR="$EXP/configs"
LOG_DIR="$EXP/logs"
RESULT_DIR="$EXP/results"
DATA_FILE="$LF/data/aya_slovak_300k_fixed.jsonl"
DATASET_INFO="$LF/data/dataset_info.json"
BASE_CONFIG="$ROOT/optuna_lr_hpo_1gpu/base_hpo_config.yaml"
mkdir -p "$EXP" "$CONFIG_DIR" "$LOG_DIR" "$RESULT_DIR" "$ROOT/scripts"
source /home/schwarc/miniconda3/etc/profile.d/conda.sh
conda activate llama_factory_unsloth
echo
echo "========================================"
echo "1. KONTROLA PROSTREDIA"
echo "========================================"
python - <<'PY'
import torch
import datasets
import yaml
print("Torch:", torch.__version__)
print("CUDA:", torch.cuda.is_available())
print("Datasets:", datasets.__version__)
if torch.cuda.is_available():
print("GPU 0:", torch.cuda.get_device_name(0))
PY
# ============================================================
# 2. VYTVORENIE FIXNEHO 300K DATASETU
# ============================================================
echo
echo "========================================"
echo "2. AYA SLOVAK 300K"
echo "========================================"
python - <<'PY'
from pathlib import Path
from datasets import load_dataset
import json
TARGET = Path(
"/home/schwarc/LLaMA-Factory/data/"
"aya_slovak_300k_fixed.jsonl"
)
EXPECTED = 300_000
SEED = 42
def count_lines(path):
with path.open("r", encoding="utf-8") as f:
return sum(1 for _ in f)
if TARGET.exists():
count = count_lines(TARGET)
if count == EXPECTED:
print(
f"Dataset uz existuje a ma spravne "
f"{count} riadkov."
)
raise SystemExit(0)
else:
raise RuntimeError(
f"{TARGET} existuje, ale ma "
f"{count} riadkov namiesto {EXPECTED}. "
"Nebudem ho automaticky prepisovat."
)
print("Nacitavam Aya Collection - slovak/train...")
ds = load_dataset(
"CohereLabs/aya_collection_language_split",
"slovak",
split="train",
)
print("Povodny train split:", len(ds))
def valid_batch(batch):
result = []
for inp, target in zip(
batch["inputs"],
batch["targets"],
):
ok = (
isinstance(inp, str)
and isinstance(target, str)
and bool(inp.strip())
and bool(target.strip())
)
result.append(ok)
return result
print("Filtrujem prazdne inputs/targets...")
ds = ds.filter(
valid_batch,
batched=True,
batch_size=10000,
num_proc=4,
)
print("Platne zaznamy:", len(ds))
if len(ds) < EXPECTED:
raise RuntimeError(
f"Po filtrovani ostalo iba {len(ds)} zaznamov."
)
print("Shuffle seed =", SEED)
ds = ds.shuffle(seed=SEED)
ds = ds.select(
range(EXPECTED)
)
print("Zapisujem:", TARGET)
with TARGET.open(
"w",
encoding="utf-8"
) as f:
for row in ds:
item = {
"instruction": row["inputs"].strip(),
"input": "",
"output": row["targets"].strip(),
}
f.write(
json.dumps(
item,
ensure_ascii=False
)
+ "\n"
)
count = count_lines(TARGET)
if count != EXPECTED:
raise RuntimeError(
f"Finalny dataset ma {count} riadkov."
)
print("HOTOVO.")
print("Pocet:", count)
print("Dataset:", TARGET)
PY
# ============================================================
# 3. DATASET_INFO.JSON
# ============================================================
echo
echo "========================================"
echo "3. DATASET_INFO"
echo "========================================"
python - <<'PY'
from pathlib import Path
import json
import copy
import shutil
p = Path(
"/home/schwarc/LLaMA-Factory/data/"
"dataset_info.json"
)
backup = p.parent / (
"dataset_info_before_aya300k_backup.json"
)
if not backup.exists():
shutil.copy2(p, backup)
with p.open(
"r",
encoding="utf-8"
) as f:
info = json.load(f)
source_name = "aya_slovak_100k_fixed"
new_name = "aya_slovak_300k_fixed"
if source_name not in info:
raise RuntimeError(
f"V dataset_info chyba {source_name}"
)
entry = copy.deepcopy(
info[source_name]
)
entry["file_name"] = (
"aya_slovak_300k_fixed.jsonl"
)
info[new_name] = entry
with p.open(
"w",
encoding="utf-8"
) as f:
json.dump(
info,
f,
ensure_ascii=False,
indent=2
)
print(
"Registrovany dataset:",
new_name
)
print(
json.dumps(
info[new_name],
ensure_ascii=False,
indent=2
)
)
PY
# ============================================================
# 4. VYTVORENIE 3 CONFIGOV
# ============================================================
echo
echo "========================================"
echo "4. CONFIGY"
echo "========================================"
python - <<'PY'
from pathlib import Path
import yaml
ROOT = Path(
"/home/schwarc/diplomovka"
)
EXP = ROOT / "aya_300k_lr_validation"
BASE = (
ROOT
/ "optuna_lr_hpo_1gpu"
/ "base_hpo_config.yaml"
)
if not BASE.exists():
BASE = (
ROOT
/ "configs"
/ "hruska_compare9_100k_fixed"
/ "10_r16_a32_lr1e4.yaml"
)
if not BASE.exists():
raise RuntimeError(
"Nenasiel som base config."
)
with BASE.open(
"r",
encoding="utf-8"
) as f:
base = yaml.safe_load(f)
# ------------------------------------------------------------
# FIXNE PARAMETRE PRE VSETKY 3 BEHY
# ------------------------------------------------------------
base["dataset"] = "aya_slovak_300k_fixed"
base["streaming"] = False
# presne 1 cely epoch
base.pop("max_steps", None)
base["num_train_epochs"] = 1.0
# 300k -> 1000 validation -> cca 299k train
base["val_size"] = 1000
# 1 GPU:
# 1 * 16 * 1 = effective batch 16
base["per_device_train_batch_size"] = 1
base["per_device_eval_batch_size"] = 1
base["gradient_accumulation_steps"] = 16
# cca 18 688 optimizer krokov
# ~8 % warmup
base["warmup_steps"] = 1500
base.pop("warmup_ratio", None)
# chceme sledovat priebeh
base["eval_strategy"] = "steps"
base["eval_steps"] = 1000
base["logging_steps"] = 10
# checkpointy pre pripad restartu servera
base["save_steps"] = 2000
base["save_total_limit"] = 2
base["seed"] = 42
base["overwrite_output_dir"] = True
base["report_to"] = "none"
# explicitne zachovame Unsloth + bf16
base["use_unsloth"] = True
base["use_unsloth_gc"] = True
base["bf16"] = True
base["fp16"] = False
# chceme rovnaky optimizer/scheduler
base["optim"] = "adamw_torch"
base["lr_scheduler_type"] = "cosine"
# rovnaka gradient clipping hranica
base["max_grad_norm"] = 0.5
runs = [
("lr_0p00018", 0.00018),
("lr_0p00020", 0.00020),
("lr_0p00023", 0.00023),
]
for name, lr in runs:
cfg = dict(base)
cfg["learning_rate"] = lr
cfg["output_dir"] = str(
EXP / name
)
path = (
EXP
/ "configs"
/ f"{name}.yaml"
)
with path.open(
"w",
encoding="utf-8"
) as f:
yaml.safe_dump(
cfg,
f,
sort_keys=False,
allow_unicode=True
)
print()
print(path)
print(" LR:", lr)
print(
" output:",
cfg["output_dir"]
)
print()
print("Base kontrola:")
print("dataset:", base["dataset"])
print("epochs:", base["num_train_epochs"])
print(
"batch:",
base["per_device_train_batch_size"]
)
print(
"grad_accum:",
base["gradient_accumulation_steps"]
)
print(
"warmup:",
base["warmup_steps"]
)
print(
"eval_steps:",
base["eval_steps"]
)
print(
"save_steps:",
base["save_steps"]
)
print(
"LoRA rank:",
base.get("lora_rank")
)
print(
"LoRA alpha:",
base.get("lora_alpha")
)
print(
"LoRA dropout:",
base.get("lora_dropout")
)
print(
"LoRA target:",
base.get("lora_target")
)
PY
# ============================================================
# 5. ANALYZATOR
# ============================================================
cat > "$ROOT/scripts/analyze_aya_300k_lr.py" <<'PY'
from pathlib import Path
import csv
import json
import math
ROOT = Path(
"/home/schwarc/diplomovka/"
"aya_300k_lr_validation"
)
RESULT_DIR = ROOT / "results"
RESULT_DIR.mkdir(
parents=True,
exist_ok=True
)
RUNS = [
("0.00018", ROOT / "lr_0p00018"),
("0.00020", ROOT / "lr_0p00020"),
("0.00023", ROOT / "lr_0p00023"),
]
def load_best_state(output):
files = list(
output.rglob(
"trainer_state.json"
)
)
if not files:
return None
candidates = []
for p in files:
try:
data = json.loads(
p.read_text(
encoding="utf-8"
)
)
candidates.append(
(
int(
data.get(
"global_step",
0
)
),
data,
p,
)
)
except Exception:
pass
if not candidates:
return None
return max(
candidates,
key=lambda x: x[0]
)
rows = []
eval_curves = {}
grad_curves = {}
for lr, output in RUNS:
result = load_best_state(
output
)
if result is None:
continue
global_step, state, state_file = result
history = state.get(
"log_history",
[]
)
evals = []
grads = []
for item in history:
step = int(
item.get("step", 0)
)
if "eval_loss" in item:
try:
value = float(
item["eval_loss"]
)
if math.isfinite(value):
evals.append(
(step, value)
)
except Exception:
pass
if "grad_norm" in item:
try:
value = float(
item["grad_norm"]
)
if math.isfinite(value):
grads.append(
(step, value)
)
except Exception:
pass
if evals:
final_eval_step, final_eval = (
evals[-1]
)
min_eval_step, min_eval = min(
evals,
key=lambda x: x[1]
)
else:
final_eval_step = ""
final_eval = ""
min_eval_step = ""
min_eval = ""
grad_values = [
value
for _, value in grads
]
if grad_values:
max_grad = max(
grad_values
)
ordered = sorted(
grad_values
)
p95_index = int(
0.95
* (len(ordered) - 1)
)
p95_grad = (
ordered[p95_index]
)
else:
max_grad = ""
p95_grad = ""
rows.append(
{
"learning_rate": lr,
"global_step": global_step,
"final_eval_step":
final_eval_step,
"final_eval_loss":
final_eval,
"min_eval_step":
min_eval_step,
"min_eval_loss":
min_eval,
"max_grad_norm":
max_grad,
"p95_grad_norm":
p95_grad,
"trainer_state":
str(state_file),
}
)
eval_curves[lr] = evals
grad_curves[lr] = grads
csv_path = (
RESULT_DIR
/ "aya_300k_lr_summary.csv"
)
with csv_path.open(
"w",
encoding="utf-8",
newline=""
) as f:
fields = [
"learning_rate",
"global_step",
"final_eval_step",
"final_eval_loss",
"min_eval_step",
"min_eval_loss",
"max_grad_norm",
"p95_grad_norm",
"trainer_state",
]
writer = csv.DictWriter(
f,
fieldnames=fields
)
writer.writeheader()
writer.writerows(rows)
print()
print("===== 300K LR SUMMARY =====")
for row in rows:
print(
f"LR={row['learning_rate']} | "
f"step={row['global_step']} | "
f"final_eval={row['final_eval_loss']} | "
f"min_eval={row['min_eval_loss']} "
f"@ {row['min_eval_step']} | "
f"max_grad={row['max_grad_norm']} | "
f"p95_grad={row['p95_grad_norm']}"
)
print()
print("CSV:", csv_path)
try:
import matplotlib.pyplot as plt
if eval_curves:
plt.figure(
figsize=(12, 7)
)
for lr, points in (
eval_curves.items()
):
if not points:
continue
plt.plot(
[x for x, _ in points],
[y for _, y in points],
marker="o",
label=f"LR {lr}",
)
plt.xlabel(
"optimizer step"
)
plt.ylabel(
"eval loss"
)
plt.title(
"Aya 300k - eval loss"
)
plt.legend()
plt.grid(alpha=0.25)
plt.tight_layout()
plt.savefig(
RESULT_DIR
/ "eval_loss_over_steps.png",
dpi=200,
bbox_inches="tight"
)
plt.close()
if grad_curves:
plt.figure(
figsize=(12, 7)
)
for lr, points in (
grad_curves.items()
):
if not points:
continue
plt.plot(
[x for x, _ in points],
[y for _, y in points],
label=f"LR {lr}",
)
plt.xlabel(
"optimizer step"
)
plt.ylabel(
"grad norm"
)
plt.title(
"Aya 300k - gradient norm"
)
plt.yscale("log")
plt.legend()
plt.grid(alpha=0.25)
plt.tight_layout()
plt.savefig(
RESULT_DIR
/ "grad_norm_over_steps.png",
dpi=200,
bbox_inches="tight"
)
plt.close()
except Exception as exc:
print(
"Grafy sa nepodarilo vytvorit:",
exc
)
PY
# ============================================================
# 6. RUNNER
# ============================================================
cat > "$ROOT/scripts/run_aya_300k_lr_validation.sh" <<'BASH2'
#!/usr/bin/env bash
set -euo pipefail
source /home/schwarc/miniconda3/etc/profile.d/conda.sh
conda activate llama_factory_unsloth
ROOT="/home/schwarc/diplomovka"
EXP="$ROOT/aya_300k_lr_validation"
cd /home/schwarc/LLaMA-Factory
export CUDA_VISIBLE_DEVICES=0
unset FORCE_TORCHRUN || true
export PYTHONUNBUFFERED=1
RUNS=(
"lr_0p00018"
"lr_0p00020"
"lr_0p00023"
)
for NAME in "${RUNS[@]}"; do
CFG="$EXP/configs/$NAME.yaml"
OUT="$EXP/$NAME"
LOG="$EXP/logs/$NAME.log"
DONE="$OUT/TRAINING_COMPLETE"
echo
echo "========================================"
echo "RUN: $NAME"
echo "========================================"
if [ -f "$DONE" ]; then
echo "Uz dokoncene - preskakujem."
continue
fi
# Ak existuje checkpoint po predoslom pade servera,
# radsej automaticky nic neprepiseme.
if [ -d "$OUT" ] && \
find "$OUT" -maxdepth 1 -type d \
-name 'checkpoint-*' | grep -q .; then
echo
echo "POZOR:"
echo "Nasiel som nedokonceny run s checkpointom:"
echo "$OUT"
echo
echo "Nebudem ho automaticky prepisovat."
echo "Treba ho najprv resume-nut."
exit 2
fi
llamafactory-cli train "$CFG" \
2>&1 | tee "$LOG"
mkdir -p "$OUT"
touch "$DONE"
python \
"$ROOT/scripts/analyze_aya_300k_lr.py"
done
echo
echo "========================================"
echo "VSETKY 300K LR BEHY HOTOVE"
echo "========================================"
python \
"$ROOT/scripts/analyze_aya_300k_lr.py"
BASH2
chmod +x \
"$ROOT/scripts/run_aya_300k_lr_validation.sh"
echo
echo "========================================"
echo "SETUP HOTOVY"
echo "========================================"
echo
echo "Dataset:"
wc -l "$DATA_FILE"
echo
echo "Configy:"
ls -1 "$CONFIG_DIR"
echo
echo "Runner:"
echo "$ROOT/scripts/run_aya_300k_lr_validation.sh"

View File

@ -1,74 +0,0 @@
from pathlib import Path, PurePosixPath
import argparse
import collections
import hashlib
import json
import re
import tarfile
parser = argparse.ArgumentParser(description="Safely extract an experiment archive and create audit path manifests (Python 3.11+).")
parser.add_argument("--archive", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
SOURCE = args.archive.resolve()
DEST = args.output.resolve()
if DEST.exists() and any(DEST.iterdir()):
raise SystemExit(f"Output directory must be empty: {DEST}")
DEST.mkdir(parents=True, exist_ok=True)
start_size = SOURCE.stat().st_size
def safe_component(value):
value = value.replace('%', '%25')
value = re.sub(r'[<>:"\\|?*\x00-\x1f]', lambda m: f'%{ord(m.group()):02X}', value)
while value.endswith((' ', '.')):
value = value[:-1] + f'%{ord(value[-1]):02X}'
if value.split('.')[0].upper() in {'CON', 'PRN', 'AUX', 'NUL', *(f'COM{i}' for i in range(1, 10)), *(f'LPT{i}' for i in range(1, 10))}:
value = '%5F' + value
return value
manifest = []
seen = set()
with tarfile.open(SOURCE, 'r:gz') as archive:
for member in archive:
original = PurePosixPath(member.name)
if original.is_absolute() or '..' in original.parts or '\\' in member.name:
raise RuntimeError(f'Unsafe archive path: {member.name!r}')
relative = Path(*(safe_component(x) for x in original.parts if x not in ('', '.')))
target = DEST / relative
if not target.resolve().is_relative_to(DEST.resolve()):
raise RuntimeError(f'Path escapes extraction root: {member.name!r}')
row = {'original': member.name, 'local': relative.as_posix(), 'size': member.size, 'type': 'other'}
if member.isdir():
target.mkdir(parents=True, exist_ok=True)
row['type'] = 'directory'
elif member.isfile():
key = relative.as_posix().casefold()
if key in seen:
raise RuntimeError(f'Archive filename collision: {member.name!r}')
seen.add(key)
target.parent.mkdir(parents=True, exist_ok=True)
extracted = archive.extractfile(member)
assert extracted is not None
with extracted, target.open('wb') as handle:
while chunk := extracted.read(1024 * 1024):
handle.write(chunk)
if target.stat().st_size != member.size:
raise RuntimeError(f'Incomplete extraction: {member.name!r}')
row['type'] = 'file'
else:
row['type'] = 'skipped_link_or_special'
manifest.append(row)
if SOURCE.stat().st_size != start_size:
raise RuntimeError('Archive changed during extraction')
with SOURCE.open('rb') as handle:
digest = hashlib.file_digest(handle, 'sha256').hexdigest()
(DEST / 'archive_manifest.json').write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding='utf-8')
files = [x for x in manifest if x['type'] == 'file']
summary = {'source': str(SOURCE), 'compressed_bytes': start_size, 'sha256': digest,
'files': len(files), 'uncompressed_bytes': sum(x['size'] for x in files),
'skipped_special': [x for x in manifest if x['type'] == 'skipped_link_or_special'],
'top_level_files': dict(collections.Counter(PurePosixPath(x['original']).parts[0] for x in files)),
'largest_files': sorted(files, key=lambda x: x['size'], reverse=True)[:12]}
(DEST / 'archive_summary.json').write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps(summary, ensure_ascii=False, indent=2))