AI & MCP
Embedding per un catalogo: 111.985 vettori da mantenere
Indicizzare un catalogo con gli embedding costa poco una volta e molto quando cambia il modello. Il conto si fa prima: token in ingresso, 656 MiB di vettori, indice in memoria.
In sintesi
- Il testo da vettorizzare è nome, categoria e tag: il codice del componente non aggiunge significato.
- 111.985 vettori da 1.536 dimensioni occupano circa 656 MiB in float32, indice escluso.
- Cambiare modello significa rigenerare tutto: la dimensione dei vettori va salvata accanto ai dati.
Un catalogo si indicizza con gli embedding quando la ricerca deve capire la richiesta invece di copiare una parola: 111.985 componenti diventano 111.985 vettori da tenere allineati.
Cosa si vettorizza
- Nome, categoria e tag: è il testo con cui le persone descrivono ciò che cercano.
- Descrizione tagliata: i primi caratteri bastano; il resto diluisce il vettore.
- Codice escluso: 177.656 byte di snippet non aggiungono significato alla ricerca.
import OpenAI from 'openai';
const openai = new OpenAI();
async function embedBatch(items: { id: string; text: string }[]) {
const res = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: items.map((i) => i.text.slice(0, 2000)),
encoding_format: 'float',
});
return res.data.map((d, i) => ({ id: items[i].id, embedding: d.embedding }));
}
Il conto si fa prima
Il costo di una passata è il numero di token in ingresso diviso un milione per 0,02 $. Il costo che sorprende è il secondo: cambiare modello significa rigenerare ogni vettore, quindi la dimensione va salvata accanto ai dati e il prezzo del nuovo modello va letto prima di migrare.
curl -s "https://ui.eneawork.it/api/stats" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const j=JSON.parse(s);console.log(j.components*1536*4,'bytes')})"
Il comando legge il catalogo e moltiplica per la dimensione dichiarata: serve a rifare il conto quando il catalogo cresce, senza fidarsi del numero scritto qui.
Aggiornare, non ricostruire
Un catalogo cambia ogni giorno: si vettorizzano le righe nuove, si cancellano quelle rimosse e si rigenera solo ciò che è cambiato. L'indice si ricostruisce quando il recall peggiora, non a ogni inserimento.
La limitazione
656 MiB sono solo l'inizio: l'indice HNSW aggiunge strutture in memoria e va dimensionato. E non abbiamo una misura di qualità su questo catalogo, perché servirebbe un set di query con la risposta attesa che non abbiamo pubblicato.
Dove continuare
La scelta della ricerca è in ricerca semantica nel sito, il database in SQLite o Postgres, la struttura del catalogo in che cos'è un registry. I record: 111.985 componenti, 1.556 blocchi, Aceternity UI.
Domande frequenti
Quanti vettori servono per un catalogo di 111.985 elementi?
Uno per elemento, quindi 111.985. Se si vettorizzano anche blocchi e icone il numero cresce: 1.556 blocchi e 12.808 icone portano il totale a 126.349 vettori.
Quanto spazio occupano i vettori?
A 1.536 dimensioni in float32, 6.144 byte per vettore: circa 656 MiB per 111.985 elementi. Un indice HNSW aggiunge memoria e va dimensionato a parte.
Meglio embedding locali o API?
Locali quando il volume è alto e il testo non esce, API quando vuoi evitare di scaricare un modello da 9.990.867 byte come @huggingface/transformers 4.3.2. La differenza vera è chi paga la CPU.
Ogni quanto va rigenerato l'indice?
Quando cambia il modello o quando il recall scende. Con lo stesso modello bastano aggiornamenti incrementali sulle righe modificate, più una ricostruzione periodica pianificata.
Gli embedding sostituiscono la ricerca per parola chiave?
No, la completano. Il filtro esatto su categoria e libreria resta, la similarità ordina i risultati dentro quel sottoinsieme.