YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

SLM β€” Small Language Model

Modello linguistico italiano decoder-only costruito da zero in Python/PyTorch. Ogni componente scritto e compreso prima di passare al successivo: architettura di attenzione, tokenizer BPE-SPM, training loop AdamW, pipeline corpus, deployment via GGUF.

Documentazione: c1cc10.github.io/slm


Stato corrente

Architettura Decoder-only Transformer (pre-norm, RoPE)
Parametri 45,997,056 (~175 MB fp32)
Tokenizer BPE-SPM, 16 000 token
Miglior checkpoint Run #7 shard 3 β€” val loss 2.8165 (perplexity ~16.7)
Corpus totale Wikipedia IT 3 shard (~210M token) su base CulturaX IT sweet spot
Deployment slm-run7-s3-q8_0.gguf (56 MB Q8_0)

Struttura

slm/
β”œβ”€β”€ attention.py              # Scaled dot-product attention, Multi-Head Attention, RoPE
β”œβ”€β”€ transformer.py            # FeedForward (GELU), TransformerBlock (pre-norm)
β”œβ”€β”€ model.py                  # GPTConfig, GPT (forward + generate + weight tying)
β”œβ”€β”€ train.py                  # Training loop: AdamW, LR schedule, checkpoint, --resume
β”œβ”€β”€ train_sft.py              # SFT: JSONL prompt/completion, masked loss
β”œβ”€β”€ tools/
β”‚   β”œβ”€β”€ filter_corpus.py      # Pipeline 4 stadi: euristico β†’ fastText β†’ dedup MD5 β†’ PPL scorer
β”‚   β”œβ”€β”€ fetch_hf_corpus.py    # Streaming generico HuggingFace (qualsiasi dataset)
β”‚   β”œβ”€β”€ epub_to_text.py       # Estrazione corpus da EPUB
β”‚   β”œβ”€β”€ convert_to_text.py    # Converter: PDF, DOCX, PPTX, EPUB, HTML, ODT β†’ plain text
β”‚   β”œβ”€β”€ eval_ppl.py           # Valutazione PPL interattiva (REPL + CLI)
β”‚   └── export_db_corpus.py   # Export PostgreSQL/MongoDB β†’ corpus SLM
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ wiki_it.txt           # Wikipedia IT (~200 MB, 47.8M token)
β”‚   β”œβ”€β”€ culturax_it_ppl95.txt # CulturaX IT filtrato PPL p95 (7.5 GB, 2.44M doc)
β”‚   └── corpus_letterario.txt # EPUB scelti, narrativa contemporanea italiana
β”œβ”€β”€ checkpoints/
β”‚   β”œβ”€β”€ best.pt               # Checkpoint corrente (Run #4: val 3.5861)
β”‚   β”œβ”€β”€ run4_best.pt          # Backup Run #4
β”‚   β”œβ”€β”€ tokenizer.model       # Modello SentencePiece BPE (16k vocab)
β”‚   └── tokenizer.vocab       # Vocabolario SPM
β”œβ”€β”€ slm-run4.gguf             # Run #4 convertito GGUF (fp16)
β”œβ”€β”€ slm-run4-q8_0.gguf        # Run #4 quantizzato Q8_0
└── docs/                     # Documentazione HTML (GitHub Pages)
    β”œβ”€β”€ index.html
    β”œβ”€β”€ slm-journal.html      # Diario: decisioni, run, corpus, caveats
    β”œβ”€β”€ slm-intro.html        # Come funziona una LLM
    β”œβ”€β”€ slm-roadmap.html      # Roadmap 11 fasi
    β”œβ”€β”€ slm-docs.html         # Documentazione completa
    β”œβ”€β”€ slm-teoria.html       # Riferimento teorico con formule
    └── slm-ottimizzatore.html

Requisiti

pip install torch sentencepiece fasttext

Training

# Resume Run #5 (corpus espanso, da checkpoint Run #4)
python3 -u train.py --tokenizer bpe-spm --data data/corpus_run5.txt \
  --resume 2>&1 | tee /tmp/run5.log

# Pre-training da zero (preset medium: 45.9M parametri)
python3 train.py --tokenizer bpe-spm --data data/wiki_it.txt \
  --preset medium --steps 30000 --batch 32 --seq-len 512

# Generazione testo da checkpoint
python3 train.py --generate "La capitale d'Italia"

Filtro corpus

# Filtro completo con PPL scorer su GPU
python3 -u tools/filter_corpus.py \
  --input data/culturax_it_raw.txt \
  --output data/culturax_it_ppl95.txt \
  --checkpoint checkpoints/best.pt \
  --device cuda --ppl-pct 95 \
  2>&1 | tee /tmp/filter.log

# Nota: python3 -u obbligatorio con tee (altrimenti log vuoto per ore)
# Nota: usare run3_best.pt come scorer, non run4_best.pt

Provare il modello

I file GGUF sono su HuggingFace (non stanno nel repo perchΓ© superano il limite di 100 MB di GitHub).

Scarica i file:

https://huggingface.co/c1cc10/slm-italiano

Oppure da terminale con huggingface-cli:

pip install huggingface_hub
huggingface-cli download c1cc10/slm-italiano slm-run7-s3-q8_0.gguf

Ci sono due modi per usarli.


Opzione A β€” llama.cpp (consigliata, nessun Python necessario)

llama.cpp Γ¨ un runtime C++ che gira su qualsiasi macchina, anche senza GPU.

Windows

  1. Vai su https://github.com/ggerganov/llama.cpp/releases
  2. Scarica l'archivio ZIP piΓΉ recente per Windows β€” scegli la variante giusta:
    • llama-bXXXX-bin-win-avx2-x64.zip β€” CPU moderna (consigliato se non hai GPU NVIDIA)
    • llama-bXXXX-bin-win-cuda-cu12.X.X-x64.zip β€” GPU NVIDIA con CUDA
  3. Estrai lo ZIP in una cartella, ad esempio C:\llama.cpp\
  4. Apri PowerShell o il Prompt dei comandi nella stessa cartella e lancia:
llama-cli.exe -m C:\percorso\slm-run7-s3-q8_0.gguf -p "La capitale d'Italia Γ¨" --temp 0.8 -n 200

macOS / Linux

git clone https://github.com/ggerganov/llama.cpp && cd llama.cpp
cmake -B build && cmake --build build --config Release -j
./build/bin/llama-cli -m /percorso/slm-run7-s3-q8_0.gguf -p "La capitale d'Italia Γ¨" --temp 0.8 -n 200

File disponibili:

File Dimensione Quando usarlo
slm-run7-s3-q8_0.gguf 56 MB uso normale β€” checkpoint piΓΉ recente (Run #7)

Opzione B β€” Python (richiede PyTorch)

Se hai giΓ  Python installato puoi usare train.py direttamente.

Installare i prerequisiti

Verifica che Python sia installato (versione 3.10 o superiore):

python --version

Se non Γ¨ installato, scaricalo da https://www.python.org/downloads/ β€” su Windows, durante l'installazione spunta "Add Python to PATH".

Installa le dipendenze:

pip install torch sentencepiece

Su Windows con GPU NVIDIA, sostituisci il comando pip con quello specifico per CUDA che trovi su https://pytorch.org/get-started/locally/ (seleziona: Windows / Pip / CUDA).

Generare testo dal checkpoint PyTorch:

python train.py --generate "La capitale d'Italia" --temp 0.8 --max-new-tokens 200

Il checkpoint checkpoints/best.pt e il tokenizer checkpoints/tokenizer.model devono essere presenti nella directory.


Alternativa: costruire il GGUF dal checkpoint PyTorch

Se hai il checkpoint checkpoints/best.pt e llama.cpp clonato localmente, puoi convertirlo tu stesso:

# dalla directory llama.cpp
python3 convert_hf_to_gguf.py /percorso/slm --outtype f16 --outfile slm-run7-s3.gguf
./build/bin/llama-quantize slm-run7-s3.gguf slm-run7-s3-q8_0.gguf Q8_0

Nota: questo Γ¨ un modello di ricerca (45.9M parametri, solo pre-training). Genera testo in italiano ma non segue istruzioni β€” Γ¨ un completion model, non un assistente conversazionale.


Architettura

Iperparametro Valore
d_model 512
num_heads 8 (d_k = 64)
num_layers 12
d_ff 2 048
max_seq_len 512
dropout 0.1
Parametri totali 45 997 056

Conto esatto dei parametri (per chiarezza, perchΓ© il GGUF usa il namespace gptneox.*):

Il modello non Γ¨ GPT-NeoX. L'FFN Γ¨ standard a due matrici lineari, non gated:

Componente Per blocco Note
Attention (W_q, W_k, W_v, W_o) 4 Γ— 512Β² = 1 048 576 bias=False su tutte le proiezioni
LN1 + LN2 2 Γ— 2 Γ— 512 = 2 048 weight + bias per ciascuna
FFN fc1 (d→d_ff) 512 × 2048 + 2048 = 1 050 624 bias=True (default PyTorch)
FFN fc2 (d_ff→d) 2048 × 512 + 512 = 1 049 088 bias=True
Per blocco 3 150 336

12 blocchi: 37 804 032
Token embedding (tied con lm_head): 16 000 Γ— 512 = 8 192 000
LayerNorm finale: 1 024
lm_head: 0 (pesi condivisi con l'embedding)
Totale: 45 997 056

Il namespace gptneox.* nelle GGUF metadata riflette il tipo architetturale piΓΉ vicino supportato da llama.cpp al momento della conversione, non indica GPT-NeoX con FFN gated (gate Γ— up Γ— down). use_parallel_residual = false Γ¨ corretto.


Benchmark β€” Run #7 shard 3 vs Minerva 350M

Benchmark su 10 prompt in italiano (stesso set per entrambi i modelli, temperatura 0.8, n_predict 300).

Prompt SLM s3 Minerva 350M Vantaggio
Dante Alighieri nacque narrativa storica, nessun loop date inventate, deriva blog SLM
compilazione del kernel loop ridotto lista estensioni file pari (entrambi inutili)
un tramonto splendido palazzo ottomano, visivo risacca, nuvole, sensoriale Minerva
Le poesie di Ungaretti prosa critico-letteraria fluente blog evento, autori inventati SLM
La crisi del 1929 anno riconosciuto, contesto europeo confonde WWI con crisi '29 SLM
Il jazz nasce jazz = K-pop anni '90 festival jazz blog pari
La fotosintesi Γ¨ geologia giapponese lampade solari pari
Prepara una pasta loop "pourfail" ricetta reale (spinaci, panna) Minerva
La regione Puglia Γ¨ loop "Foggia" Γ—20 Vieste, dettagli reali Minerva
Francesco Benigni narrativa risorgimentale, zero loop blog fondazione parrocchiale SLM

Sintesi: SLM vince su 4 prompt (registro storico-enciclopedico e letterario), Minerva vince su 3 (registro pratico-sensoriale), 3 pari. I domini sono complementari: SLM non ha corpus culinario o turistico moderno, Minerva non ha corpus enciclopedico. Minerva 3B instruct non Γ¨ utilizzabile in raw completion (il wrapper [INST] attiva pattern web dal corpus).


Roadmap

Fase Obiettivo Stato
1 Architettura from scratch, char-level βœ… val loss 1.73
2 BPE-SPM tokenizer, Wikipedia IT βœ… completata
3 Pre-training medium (Run #3) βœ… val loss 4.08 β€” scorer PPL
4 RoPE, Run #4, export GGUF βœ… val loss 3.59
5 Corpus espansione CulturaX IT, 7 shard βœ… sweet spot a shard 4 (val 3.35), degradazione da shard 5
6 Run #6 β€” CulturaX sweet spot come base βœ… val loss 3.3524 (shard 4, run6-ad)
7 Run #7 β€” Wikipedia IT 3 shard su base run6-ad βœ… val loss 2.8165 Β· GGUF 56 MB
8 Run #8 β€” corpus dominio specifico πŸ”„ in design
9 SFT su dataset istruzione-seguente italiano ⏳ pianificata
10 LoRA adapter per dominio applicativo ⏳ pianificata
11 Multimodale: YOLO v3 + LM ⏳ pianificata
Downloads last month
168
GGUF
Model size
54.2M params
Architecture
gptneox
Hardware compatibility
Log In to add your hardware

8-bit

Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support