Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Embeddings i cerca vectorial

Els embeddings i la cerca vectorial són una de les bases dels sistemes de recomanació moderns, el RAG i la cerca semàntica. La idea central és simple: convertir objectes en vectors perquè sigui possible comparar-los per significat i no només per paraules exactes.

Què és un embedding

Un embedding és un vector de nombres reals de dimensió fixa que representa un objecte, com ara un text, un usuari, un producte o una imatge. La propietat important és que objectes semànticament semblants queden propers en l’espai vectorial.

Representació dispersa vs. densa

La manera tradicional de representar text era amb vectors dispersos (sparse): un vector de tants components com paraules existeixin al vocabulari, on gairebé tots els valors són zero. Aquesta representació és fàcil d’entendre, però no captura bé la similitud de significat.

Exemple: si el vocabulari té 50.000 paraules, la paraula “gat” seria:

\[ v_{\text{gat}} = [0, 0, \ldots, 0, 1, 0, \ldots, 0] \quad (\text{50.000 components, un sol 1}) \]

Problemes d’aquesta representació:

  • No captura cap relació entre paraules (“gat” i “felí” queden igual de lluny que “gat” i “cotxe”).
  • Ocupa molt d’espai, i els càlculs de similitud sobre milions de vectors dispersos son lents.

Un embedding dens representa la mateixa paraula amb un vector de dimensió molt menor (típicament 256–4.096 components) on tots els valors són significatius. A diferència del vector dispers, aquí la posició del vector reflecteix millor el significat:

\[ v_{\text{gat}} = [0.23, -0.81, 0.45, \ldots, 0.12] \quad (\text{768 components}) \]

La propietat clau és que la geometria del vector captura semàntica. Vectors propers corresponen a objectes amb significat similar.

Intuïció geomètrica

graph LR
    subgraph "Espai d'embeddings (2D simplificat)"
        GAT["gat 🐱"]
        GOS["gos 🐶"]
        FELI["felí 🐈"]
        COTXE["cotxe 🚗"]
        MOTO["moto 🏍️"]
    end
    GAT ---|"proper"| FELI
    GAT ---|"proper"| GOS
    COTXE ---|"proper"| MOTO

“Gat”, “gos” i “felí” seran propers entre ells. “Cotxe” i “moto” seran propers entre ells però lluny dels animals. Aquesta estructura emergeix automàticament de l’entrenament, així que no cal definir-la a mà.

Com s’aprenen els embeddings

Un model d’embeddings s’entrena per optimitzar una funció de pèrdua. La intuïció és que el model ha d’aprendre a posar junts els exemples semblants i a separar els exemples diferents.

Pèrdua contrastiva

La pèrdua contrastiva treballa amb triplets (anchor, positiu, negatiu): donada una mostra de referència, un exemple similar i un de diferent, l’objectiu és que el positiu quedi més a prop de l’anchor que el negatiu:

\[ \mathcal{L} = \max(0,; d(a, p) - d(a, n) + \text{marge}) \]

On \(d\) és una mètrica de distància, \(a\) és l’anchor, \(p\) el positiu i \(n\) el negatiu. La pèrdua és zero quan el positiu és prou més proper que el negatiu; augmenta quan no ho és.

Com es construeixen els parells positius? Depèn del domini:

DominiParells positiusParells negatius
TextDues frases del mateix documentFrases de documents no relacionats
Recomanació(usuari, ítem que ha consumit)(usuari, ítem que no ha vist)
Cerca(consulta, document rellevant)(consulta, document irrellevant)

Els negatius es solen obtenir per mostreig aleatori del conjunt de dades (in-batch negatives): els altres exemples del mateix batch d’entrenament actuen com a negatius implícits.

Softmax sobre catàleg (skip-gram)

El model word2vec (skip-gram) va popularitzar un objectiu diferent: donada una paraula central, predir les paraules del context. Aquesta idea mostra una altra manera d’aprendre embeddings i és equivalent a maximitzar un softmax sobre tot el catàleg:

\[ P(\text{context} \mid \text{paraula}) = \frac{e^{v_{\text{context}} \cdot v_{\text{paraula}}}}{\sum_{w} e^{v_w \cdot v_{\text{paraula}}}} \]

La matriu de pesos apreses durant l’entrenament són els embeddings. El mateix principi s’aplica als sistemes de recomanació: substituint “paraules” per “ítems” i “context” per “ítems co-consumits”.

LLMs com a productors d’embeddings

Els models d’embeddings moderns, com BERT, sentence-transformers o text-embedding-3, produeixen vectors densos útils per a recuperació semàntica. En alguns encoders, el vector del token especial [CLS] o la mitjana dels tokens de sortida es pot usar directament com a representació del text. Aquests models solen obtenir bones puntuacions en benchmarks de recuperació semàntica com MTEB.

Mètriques de similitud

Un cop tenim dos vectors \(u\) i \(v\), cal mesurar com de similars són. Hi ha tres opcions principals i cadascuna és útil en un context diferent:

Similitud del cosinus

\[ \cos(u, v) = \frac{u \cdot v}{|u| \cdot |v|} \]

Mesura l’angle entre els dos vectors, independentment de la seva magnitud. Val 1 si apunten en la mateixa direcció, 0 si són perpendiculars i -1 si apunten en direccions oposades. És la mètrica més habitual en cerca semàntica de text.

Quan usar-la: cerca semàntica de text, quan la magnitud del vector no té significat (l’important és la direcció).

Producte escalar (dot product)

\[ u \cdot v = \sum_i u_i v_i \]

Combina angle i magnitud. Vectors llargs (alta norma) obtenen puntuacions més altes fins i tot si l’angle no és millor. Això introdueix un biaix de popularitat: ítems representats amb vectors de gran norma tendeixen a aparèixer més.

Quan usar-lo: sistemes de recomanació, on la magnitud pot capturar la popularitat o rellevància global d’un ítem.

Distància L2 (euclidiana)

\[ d(u, v) = |u - v| = \sqrt{\sum_i (u_i - v_i)^2} \]

La distància espacial directa entre dos punts.

Quan usar-la: atributs d’imatge, quan l’espai vectorial és calibrat i la distància absoluta té significat.

El truc de la normalització

Si normalitzem tots els vectors a norma unitària (\(|v| = 1\)), la similitud del cosinus i el producte escalar produeixen el mateix resultat:

\[ \cos(u, v) = u \cdot v \quad \text{si } |u| = |v| = 1 \]

Normalitzar prèviament permet usar el producte escalar (molt eficient en GPU) en lloc de calcular cosinus explícitament. En molts sistemes, els vectors d’embedding es normalitzen abans d’indexar-los o consultar-los.

Cerca aproximada de veïns (ANN)

La cerca de veïns més propers consisteix a trobar, per a un vector de consulta, els vectors del catàleg que queden més a prop segons una mètrica de similitud o distància, com ara el producte escalar, la similitud del cosinus o la distància L2. És el mecanisme que permet recuperar els resultats més rellevants a partir d’un embedding de consulta.

El problema computacional

Amb un catàleg d’1 milió de vectors de dimensió 768, trobar els 10 més similars a una consulta requereix calcular 1 milió de productes escalars. En un servei que rep milers de consultes per segon, el cost és prohibitiu.

La cerca exacta de veïns compara la consulta amb tots els vectors del catàleg i no escala a gran volum. La solució pràctica és acceptar una petita pèrdua de precisió a canvi d’una reducció dràstica de latència: la cerca aproximada de veïns (ANN).

HNSW (Hierarchical Navigable Small World)

HNSW és una manera de fer cerca aproximada recorrent un graf multicapa en lloc de revisar tots els vectors. La idea és navegar ràpidament per nodes “bons candidats” i després refinar la resposta.

HNSW construeix un graf multicapa on els vectors s’interconnecten per proximitat. Les capes superiors contenen pocs nodes i connexions llargues (navegació ràpida); les capes inferiors contenen tots els nodes i connexions curtes (refinament precís).

graph TD
    subgraph "Capa 2 (navegació global)"
        A2["A"] --- C2["C"]
        C2 --- F2["F"]
    end
    subgraph "Capa 1"
        A1["A"] --- B1["B"]
        B1 --- C1["C"]
        C1 --- E1["E"]
        E1 --- F1["F"]
    end
    subgraph "Capa 0 (tots els nodes)"
        A0["A"] --- B0["B"]
        B0 --- C0["C"]
        C0 --- D0["D"]
        D0 --- E0["E"]
        E0 --- F0["F"]
    end

Cerca: entrar per la capa superior, navegar cap al node més proper a la consulta, baixar a la capa inferior i refinar. El cost és aproximadament \(O(\log n)\) en lloc de \(O(n)\).

Avantatges: recall molt alt, latència molt baixa. Inconvenient: memòria elevada (el graf ocupa el doble que els vectors).

IVF (Inverted File Index)

IVF és una altra manera d’aproximar la cerca: en lloc de mirar tots els vectors, agrupa l’espai en clústers i només explora els grups més prometedors.

IVF divideix l’espai en \(k\) clústers (via k-means). Cada vector s’assigna al seu centroide. En el moment de la cerca, només s’exploren els \(n_{\text{probe}}\) clústers més propers a la consulta.

Avantatge: molt menor consum de memòria que HNSW. Inconvenient: si el vector de consulta queda a la frontera entre dos clústers, els veritables veïns poden estar en un clúster no explorat (recall menor).

Quantització de producte (PQ)

PQ no canvia tant la forma de buscar com la manera d’emmagatzemar els vectors: comprimeix cada vector perquè ocupi molt menys memòria, a costa de perdre una mica de precisió.

PQ comprimeix cada vector dividint-lo en \(m\) subvectors i aproximant cadascun amb el centroide del seu clúster. Un vector de 768 dimensions pot quedar comprimit a pocs bytes.

Avantatge: reducció dramàtica de memòria (10–50x). Inconvenient: pèrdua de qualitat del recall.

En la pràctica, IVF i PQ es combinen (IVFPQ): IVF redueix el nombre de candidats i PQ redueix la memòria dels vectors emmagatzemats.

Comparativa i eines

AlgorismeRecallLatènciaMemòriaCas d’ús típic
HNSWAltMolt baixaAltaServeis en temps real, < 50M vectors
IVFMitjà-AltBaixaMitjanaCatàlegs grans, menys RAM
IVFPQMitjàBaixaBaixaCentenars de milions de vectors

FAISS (Meta): biblioteca de referència per a CPU i GPU. Implementa HNSW, IVF, PQ i combinacions. És baix nivell i molt configurable, així que és útil quan vols controlar bé el comportament de l’índex.

ScaNN (Google): biblioteca optimitzada per a cerca aproximada amb molt bon rendiment en recuperació. És una alternativa útil quan vols prioritzar eficiència i recall.

hnswlib: implementació lleugera de HNSW, adequada per a prototips o serveis amb pocs milions de vectors.

Cerca semàntica

La cerca semàntica és el procés de recuperar resultats rellevants segons el significat de la consulta, no només segons les paraules exactes. En la pràctica, combina embeddings, ANN i sovint algun tipus de reordenació final per donar bons resultats a l’usuari.

Per exemple, si un usuari escriu “m’han cobrat dues vegades però només he fet una comanda”, la cerca semàntica hauria de trobar documents sobre transaccions duplicades, encara que no comparteixin vocabulari literal.

Pipeline típic

Un flux de cerca semàntica normalment té aquestes etapes:

  1. Ingesta: es recullen documents, fragments, productes o entrades de coneixement.
  2. Chunking: els documents llargs es divideixen en fragments més petits per no perdre significat.
  3. Embedding: cada fragment es transforma en un vector.
  4. Indexació: els vectors s’emmagatzemen en un índex ANN o en un vector store.
  5. Consulta: la pregunta de l’usuari també es transforma en un embedding.
  6. Recuperació: es busquen els vectors més propers a la consulta.
  7. Reranking: un segon model o una heurística reordena els candidats més rellevants.

Chunking de documents

El chunking consisteix a dividir documents llargs en fragments prou petits perquè cada embedding representi una idea coherent. És una decisió clau perquè un fragment massa gran barreja massa context i un fragment massa petit perd informació.

Un criteri pràctic és fer coincidir els chunks amb l’estructura natural del document:

  • Markdown: un chunk per secció o subsecció, i si una secció és massa llarga, dividir-la per paràgrafs.
  • HTML o articles: dividir per títols i paràgrafs abans que per longitud fixa.
  • PDFs o textos sense estructura: dividir per paràgrafs i, si cal, aplicar solapament petit entre chunks consecutius.

Per exemple, en un document Markdown:

# Guia de suport

## Facturació
Paràgraf 1...
Paràgraf 2...

## Enviaments
Paràgraf 3...
Paràgraf 4...

Una partició raonable seria:

  • chunk 1: ## Facturació + els seus paràgrafs
  • chunk 2: ## Enviaments + els seus paràgrafs

Si una secció és massa llarga, es pot dividir en chunks més petits mantenint el títol o una mica de context al principi de cada fragment.

Per què no n’hi ha prou amb ANN

ANN és la part que fa la recuperació ràpida, però una bona cerca semàntica normalment no s’atura aquí. Hi ha tres motius principals:

  • Keywords exactes: algunes consultes contenen codis, noms propis o termes molt específics que un sistema semàntic pot diluir.
  • Ambigüitat: un únic embedding de consulta pot recuperar resultats massa generals si no hi ha reranking.
  • Context de negoci: a vegades cal prioritzar resultats recents, del mateix idioma o del mateix producte.

Per això molts sistemes combinen cerca lèxica i cerca semàntica.

Cerca híbrida

La cerca híbrida barreja dues senyals:

  • BM25 o keyword search per a coincidències exactes.
  • Embeddings per a coincidències per significat.

Això és especialment útil quan la consulta pot ser de dos tipus alhora: part exacta i part semàntica. Per exemple, error 4012 necessita coincidència lèxica, mentre que “l’app es tanca quan pago” necessita coincidència semàntica.

Reranking

El reranking pren un conjunt petit de candidats recuperats per ANN i els reordena amb un criteri més car però més precís. Això permet:

  • recuperar ràpidament centenars o milers de candidats
  • aplicar després un model més precís sobre només els top k

En molts sistemes, aquest pas marca més diferència en la qualitat final que no pas triar un embedding una mica millor.

Com s’avalua

Una cerca semàntica no s’ha d’avaluar només per sensació. Algunes mètriques útils són:

  • Recall@k: quin percentatge de respostes rellevants apareixen entre els k primers.
  • Precision@k: quants dels k primers són realment rellevants.
  • MRR: com de dalt apareix el primer resultat correcte.
  • Avaluació humana: revisió manual sobre consultes reals.

Cal distingir dues coses: el score de recuperació és la puntuació que rep cada resultat quan el sistema el compara amb la consulta, mentre que una mètrica d’avaluació resumeix si el sistema funciona bé en un conjunt de consultes de prova. El score serveix per ordenar resultats; la mètrica serveix per mesurar la qualitat global.

La conclusió pràctica és que la qualitat no depèn només de l’embedding. També depèn del chunking, de l’índex, del reranking, dels filtres i de com es mesura el resultat.

Connexions

Aquest document cobreix els fonaments (representació densa, mètriques de similitud, cerca ANN i el concepte de cerca semàntica). La part operativa i altres aplicacions es tracten en altres materials:

  • Prompts i integració — porta aquests fonaments a la pràctica dins de pipelines RAG: selecció de models d’embeddings, estratègies de chunking, cerca híbrida i, sobretot, els vector stores (Chroma, Qdrant, Weaviate), que afegeixen persistència, filtratge per metadades i multitenancy sobre l’índex ANN. Com a regla pràctica, per a catàlegs petits (menys de ~10.000 vectors) la cerca exacta en memòria ja és suficient i un vector store només compensa a partir d’aquest volum.
  • Sistemes de recomanació — l’arquitectura two-tower usa embeddings apresos per a usuaris i ítems; la fase de retrieval s’implementa amb ANN sobre els vectors d’ítems precomputats.
Last change: , commit: e0566f7