Finora fare RAG su documenti visivi — PDF scansionati, screenshot, slide, immagini di prodotto — richiedeva pipeline complesse con OCR, pre-processing e modelli separati per testo e immagini. Sentence Transformers v5.4 cambia questo: con una singola API puoi creare embedding multimodali su testo, immagini e video, e costruire sistemi di ricerca semantica che funzionano cross-modale. Requisito minimo: Python 3.9+, GPU con 8GB VRAM per i modelli 2B.

Cosa ottieni alla fine

Un sistema RAG che risponde a query di testo cercando tra documenti visivi — PDF come immagini, screenshot di interfacce, cataloghi prodotto fotografati. Stessa API che già conosci da Sentence Transformers, zero cambio di paradigma. Il modello principale è Qwen3-VL-Embedding-2B: 2 miliardi di parametri, input testo + immagini + video, 8GB VRAM.

Hardware: cosa serve per girare i modelli

GPU VRAM Modello consigliato Velocità embedding Note
RTX 4060 / 4060 Ti 8 GB / 16 GB Qwen3-VL-Embedding-2B ~12 img/s Ideale per 2B — 16GB per batch grandi
RTX 4070 / 4070 Super 12 GB Qwen3-VL-Embedding-2B ~18 img/s Buon equilibrio velocità/costo
RTX 4070 Ti Super / 4080 16 GB Qwen3-VL-Embedding-2B/8B ~25 img/s (2B) 8B funziona ma lento senza offload
RTX 4090 / RTX 5080 24 GB Qwen3-VL-Embedding-8B ~20 img/s 8B fluido — qualità massima
Apple M3 Pro / M4 Pro 18-48 GB unified Qwen3-VL-Embedding-2B/8B ~8 img/s (2B) MPS backend, velocità inferiore alla GPU dedicata
CPU only RAM sistema Qwen3-VL-Embedding-2B <1 img/s Estremamente lento — solo per test

Il principio è identico alla VRAM per gli LLM: il modello deve stare interamente in memoria GPU per lavorare a velocità utile. Con Qwen3-VL-Embedding-2B pesano circa 6GB in bfloat16 — lasci margine per il batch.

Modelli disponibili: tabella completa

Modello Parametri VRAM Modalità Caso d’uso
Qwen3-VL-Embedding-2B 2B ~8 GB Testo, Immagine, Video Uso generale, RAG su documenti
Qwen3-VL-Embedding-8B 8B ~20 GB Testo, Immagine, Video Alta qualità, corpus grandi
nvidia/llama-nemotron-embed-vl-1b-v2 1.7B ~6 GB Testo, Immagine Hardware limitato
Qwen3-VL-Reranker-2B 2B ~8 GB Testo, Immagine, Video Reranking dopo retrieval
nvidia/llama-nemotron-rerank-vl-1b-v2 1.7B ~6 GB Testo, Immagine Reranking leggero

Step 1 — Installazione

# Installa Sentence Transformers con supporto immagini
pip install -U "sentence-transformers[image]"

# Per supporto audio (opzionale)
pip install -U "sentence-transformers"

# Per video (opzionale, peso extra)
pip install -U "sentence-transformers"

# Verifica versione installata (deve essere >= 5.4)
python -c "import sentence_transformers; print(sentence_transformers.__version__)"

Step 2 — Carica il modello e crea embedding

from sentence_transformers import SentenceTransformer

# Carica Qwen3-VL-Embedding-2B
# La revision è obbligatoria — il modello è in PR su HuggingFace
model = SentenceTransformer(
    "Qwen/Qwen3-VL-Embedding-2B",
    revision="refs/pr/23",
    model_kwargs={
        "torch_dtype": "bfloat16",          # Dimezza la VRAM rispetto a float32
        "attn_implementation": "flash_attention_2",  # Richiede GPU Ampere+
    }
)

# Verifica modalità supportate
print(model.modalities)
# Output atteso: ['text', 'image', 'video', 'message']

# Embedding di testo
testo_embeddings = model.encode([
    "fattura Q1 2026 con errore IVA",
    "grafico vendite anno corrente",
])

# Embedding di immagini (URL, path o PIL Image)
img_embeddings = model.encode([
    "./screenshot_fattura.png",
    "https://example.com/grafico.jpg",
])

# Similarità cross-modale testo → immagini
similarita = model.similarity(testo_embeddings, img_embeddings)
print(similarita)
# tensor([[0.82, 0.11],   # testo 0 molto simile a img 0
#         [0.09, 0.79]])  # testo 1 molto simile a img 1

Step 3 — Pipeline RAG completa con retrieval e reranking

from sentence_transformers import SentenceTransformer, CrossEncoder
import os
import numpy as np

# --- FASE 1: Indicizzazione del corpus ---
embedder = SentenceTransformer(
    "Qwen/Qwen3-VL-Embedding-2B",
    revision="refs/pr/23",
    model_kwargs={"torch_dtype": "bfloat16"}
)

# Lista dei tuoi documenti (screenshot, PDF come immagini, foto)
corpus_docs = [
    "./docs/fattura_2026_01.png",
    "./docs/grafico_vendite_q1.jpg",
    "./docs/contratto_fornitore.png",
    # ... aggiungi tutti i tuoi documenti
]

# Crea embedding del corpus (fallo una volta e salva)
corpus_embeddings = embedder.encode_document(
    corpus_docs,
    batch_size=8,
    show_progress_bar=True
)
# Salva per non ricalcolare ogni volta
np.save("corpus_embeddings.npy", corpus_embeddings)

# --- FASE 2: Retrieval con query testuale ---
query = "mostrami le fatture con IVA errata del 2026"
query_embedding = embedder.encode_query(query)

# Calcola similarità e prendi top-10
similarita = embedder.similarity(query_embedding, corpus_embeddings)[0]
top10_indices = similarita.argsort(descending=True)[:10].tolist()
top10_docs = [corpus_docs[i] for i in top10_indices]

# --- FASE 3: Reranking dei top-10 ---
reranker = CrossEncoder(
    "Qwen/Qwen3-VL-Reranker-2B",
    revision="refs/pr/11",
    trust_remote_code=True,
)

rankings = reranker.rank(query, top10_docs)
for rank in rankings[:3]:  # Stampa i top-3 dopo reranking
    doc_path = top10_docs[rank["corpus_id"]]
    print(f"Score: {rank['score']:.4f} — {doc_path}")

Performance attese nella pratica

Setup avanzato: ottimizzazione per corpus grandi

# Per corpus da migliaia di documenti, usa FAISS per il retrieval
# pip install faiss-gpu  # oppure faiss-cpu

import faiss
import numpy as np

# Carica embedding pre-calcolati
corpus_embeddings = np.load("corpus_embeddings.npy").astype("float32")

# Crea indice FAISS
dimension = corpus_embeddings.shape[1]  # 2048 per Qwen3-VL-2B
index = faiss.IndexFlatIP(dimension)  # Inner product = cosine similarity su vettori normalizzati
faiss.normalize_L2(corpus_embeddings)
index.add(corpus_embeddings)

# Salva indice
faiss.write_index(index, "corpus.faiss")

# Retrieval ultra-veloce su corpus da 100k documenti
query_vec = np.array([query_embedding]).astype("float32")
faiss.normalize_L2(query_vec)
scores, indices = index.search(query_vec, k=10)  # Top-10 in millisecondi

Risoluzione problemi comuni

Risorse

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *