Dan Levy

Ricerca vettoriale semantica e altri argomenti per conquistare amici e amanti

Il panorama completo della ricerca: esatta, fuzzy, semantica, ibrida — e quando combinarle tutte.

La ricerca non è una cosa sola, e la ricerca semantica non sostituisce tutto il resto.

Panoramica della ricerca vettoriale: confronto tra 16 opzioni

Confronta modalità di deployment, licenza, capacità di ricerca e adeguatezza ai diversi workload. Le spiegazioni delle colonne e gli esempi SQL seguono più avanti.

Come leggere questo confronto

DatabaseDeploymentLicenzaRicerca ibridaVettori sparsiInterfaccia di queryEmbedding multimodale integratoIndice su discoLimiti sulla dimensionalità dei vettoriIdeale per
pgvectorSelf-host / gestito (Supabase, Neon, RDS)OSS (PostgreSQL)Manuale (RRF via SQL)❌✅ SQL completo❌✅ HNSW su disco16.000 per lo storage; 2.000 indicizzati con vectorChi è già su Postgres; quantità moderate di vettori
QdrantSelf-host / CloudApache 2.0✅ BM25 nativo✅ Supporto maturo❌ (REST/gRPC)❌✅65.535Query filtrate su larga scala; metadati complessi
WeaviateSelf-host / CloudBSD 3✅ BM25 nativo + RRF✅❌ (GraphQL / gRPC)✅ tramite moduli✅65.535Pattern di accesso GraphQL; vettorializzazione integrata
PineconeSolo CloudProprietaria✅ (aggiunta nel 2024)✅❌❌✅ (serverless)20.000Semplicità gestita; nessun team operations
Milvus / ZillizSelf-host / Cloud (Zilliz)Apache 2.0✅ Nativa✅✅ Simile a SQL (Milvus Query Language)✅✅ DiskANN32.768Scala di miliardi di elementi; on-prem enterprise
ChromaEmbedded / self-hostApache 2.0❌❌❌❌❌65.535Solo sviluppo locale e prototipazione
LanceDBEmbedded / CloudApache 2.0✅❌✅ SQL tramite DataFusion✅ Nativa✅ (formato Lance)IllimitataEdge / serverless; lakehouse multimodale
OramaEmbedded / CloudApache 2.0✅ Full-text + vettoriale❌❌❌❌VariabileApp JavaScript/edge; ricerca leggera per siti e app
TurbopufferSolo Cloud (serverless)Proprietaria✅ BM25 + vettoriale❌❌❌✅ (object storage)16.000SaaS multi-tenant; milioni di namespace
ElasticsearchSelf-host / Elastic CloudSSPL / AGPLv3✅ RRF + ELSER sparso✅ (ELSER)✅ Query DSL❌✅ DiskBBQ4.096Chi è già sullo stack Elastic; ricerca enterprise ibrida
OpenSearchSelf-host / gestito da AWSApache 2.0✅ RRF + Neural Search✅✅ Query DSL❌✅ FAISS + HNSW16.000Ambienti AWS-native; alternativa open source a Elastic
VespaSelf-host / CloudApache 2.0✅ Nativa✅ Tensor / ranking lessicale✅ YQL✅ Tensor✅Di fatto illimitataSistemi di ricerca + ranking + raccomandazione
ClickHouseSelf-host / CloudApache 2.0Manuale❌✅ SQL completo❌✅ Colonnare + HNSWVariabileAnalytics/log con ricerca vettoriale accanto all’OLAP
MongoDB AtlasCloud / self-hostSSPL✅ Integrata❌✅ MQL + aggregazione❌✅ HNSW8.192Chi è già su MongoDB; documenti + vettori in un unico sistema
Redis (VSS)Self-host / Redis CloudRSALv2 / SSPL✅ (RediSearch)✅❌❌❌ Solo RAM32.768Latenza ultra-bassa; ricerca vettoriale nel livello cache
MarqoCloud / self-hostApache 2.0✅❌❌✅ Focus nativo✅VariabileMultimodale end-to-end: immagini + testo + video

“Trova l’utente con l’email dan@example.com” e “trovami articoli sul debugging per chi è un ingegnere alle prime armi” vengono entrambi descritti come ricerca, ma come problemi ingegneristici hanno ben poco in comune. Nel primo caso esiste una risposta corretta e una ricerca su indice O(log n). Nel secondo non esiste una risposta corretta: esiste solo la rilevanza, e serve comprendere linguaggio, intento e significato.

Gli ingegneri più convincenti quando si prendono decisioni sulla ricerca — quelli che vincono le discussioni e realizzano il sistema giusto — conoscono l’intero panorama. Sanno quale strumento usare e perché, e sanno spiegarlo con chiarezza.

Questo articolo tratta il livello semantico: cosa fa davvero la ricerca vettoriale, quando è la scelta migliore e quando dovrebbe restare fuori dai piedi. La versione utile non è “fare l’embedding di tutto”. È sapere quando i vettori devono affiancare la ricerca lessicale, fuzzy ed exact-match in un’architettura ibrida.

La metà lessicale e fuzzy del problema — tsvector, pg_trgm, pg_search — è trattata nella Guida alla ricerca testuale in Postgres 2026.


Termini usati in questa guida

Embedding — Un elenco denso di numeri in virgola mobile prodotto da un modello, che rappresenta un testo (o un’immagine, un audio e così via) come un punto in uno spazio ad alta dimensionalità. I contenuti semanticamente correlati finiscono vicini; quelli non correlati finiscono lontani.

Ricerca lessicale — Ricerca basata sulla corrispondenza esatta di parole e token. È veloce, deterministica e corretta per i termini noti. Non comprende sinonimi, parafrasi o equivalenti tra lingue diverse.

Ricerca semantica — Ricerca basata sul significato anziché sui token. Una query come “come gestisco i timeout” può trovare un documento intitolato “configurazione delle policy di retry” senza alcuna parola in comune, perché i rispettivi embedding sono geometricamente vicini.

Vettore — Un elenco di numeri. Nel contesto della ricerca, è l’output di un modello di embedding. La “ricerca vettoriale” trova i vettori più vicini a un vettore di query in base alla distanza geometrica.

FTS (Full-Text Search) — La ricerca lessicale integrata di Postgres, basata su tsvector / tsquery. Tokenizza, riconduce le parole alla radice e indicizza il testo per le query basate su keyword. È efficace per la prosa e la ricerca di termini esatti; non sa nulla del significato.

BM25 — Un algoritmo di ranking per la ricerca lessicale (usato da Elasticsearch, Qdrant e altri). Assegna un punteggio ai risultati in base alla frequenza del termine, pesata rispetto alla sua rarità nell’intero corpus. È migliore della semplice corrispondenza di keyword; resta comunque lessicale.

HNSW (Hierarchical Navigable Small World) — L’indice standard per la ricerca approssimata dei vicini più prossimi nei vettori. Costruisce un grafo di prossimità a livelli per eseguire rapidamente query di similarità con alta probabilità di recupero. Lo usano pgvector, Qdrant, Weaviate e quasi tutti gli altri.

RRF (Reciprocal Rank Fusion) — Un algoritmo per combinare liste di risultati ordinate provenienti da più sistemi di retrieval. Usa solo la posizione in classifica: non serve normalizzare i punteggi. Un risultato che si trova in alto sia nella lista FTS sia in quella vettoriale riceve un punteggio combinato più alto rispetto a uno che prevale nettamente in una sola delle due.


Come gli embedding trovano contenuti correlati

Gli embedding vettoriali convertono il testo (o immagini, audio e così via) in una lista di numeri: un punto in uno spazio ad alta dimensionalità. Un modello di embedding viene addestrato in modo che i testi semanticamente correlati finiscano vicini in quello spazio. “Dog” e “canine” finiscono vicini. “Running a marathon” e “running a Python script” finiscono lontani, nonostante condividano una parola.

La ricerca per similarità in quello spazio individua i documenti il cui significato è più vicino a quello della query, indipendentemente dalla sovrapposizione esatta delle parole.

Questo significa che:

La ricerca lessicale (tsvector, pg_trgm) non può fare nulla di tutto questo. Opera su parole e caratteri, non sul significato. Gli strumenti non sono intercambiabili: risolvono problemi diversi.


Quando pgvector è la scelta giusta

Per costruire sistemi RAG. La Retrieval-Augmented Generation recupera i chunk di documenti il cui significato è più vicino alla domanda dell’utente, poi li passa a un modello linguistico come contesto. Questo passaggio di retrieval è un’operazione vettoriale. FTS non trova parafrasi, sinonimi e corrispondenze concettuali che un chunk rilevante potrebbe esprimere in modo diverso. Il vantaggio di pgvector rispetto a un vector store separato: gira dentro l’istanza Postgres che già usi; non devi fare il deploy, gestire o sincronizzare i dati con un servizio aggiuntivo.

Quando gli utenti descrivono ciò che vogliono, non cosa cercare. “Articoli su come costruire la fiducia in sé come nuovo manager” non contiene keyword che compaiano in modo affidabile nei post pertinenti. “Un framework leggero per gestire gli effetti collaterali” potrebbe non usare quelle parole esatte nella documentazione. La ricerca vettoriale cerca l’intento, non l’ortografia.

Per trovare elementi simili. Prodotti correlati, ticket di supporto simili, segnalazioni di bug duplicate, articoli che potrebbero interessarti. “Trova issue simili a questa” è una ricerca dei vicini più prossimi: incorpori l’elemento e trovi i suoi vicini geometrici. Una precisazione importante: la ricerca vettoriale restituisce sempre dei risultati, anche quando nulla è davvero simile. Nei casi d’uso di deduplicazione e raccomandazione, filtra in base a una soglia minima di similarità (ad esempio, similarità coseno ≥ 0,80) per evitare di presentare corrispondenze poco affidabili come se avessero un significato.

Deduplicazione semantica. Prima di indicizzare contenuti per RAG o ricerca, spesso devi identificare i quasi-duplicati nel corpus: articoli revisionati più volte, ticket di supporto aperti due volte, voci della knowledge base con una sovrapposizione significativa. Genera gli embedding dei documenti e applica una soglia sulla similarità coseno per segnalare o unire i quasi-duplicati prima che contaminino l’indice. In questo modo eviti che il retrieval restituisca più chunk quasi identici e diluisca il contesto disponibile.

Ricerca multilingue. I modelli di embedding multilingue mappano contenuti semanticamente equivalenti in lingue diverse su vettori vicini. Una query in spagnolo per “perder peso” può trovare un articolo in inglese sulle “abitudini sostenibili per perdere peso”: nessun token condiviso, stesso significato di fondo. FTS richiede una configurazione del dizionario per ogni lingua e gestisce male le query cross-language. pg_trgm è indipendente dalla lingua, ma opera sull’ortografia, non sulla semantica.

Configurare pgvector

Dall’installazione dell’estensione alla query di similarità, la configurazione richiede una manciata di istruzioni SQL:

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
-- HNSW is usually the first index to try for moderate-size datasets
CREATE INDEX documents_embedding_idx
ON documents USING hnsw (embedding vector_cosine_ops);
-- Semantic search query
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
ORDER BY embedding <=> $1::vector
LIMIT 10;

<=> è la distanza coseno. 1 - cosine_distance restituisce la similarità coseno (1,0 = identico, 0,0 = ortogonale). Per ivfflat (l’alternativa più vecchia e più rapida da costruire), usa lists = sqrt(row_count) come punto di partenza.

Dove la ricerca vettoriale restituisce la risposta sbagliata


Combina parole chiave e vettori per le query miste

La documentazione tecnica è l’esempio più chiaro di un caso in cui nessuno dei due strumenti è sufficiente da solo.

Chi cerca “come configurare i timeout” ha bisogno di una corrispondenza concettuale: un articolo intitolato “Configurare le policy di retry e i limiti di connessione” non contiene parole chiave in comune, ma è esattamente quello che serve.

Gli stessi utenti cercano anche withRetry(), ECONNRESET ed ERR_SOCKET_TIMEOUT. Queste stringhe esatte devono comparire: la corrispondenza semantica potrebbe non trovarle in modo affidabile e un falso positivo — concettualmente simile, ma riferito all’API sbagliata — è fuorviante in modo concreto.

La ricerca vettoriale gestisce le query concettuali. FTS gestisce i termini esatti. Nessuno dei due, da solo, gestisce bene entrambi i casi.

La soluzione è la ricerca ibrida: esegui entrambe le ricerche e combina i risultati.

Unisci i risultati classificati con RRF

La Reciprocal Rank Fusion (RRF) è l’algoritmo standard per combinare liste classificate provenienti da sistemi di retrieval diversi. Non richiede di normalizzare i punteggi tra i sistemi: usa soltanto le posizioni in classifica. Un risultato che compare in alto in entrambe le liste riceve un punteggio combinato maggiore rispetto a uno che domina in una sola.

WITH fts_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, query) DESC) AS rank
FROM documents, to_tsquery('english', $1) query
WHERE search_vector @@ query
LIMIT 50
),
vector_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
FROM documents
ORDER BY embedding <=> $2::vector
LIMIT 50
),
rrf AS (
SELECT
COALESCE(f.id, v.id) AS id,
COALESCE(1.0 / (60 + f.rank), 0) +
COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score
FROM fts_results f
FULL OUTER JOIN vector_results v ON f.id = v.id
)
SELECT d.id, d.title, rrf.rrf_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

Il 60 al denominatore è la costante RRF. Valori più alti attenuano le differenze tra le posizioni in classifica; valori più bassi le amplificano. Il valore predefinito, 60, funziona bene per la maggior parte dei tipi di contenuto.

RRF evita il problema più difficile di normalizzare ts_rank — un punteggio basato sulla frequenza logaritmica — rispetto alla distanza coseno, una misura geometrica. Non sono confrontabili. RRF chiede soltanto: “quanto in alto è comparso questo risultato in ciascuna lista?”

Aggiungi i trigrammi per refusi e nomi

Per la ricerca rivolta agli utenti su contenuti misti — in cui, nella stessa sessione, si può cercare il nome di una persona, un concetto o un termine esatto — la fusione a tre vie gestisce tutti i casi:

WITH trgm_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY similarity(title, $1) DESC) AS rank
FROM documents
WHERE title % $1
LIMIT 50
),
fts_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, to_tsquery('english', $1)) DESC) AS rank
FROM documents
WHERE search_vector @@ to_tsquery('english', $1)
LIMIT 50
),
vector_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
FROM documents
ORDER BY embedding <=> $2::vector
LIMIT 50
),
rrf AS (
SELECT
COALESCE(t.id, f.id, v.id) AS id,
COALESCE(1.0 / (60 + t.rank), 0) +
COALESCE(1.0 / (60 + f.rank), 0) +
COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score
FROM trgm_results t
FULL OUTER JOIN fts_results f ON t.id = f.id
FULL OUTER JOIN vector_results v ON COALESCE(t.id, f.id) = v.id
)
SELECT d.id, d.title, rrf.rrf_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

Gestisce corrispondenze fuzzy dei nomi (trigrammi), corrispondenze esatte delle parole chiave (FTS) e query concettuali (vettori). Una singola casella di ricerca può servire tutti e tre gli intenti degli utenti.


Associa ogni superficie di ricerca ai relativi tipi di query

Le applicazioni reali hanno raramente una sola superficie di ricerca. Ne hanno diverse, ciascuna con esigenze differenti:

SuperficieCosa cercano gli utentiLivelli consigliati
Ricerca in blog / documentazioneParole chiave + concettiFTS + pgvector (RRF)
Ricerca di nomi di utenti/clientiNomi con refusipg_trgm
Ricerca prodottiNomi, descrizioni, “simile a”pg_trgm + FTS + pgvector
Deduplicazione dei ticket di supporto”Problemi simili a questo”Solo pgvector
Ricerca interna di SKU/ordiniIdentificatori esattiIndice B-tree
RAG su una knowledge base ampiaDomande in linguaggio naturalepgvector (documenti suddivisi in chunk)
“Potrebbe piacerti anche” nell’e-commerceSimilarità comportamentale + semanticapgvector
AutocompletePrefisso, tolleranza agli errori ortograficipg_trgm

Non sono casi ipotetici. La maggior parte delle applicazioni ricche di contenuti ha almeno due superfici di ricerca distinte, con forme di query differenti. La tentazione è scegliere un unico approccio e usarlo ovunque — di solito oggi la ricerca vettoriale, perché è la scelta di moda. Il risultato sono embedding costosi per problemi in cui un indice trigram sarebbe stato più veloce, più economico e più corretto.

Aggiungi un livello di ricerca quando un tipo di query fallisce

Aggiungi un livello quando compare una modalità di errore che quello attuale non può risolvere:


Quando andare oltre pgvector

pgvector copre gran parte delle esigenze di ricerca applicativa prima che serva un altro database. La soglia indicativa dipende dal numero di vettori, dalle impostazioni dell’indice, dalla frequenza di scrittura, dai filtri, dall’hardware e dalla concorrenza; quindi considera qualunque regola del tipo “meno di 10 milioni di vettori” come un’ipotesi iniziale da verificare con benchmark, non come un limite del prodotto. Quando lo superi davvero — concorrenza molto elevata, requisiti di latenza p99 molto bassa, miliardi di vettori o esigenze serie di isolamento tra tenant — il panorama dei database vettoriali dedicati è ampio e vale la pena conoscerlo.

Come leggere il confronto

Ricerca ibrida significa eseguire la ricerca per parole chiave BM25 e la similarità vettoriale in un’unica query, combinandole tramite RRF. Senza questa funzione, devi scegliere una sola modalità di ricerca oppure fondere manualmente due query.

I vettori sparsi vanno oltre BM25. Un vettore sparso SPLADE ha circa 30.000 dimensioni (una per ogni termine del vocabolario), di cui circa il 98% è composto da zeri. Le posizioni non nulle indicano quali termini contano e in quale misura. Una query per “dogs” assegna peso anche a “canine” e “pet”: precisione a livello BM25 più espansione dei termini all’interno di un indice vettoriale. Se questa colonna è false, ti serve un livello FTS separato per le query basate sui termini esatti.

# SPLADE: ~30,000 dims, ~60 non-zero — only relevant vocabulary positions fire
def encode_splade(text: str) -> dict:
tokens = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
with torch.no_grad():
output = model(**tokens)
vec = torch.log1p(torch.relu(output.logits)).max(dim=1).values.squeeze()
return {"indices": vec.nonzero().squeeze().tolist(), "values": vec[vec != 0].tolist()}

SQL / simile a SQL riguarda in realtà il filtraggio. La ricerca vettoriale senza filtri è una demo. Servono comunque l’ambito del tenant, gli intervalli di date, i permessi e i filtri per categoria. Il SQL completo (pgvector, LanceDB) permette di esprimere tutto questo accanto alle join già esistenti. I database progettati per questo scopo usano oggetti filtro JSON (Qdrant, Pinecone), una query DSL (Elasticsearch, Milvus) o GraphQL (Weaviate). Funzionano; il SQL diventa più interessante quando la logica dei filtri si fa complessa.

-- pgvector: vector similarity is just another expression
SELECT id, title, 1 - (embedding <=> $1) AS score
FROM documents
WHERE tenant_id = $2
AND category = ANY($3::text[])
AND created_at > NOW() - INTERVAL '90 days'
ORDER BY embedding <=> $1
LIMIT 10;
# Qdrant: equivalent filter as a Python object — same result, more ceremony
results = client.query_points(
collection_name="documents", query=query_embedding,
query_filter=models.Filter(must=[
models.FieldCondition(key="tenant_id", match=models.MatchValue(value=tenant_id)),
models.FieldCondition(key="category", match=models.MatchAny(any=categories)),
models.FieldCondition(key="created_at", range=models.DatetimeRange(gte=cutoff)),
]),
limit=10,
)

Multimodale nativo significa che il database include modelli di embedding per contenuti non testuali. Gli passi l’URL di un’immagine grezza e si occupa della vettorizzazione. La maggior parte dei database è agnostica rispetto agli embedding: la pipeline di embedding resta a tuo carico. Marqo e Weaviate (tramite i moduli CLIP/ImageBind) chiudono questo anello.

# Marqo: POST raw images, query with text — no external embedding step
mq.index("products").add_documents(
[{"id": "shoe-001", "image": "https://cdn.example.com/shoes/001.jpg"}],
tensor_fields=["image"]
)
results = mq.index("products").search(q="lightweight shoes for summer")
# Returns shoe-001 despite zero keyword overlap — CLIP handles the cross-modal match

L’indice basato su disco è una leva per i costi. Gli indici HNSW residenti in RAM possono richiedere diversi GB di RAM per ogni milione di vettori a 1536 dimensioni, una volta conteggiati i vettori grezzi, l’overhead del grafo e i metadati. Le alternative native su disco (Milvus DiskANN, Elasticsearch DiskBBQ, il formato Lance di LanceDB, il livello di object storage di Turbopuffer) spesso scambiano una parte della latenza di query con costi infrastrutturali inferiori. Per i workload RAG, in cui la latenza del modello domina già il tempo totale, questo compromesso merita spesso un benchmark.

Il numero massimo di dimensioni nasconde una migrazione nella tua architettura. text-embedding-3-large usa 3072 dimensioni, Jina v3 può produrre embedding più grandi e i modelli di ricerca continuano a spingere verso valori superiori. Alcuni servizi gestiti pubblicano limiti rigidi sulle dimensioni; altri documentano limiti elevati o nessun limite pratico per i modelli di embedding più comuni. Controlla la documentazione aggiornata prima di impegnarti. Scegli qualcosa che lasci margine: migrare un indice vettoriale perché hai raggiunto il limite dimensionale è uno sprint doloroso.

Compromessi operativi che la tabella non mostra

Il multi-tenancy di Turbopuffer è progettato attorno a un numero molto elevato di namespace. Il suo posizionamento pubblico e le storie dei clienti mettono in evidenza workload come il corpus ampio e ricco di namespace di Notion. Se ogni utente o organizzazione ha bisogno di una ricerca vettoriale isolata, quell’architettura può cambiare l’economia del sistema, ma devi comunque fare benchmark sulla forma reale dei tuoi tenant.

La modalità embedded di LanceDB è la cosa più vicina a “SQLite per la ricerca vettoriale”. Viene eseguita in-process, non richiede un server e funziona in Lambda, Cloudflare Workers e negli ambienti edge. Il formato colonnare Lance rende praticabile l’esecuzione embedded anche a una scala reale.

Chroma dà il meglio di sé nello sviluppo, nei test e nei deployment di piccole applicazioni. Se punti a corpus molto grandi, alta disponibilità, un funzionamento fortemente basato su disco o una ricerca ibrida di primo livello, valuta un motore orientato alla produzione prima di trasformare il prototipo in infrastruttura.

Vespa è la scelta giusta quando il retrieval è solo metà del prodotto. Combina retrieval lessicale, ricerca dei vicini più prossimi, tensori, espressioni di ranking, raggruppamento e serving online. Questa potenza è reale, ma lo sono anche la complessità operativa e quella della modellazione. È più adatto ai team che si occupano di ricerca e recommendation che a chi vuole semplicemente “aggiungere la ricerca semantica alla propria app CRUD”.

ClickHouse entra in gioco quando la ricerca è legata all’analisi. Se la tua source of truth è costituita da eventi, log, trace o metriche, ClickHouse riunisce distanza vettoriale, filtri, aggregazioni e indicizzazione full-text seria in un unico motore SQL. Non è un database vettoriale specializzato, ma spesso è la risposta banalmente corretta per il retrieval analitico.

I vettori sparsi sono il modo per ottenere un keyword matching di qualità BM25 all’interno di un indice vettoriale, senza gestire un motore full-text separato. Qdrant ed Elasticsearch offrono implementazioni particolarmente mature in questo ambito. Se la ricerca ibrida è fondamentale e un’architettura a due sistemi è fuori discussione, il supporto ai vettori sparsi è ciò che devi cercare.

Scegliere un motore in base al workload


Non fare l’embedding degli ID aspettandoti match esatti

Non usare la ricerca vettoriale come ricerca testuale fuzzy per dati che hanno una risposta corretta.

“Trova l’utente con l’email dan@example.com” non è un problema di ricerca vettoriale. Neppure “Trova l’ordine con ID ORD-12345”. Fare l’embedding di ORD-12345 e cercare per similarità coseno restituirà qualcosa, ma potrebbe essere sbagliato. Un identificatore ha una risposta corretta. Un match approssimato su un identificatore è un bug.

La ricerca vettoriale restituisce l’elemento più simile nel dataset, anche quando nulla è davvero pertinente. Non sa riconoscere quando non esiste una buona risposta. Per i documenti correlati va bene. È un problema serio per il lookup esatto dei record, dove una risposta sbagliata ma sicura di sé è peggiore di un risultato vuoto.

Lo stesso vale nella direzione opposta: non usare FTS per query in cui l’utente sta descrivendo un concetto. “Articoli su come prendere decisioni difficili in condizioni di incertezza” non contiene keyword affidabili. FTS restituirà rumore oppure nulla. Usa lo strumento adatto alla forma della query.


Costruisci la ricerca attorno alla forma della query

La maggior parte dei sistemi di ricerca in produzione richiede più di un livello:

Non sono strumenti concorrenti. Sono complementari. Un sistema di ricerca ben progettato sceglie il livello giusto per ogni forma di query e, quando le forme si sovrappongono, esegue più livelli e fonde i risultati.

I team che rilasciano buone funzionalità di ricerca comprendono l’intero stack. Gli altri scelgono un database vettoriale, fanno l’embedding di tutto e poi si chiedono perché i lookup esatti restituiscano a volte il record sbagliato.