andreapellizzari.it
Indice diario
468 parole · 2 min

Il coseno manca i codici esatti: retrieval ibrido su cataloghi PDF

Un agente di vendita cerca dentro i cataloghi PDF dei produttori per similarità semantica. Ma su contenuto pieno di codici e misure, il coseno sbaglia proprio sui termini esatti. La cura: una gamba lessicale fusa con RRF.

#ai#rag#python#claude

Sto costruendo un agente di vendita virtuale per un catalogo multi-marca di cucine ed elettrodomestici: il modello ragiona, e una serie di strumenti gli danno accesso ai dati. Uno di questi strumenti cerca dentro i cataloghi PDF dei produttori, migliaia di pagine indicizzate come testo. Funzionava per similarità semantica pura: la query e ogni pagina diventano vettori (embedding BGE-M3), e si recuperano le pagine più vicine.

Il problema l'ho visto solo guardando i casi giusti. La similarità semantica è ottima per i concetti ("schemi di montaggio", "manutenzione filtri"), ma sui codici articolo e le misure sbaglia dove dovrebbe essere più precisa. Un codice come RT.4150 per il coseno è quasi rumore: non c'è semantica in una sigla. E in un catalogo tecnico, spesso il codice esatto è la ricerca.

La cura non era esotica. Lo stesso sistema aveva già, su un altro strato, un retrieval ibrido collaudato: una gamba lessicale (BM25 su indice FTS5, che pesa la corrispondenza letterale dei termini) accanto a quella vettoriale, e le due liste fuse con Reciprocal Rank Fusion (un metodo che combina i due ordinamenti premiando chi sta in alto in entrambi). Uno strumento solo era rimasto indietro. Ho copiato il pattern già maturo invece di inventarne uno nuovo.

rendering diagramma…

La parte che mi ha insegnato qualcosa è la verifica. Misurare la precisione aggregata avrebbe mentito: la media sarebbe sembrata buona, nascondendo che le query per codice esatto fallivano del tutto. Ho segmentato i test in tre categorie (codice esatto, misura o sigla, concetto) e confrontato la versione vettoriale pura con l'ibrido. Sui codici esatti il risultato è netto:

Query per codice esattoCoseno puroIbrido
sigla puntata (RT.4150)fuori dai primi 53ª posizione
codice EAN a 13 cifrefuori dai primi 52ª posizione
seconda sigla puntatafuori dai primi 53ª posizione

Tre casi su tre in cui prima la pagina corretta non usciva nemmeno tra le prime cinque, e ora esce in cima. Sui concetti: pari, nessuna regressione. È esattamente la diagnosi che la metrica aggregata avrebbe sepolto.

Un dettaglio di igiene operativa che rifarei sempre: l'indice lessicale è un file separato, derivato, rigenerabile in meno di un decimo di secondo. Non lo verso nel repository e non lo "migro": un controllo all'avvio del server confronta numero di righe e timestamp dell'ultima ingestione, e se qualcosa è cambiato lo ricostruisce da solo. Se per qualsiasi motivo manca, lo strumento torna al comportamento vecchio (solo vettoriale) invece di rompersi. In produzione il primo avvio l'ha rigenerato in mezzo secondo, e una query reale ha confermato la fusione attiva.

L'ibrido non è una novità. La disciplina di non fidarsi della media, e di trattare gli artefatti derivati come usa-e-getta, quella sì che paga.