Database vettoriali: cercare per significato
Dove finiscono i vettori dei tuoi documenti e come si fa a ritrovarli in fretta. Indici, metriche di distanza e la scelta fra le opzioni che contano davvero, senza cambiare strumento tre volte.
Il video parte solo se lo chiedi: nessuna richiesta a YouTube prima del click.
Un database normale risponde a domande esatte: dammi le righe dove il nome è “Marco”. Un database vettoriale risponde a una domanda diversa: dammi i testi che parlano di qualcosa di simile a questo. È il pezzo che tiene in piedi il recupero, e l’unico componente della pipeline che si comporta come un’infrastruttura vera — con indici, compromessi e conti da fare.
SQL
SELECT * FROM documenti WHERE titolo LIKE '%polimorfismo%'
→ trova solo se quella parola compare nel titolo
Vettoriale
cerca(vettore("come funziona l'ereditarietà in Java"))
→ trova anche override, classi astratte, polimorfismo:
significati vicini, parole diverse
Cosa contiene, davvero
Una riga in un archivio vettoriale non è solo un vettore. Sono tre cose, e servono tutte:
id: "manuale-java#chunk-23"
vettore: [0.23, 0.87, -0.12, 0.45, ...] ← per cercare
testo: "Il polimorfismo permette a..." ← per rispondere
metadati: { fonte: "manuale.pdf", pagina: 145, sezione: "5.3" }
Il vettore serve a trovare, il testo serve al modello per rispondere, i metadati servono a filtrare e citare. Un archivio che salva solo i vettori ti costringe a tenere i testi da un’altra parte e a riallinearli a mano: sembra un dettaglio, diventa un problema alla prima reindicizzazione.
Come si misura la vicinanza
Tre metriche, ma la scelta è più semplice di quanto sembri.
Similarità del coseno. Guarda l’angolo fra due vettori e ignora la loro lunghezza. Va da -1 a 1, dove 1 vuol dire “stessa direzione”, cioè stesso significato. È lo standard per il testo, ed è quello che vuoi in quasi tutti i casi.
Distanza euclidea. La distanza in linea d’aria fra due punti. Tiene conto anche della lunghezza dei vettori, che nel testo di solito non significa nulla.
Prodotto scalare. Combina direzione e lunghezza. Su vettori normalizzati coincide con il coseno, ed è quello che diversi archivi usano sotto il cofano proprio per questo.
Regola pratica: coseno, e passa oltre. L’unica accortezza è restare coerente: se indicizzi con una metrica e cerchi con un’altra, i punteggi non vogliono dire niente.
Gli indici: perché non si confrontano tutti i vettori
Con mille pezzi puoi confrontare la domanda con tutti, uno per uno, e prendere i più vicini. È esatto e costa niente. Con un milione di pezzi la stessa cosa diventa improponibile, e allora si usa un indice che accetta di essere quasi esatto in cambio della velocità.
| Indice | Come funziona | Il compromesso |
|---|---|---|
| Esatto (flat) | Confronta tutto | Preciso al 100%, lento sui grandi numeri |
| HNSW | Grafo navigabile a livelli | Molto veloce, si mangia RAM |
| IVF | Raggruppa i vettori in gruppi | Buon equilibrio, va tarato |
| Quantizzazione | Comprime i vettori | Poca RAM, un po’ di precisione persa |
La cosa che conta: sotto il centinaio di migliaia di pezzi, l’indice esatto va benissimo. Prima di quella soglia, mettersi a tarare un HNSW è tempo speso a ottimizzare qualcosa che non è il problema. Il problema, a quel punto, è ancora il chunking.
C’è un’implicazione che sorprende: dal momento in cui usi un indice approssimato, il recupero può perdere un pezzo pertinente che l’indice esatto avrebbe trovato. Non è un difetto, è il prezzo scelto. Ma quando confronti la qualità di due configurazioni, ricordati che stai confrontando anche questo.
Le opzioni, in ordine di quando servono
| Chroma | FAISS | LanceDB | Qdrant | Pinecone | |
|---|---|---|---|---|---|
| Come gira | Nel tuo processo | Libreria | Nel tuo processo | Server | Servizio cloud |
| In locale | Sì | Sì | Sì | Sì | No |
| Filtri sui metadati | Sì | No | Sì | Avanzati | Sì |
| Salva su disco da solo | Sì | No, a mano | Sì | Sì | Gestito |
| Per iniziare | Consigliato | No | Sì | Poi | No |
| In produzione | Piccola scala | Con impalcatura | Media scala | Sì | Sì |
Chroma per iniziare: si installa e funziona, salva su disco, tiene testo e metadati insieme. FAISS è la libreria più veloce in circolazione ma non è un database: niente persistenza, niente filtri: sei tu a doverti costruire il contorno. Qdrant è il passo successivo quando servono filtri seri o più utenti. Pinecone toglie la manutenzione e in cambio si porta i tuoi documenti su un servizio altrui — che per appunti personali o materiale aziendale è esattamente la domanda da farsi prima, non dopo.
I filtri sui metadati contano più della velocità
La ricerca puramente semantica ha un difetto pratico: non sa dire di no. Se chiedi qualcosa sul capitolo 5 e il capitolo 5 non parla di quello, ti restituisce comunque i pezzi meno lontani, presi da qualunque punto dell’archivio.
I filtri risolvono questo, e sono la ragione per cui i metadati vanno salvati fin dall’inizio:
cerca(vettore("rimborso spese"), filtro={ fonte: "regolamento-2026.pdf" })
cerca(vettore("polimorfismo"), filtro={ capitolo: 5 })
cerca(vettore("ferie"), filtro={ lingua: "it", anno: { ">=": 2025 } })
Un archivio senza filtri ti obbliga a fare la selezione dopo aver recuperato, cioè quando hai già sprecato il recupero. È il motivo principale per cui si cambia strumento a metà progetto.
Dove si sbaglia
Cambiare modello di embedding senza rifare l’archivio. I vecchi vettori vivono in uno spazio, i nuovi in un altro: le distanze diventano numeri senza senso. Non c’è un errore, c’è solo un recupero che peggiora senza motivo apparente. Se cambi modello, si ricostruisce tutto.
Reindicizzare senza svuotare. Rilanciare l’indicizzazione sugli stessi documenti senza cancellare produce doppioni: lo stesso testo occupa due o tre posti fra i primi risultati, e il modello riceve tre copie della stessa cosa invece di tre pezzi diversi.
Salvare i vettori e non i testi. Recuperi gli identificativi e poi devi andare a ripescare i testi da un’altra parte, sperando che nel frattempo nessuno abbia rinumerato i pezzi.
Ottimizzare l’indice prima del resto. Su archivi piccoli la scelta dell’indice non si sente: si sentono il chunking e il modello di embedding. L’ordine in cui vale la pena lavorare è quello, non il contrario.
Fidarsi del punteggio come se fosse una probabilità. Un coseno di 0,82 non vuol dire “82% giusto”. I punteggi sono confrontabili fra loro nella stessa ricerca, non in assoluto: la soglia sotto la quale scartare un risultato va misurata sui propri documenti, non copiata.
In sintesi
| Concetto | In una riga |
|---|---|
| Database vettoriale | Archivia vettori e trova i più vicini a una domanda |
| Cosa salvare | Vettore per cercare, testo per rispondere, metadati per filtrare |
| Metrica | Coseno, salvo casi particolari |
| Indice esatto | Sotto le centinaia di migliaia di pezzi va benissimo |
| Indici approssimati | Velocità in cambio di qualche pezzo pertinente perso |
| Da dove partire | Chroma in locale; Qdrant quando servono filtri o scala |
| Filtri sui metadati | Spesso più utili della velocità pura |
| Errore ricorrente | Cambiare modello di embedding senza ricostruire l’archivio |
- RAG
- Database vettoriali
- Ricerca semantica
Lezioni collegate
- Chunking: come si spezzano i documenti
La scelta più sottovalutata di tutta la pipeline RAG. Da come tagli i testi dipende cosa il sistema riuscirà a trovare: un chunking sbagliato rende inutili il miglior modello di embedding e il miglior LLM.
- Costruire un RAG in locale, dal PDF alla risposta
La pipeline completa su una macchina sola: estrarre il testo dai PDF, indicizzarlo, interrogarlo. Con i punti dove si inciampa davvero e come si capisce se sta funzionando.
- Cos'è il RAG: far leggere i tuoi documenti a un modello
Un modello non conosce i tuoi file. Il RAG glieli fa consultare al momento della domanda: prima cerca, poi risponde. È la differenza fra un esame a libro chiuso e uno a libro aperto.