Modello di embedding italiano ottenuto trasformando Zagreus 0.4B — un LLM generativo italiano basato su architettura Llama 3.2 — in un estrattore di embeddings densi, seguendo le tecniche SOTA per modelli Decoder-only.
⚠️ Questi esperimenti sono realizzati a scopo didattico e di ricerca. Non sono destinati alla produzione.
Cosa rende questo modello diverso da un BERT
I modelli generativi come Zagreus sono Decoder causali: leggono rigorosamente da sinistra verso destra. Applicare il classico Mean Pooling diluirebbe il significato, perché i token iniziali non conoscono il contesto futuro. Questo modello adotta tre scelte architetturali SOTA:
1. Last Token Pooling (EOS Pooling)
L'ultimo token è l'unico che ha "letto" e digerito l'intera sequenza. Tutta la semantica della frase è collassata in quel singolo vettore finale.
2. Normalizzazione L2
Tutti i vettori sono proiettati sulla superficie di un'ipersfera unitaria. In questo spazio, Dot Product e Cosine Similarity diventano matematicamente equivalenti, rendendo l'addestramento più stabile e preciso.
3. Asymmetric Prompting
Il modello distingue tra query e documenti grazie a prompt espliciti nel testo:
Arrivare a questa versione ha richiesto diversi esperimenti, ognuno dei quali ha insegnato qualcosa. Il percorso completo:
Branch
Loss
Problema riscontrato
main (originale)
MNRL standard
Anisotropia — spazio vettoriale collassato
v2.0
CachedMNRL
✅ Anisotropia risolta, ma negativi BM25 non sfruttati
v4.0
CachedMNRL + TripletLoss
Collasso inverso — gap negativo (-0.165)
v5.0
GISTEmbedLoss + BM25
Compressione dello spazio, peggio di v2.0
v6.0
GISTEmbedLoss + guida e5-base
Spazi troppo distanti, filtro mal calibrato
v7.0 → main
CachedMNRL + negativi BM25 espliciti
✅ Best model
Il salto decisivo è stato usare CachedMultipleNegativesRankingLoss con il campo negative esplicito del dataset mmarco. Sentence Transformers tratta automaticamente il negativo BM25 come hard negative aggiuntivo rispetto ai negativi in-batch impliciti, senza bisogno di una seconda loss o di una guida esterna.
Perché CachedMultipleNegativesRankingLoss
Il training originale usava la MultipleNegativesRankingLoss standard, che su GPU con VRAM limitata (8GB) produceva batch effettivi troppo piccoli. Il risultato era l'anisotropia: i vettori collassavano in una piccola regione dello spazio, con similarità coseno artificialmente alta anche tra frasi senza alcuna relazione.
La CachedMultipleNegativesRankingLoss risolve il problema calcolando gli embedding a mini-chunk e assemblando la loss su un batch effettivo molto più grande, senza saturare la memoria.
Utilizzo
python
1from sentence_transformers import SentenceTransformer
23model = SentenceTransformer("nickprock/zagreus-0.4B-ita-embeddings")45# IMPORTANTE: usare sempre i prompt query:/passage:6sentences =[7'query: puoi dichiarare bancarotta senza un avvocato?',8'passage: Molte persone chiedono il fallimento del capitolo 7 senza un avvocato. '9'Alcuni si dichiarano in bancarotta perché non possono permettersi le spese legali. '10'Anche se è possibile archiviare da soli un fallimento del capitolo 7 con successo, '11'non è sempre saggio.',12'passage: In caso di conflitto tra le informazioni in questa pagina e le regole '13'applicabili, le regole prevalgono. Link alla dichiarazione di fallimento senza avvocato.',14]1516embeddings = model.encode(sentences)17print(embeddings.shape)18# [3, 960]1920similarities = model.similarity(embeddings, embeddings)21print(similarities)
Struttura: triplette (anchor, positive, negative) con negativi BM25
Iperparametri principali
Parametro
Valore
per_device_train_batch_size
32
num_train_epochs
1
learning_rate
2e-5
warmup_steps
0.1
gradient_accumulation_steps
2
gradient_checkpointing
True
bf16
True
tf32
True
optim
adamw_torch_fused
Training logs
Epoch
Training Loss
Validation Loss
0.337
1.856
1.865
0.674
1.818
1.809
1.000
1.799
—
Il modello migliore è stato salvato a epoch 0.674 con eval_loss = 1.809.
Risultati di valutazione
Metrica
v2.0 (precedente main)
v7.0 (main attuale)
Triplet Accuracy
100%
100%
Avg Margin (pos - neg)
+0.2158
+0.3669
MRR@5
1.0000
1.0000
Recall@1
100%
100%
Sim gap (simili - dissimili)
+0.0730
+0.2801
Il sim gap è quasi 4 volte più grande rispetto alla versione precedente — il miglioramento più significativo dell'intera serie di esperimenti.
Limitazioni note
Il dataset MMarco italiano è una traduzione automatica della versione inglese. I negativi BM25 risentono del rumore introdotto dalla traduzione, ma in questo caso — a differenza degli esperimenti con GISTEmbedLoss e hard negative mining — il rumore non ha impedito al modello di imparare: CachedMNRL è abbastanza robusta da estrarre segnale utile anche da negativi imperfetti.
La query "Cosa causa il cambiamento climatico?" rimane il caso più difficile (pos=0.369, il più basso del set di test), probabilmente per la natura astratta e aperta della domanda più che per limiti del modello.
Citazioni
bibtex
1@inproceedings{reimers-2019-sentence-bert,
2 title = "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks",
3 author = "Reimers, Nils and Gurevych, Iryna",
4 booktitle = "Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing",
5 month = "11",
6 year = "2019",
7 publisher = "Association for Computational Linguistics",
8 url = "https://arxiv.org/abs/1908.10084",
9}
1011@misc{gao2021scaling,
12 title={Scaling Deep Contrastive Learning Batch Size under Memory Limited Setup},
13 author={Luyu Gao and Yunyi Zhang and Jiawei Han and Jamie Callan},
14 year={2021},
15 eprint={2101.06983},
16 archivePrefix={arXiv},
17 primaryClass={cs.LG}
18}