Panoramica di Decay RankerCompatible with Milvus 2.6.x

Nella ricerca vettoriale tradizionale, i risultati sono classificati esclusivamente in base alla somiglianza vettoriale, ovvero alla vicinanza dei vettori nello spazio matematico. Ma nelle applicazioni reali, ciò che rende un contenuto veramente rilevante spesso dipende da qualcosa di più della semplice somiglianza semantica.

Considerate questi scenari quotidiani:

  • Una ricerca di notizie in cui l'articolo di ieri dovrebbe essere più importante di un articolo simile di tre anni fa.

  • Una ricerca di ristoranti che dà priorità ai locali a 5 minuti di distanza rispetto a quelli che richiedono 30 minuti di auto

  • Una piattaforma di e-commerce che dà priorità ai prodotti di tendenza anche quando sono leggermente meno simili alla query di ricerca.

Questi scenari hanno tutti un'esigenza comune: bilanciare la somiglianza vettoriale con altri fattori numerici come il tempo, la distanza o la popolarità.

I classificatori di decadimento di Milvus rispondono a questa esigenza regolando le classifiche di ricerca in base ai valori dei campi numerici. Permettono di bilanciare la somiglianza vettoriale con la "freschezza", la "vicinanza" o altre proprietà numeriche dei dati, creando esperienze di ricerca più intuitive e contestualmente rilevanti.

Note sull'uso

  • Il ranking di decadimento non può essere utilizzato con le ricerche di raggruppamento.

  • Il campo utilizzato per il ranking di decadimento deve essere numerico (INT8, INT16, INT32, INT64, FLOAT, o DOUBLE).

  • Ogni classificatore di decadimento può utilizzare un solo campo numerico.

  • Coerenza dell'unità di tempo: Quando si utilizza una classifica di decadimento basata sul tempo, le unità di misura dei parametri origin, scale e offset devono corrispondere alle unità di misura utilizzate nei dati della raccolta:

    • Se la raccolta memorizza i timestamp in secondi, utilizzare i secondi per tutti i parametri.

    • Se la raccolta memorizza timestamp in millisecondi, utilizzare millisecondi per tutti i parametri.

    • Se la raccolta memorizza timestamp in microsecondi, utilizzare microsecondi per tutti i parametri.

Come funziona

Il Decay Ranking migliora la ricerca vettoriale tradizionale incorporando fattori numerici come il tempo o la distanza geografica nel processo di classificazione. L'intero processo segue queste fasi:

Fase 1: Calcolo dei punteggi di somiglianza normalizzati

Per prima cosa, Milvus calcola e normalizza i punteggi di somiglianza dei vettori per garantire un confronto coerente:

  • Per le metriche di distanza L2 e JACCARD (dove i valori più bassi indicano una maggiore somiglianza):

    normalized_score = 1.0 - (2 × arctan(score))/π
    

    Trasforma le distanze in punteggi di somiglianza compresi tra 0 e 1, dove il valore più alto è migliore.

  • Per le metriche IP, COSINE e BM25 (dove punteggi più alti indicano già corrispondenze migliori): I punteggi vengono utilizzati direttamente senza normalizzazione.

Fase 2: Calcolo dei punteggi di decadimento

Successivamente, Milvus calcola un punteggio di decadimento basato sul valore del campo numerico (come il timestamp o la distanza) utilizzando il ranker di decadimento selezionato:

  • Ogni classificatore di decadimento trasforma i valori numerici grezzi in punteggi di rilevanza normalizzati compresi tra 0-1.

  • Il punteggio di decadimento rappresenta la rilevanza di un elemento in base alla sua "distanza" dal punto ideale.

La formula di calcolo specifica varia a seconda del tipo di decay ranker. Per i dettagli su come calcolare un punteggio di decadimento, consultare le pagine dedicate a Decadimento gaussiano, Decadimento esponenziale e Decadimento lineare.

Fase 3: calcolo dei punteggi finali

Infine, Milvus combina il punteggio di similarità normalizzato e il punteggio di decadimento per produrre il punteggio finale della classifica:

final_score = normalized_similarity_score × decay_score

Nei casi di ricerca ibrida (che combina più campi vettoriali), Milvus prende il massimo punteggio di similarità normalizzato tra le richieste di ricerca:

final_score = max([normalized_score₁, normalized_score₂, ..., normalized_scoreₙ]) × decay_score

Ad esempio, se un documento di ricerca ottiene un punteggio di 0,82 dalla similarità vettoriale e di 0,91 dal recupero del testo basato su BM25 in una ricerca ibrida, Milvus utilizza 0,91 come punteggio di similarità di base prima di applicare il fattore di decadimento.

Il ranking di decadimento in azione

Vediamo il decay ranking in uno scenario pratico: la ricerca di "articoli di ricerca sull'intelligenza artificiale" con decadimento basato sul tempo:

In questo esempio, i punteggi di decadimento riflettono il modo in cui la rilevanza diminuisce con il tempo: i documenti più recenti ricevono punteggi più vicini a 1,0, quelli più vecchi ricevono punteggi più bassi. Questi valori sono calcolati utilizzando un classificatore di decadimento specifico. Per maggiori dettagli, consultare la sezione Scegliere il giusto classificatore di decadimento.

Carta

Similitudine vettoriale

Punteggio di somiglianza normalizzato

Data di pubblicazione

Punteggio di decadimento

Punteggio finale

Classifica finale

Carta A

Alto

0,85 (COSINE)

2 settimane fa

0.80

0.68

2

Carta B

Molto alto

0,92 (COSINE)

6 mesi fa

0.45

0.41

3

Carta C

Media

0,75 (COSINE)

1 giorno fa

0.98

0.74

1

Carta D

Medio-alto

0,76 (COSINE)

3 settimane fa

0.70

0.53

4

Senza il reranking del decadimento, il documento B si classificherebbe al primo posto in base alla pura somiglianza vettoriale (0,92). Tuttavia, con il decay reranking applicato:

  • Il documento C balza in prima posizione nonostante la media somiglianza perché è molto recente (pubblicato ieri).

  • Il documento B scende alla posizione numero 3, nonostante l'eccellente somiglianza, perché è relativamente vecchio.

  • Il documento D utilizza la distanza L2 (dove minore è migliore), quindi il suo punteggio viene normalizzato da 1,2 a 0,76 prima di applicare il decadimento.

Scegliere il giusto classificatore di decadimento

Milvus offre diversi classificatori di decadimento - gauss, exp, linear, ciascuno progettato per casi d'uso specifici:

Classificatore di decadimento

Caratteristiche

Casi d'uso ideali

Scenario di esempio

Gaussiano (gauss)

Declino graduale dal sapore naturale che si estende moderatamente

  • Ricerche generali che richiedono risultati equilibrati

  • Applicazioni in cui gli utenti hanno un senso intuitivo della distanza

  • Quando la distanza moderata non dovrebbe penalizzare gravemente i risultati

In una ricerca di ristoranti, i locali di qualità a 3 km di distanza rimangono scoperti, anche se classificati più in basso rispetto alle opzioni vicine

Esponenziale (exp)

All'inizio diminuisce rapidamente, ma mantiene una coda lunga

  • News feed, dove la ricorrenza è fondamentale

  • Social media dove i contenuti freschi dovrebbero dominare

  • Quando la prossimità è fortemente preferita, ma gli articoli eccezionalmente distanti dovrebbero rimanere visibili

In un'app di notizie, le storie di ieri si posizionano molto più in alto rispetto ai contenuti di una settimana fa, ma gli articoli più vecchi altamente rilevanti possono ancora apparire

Lineare (linear)

Declino coerente e prevedibile, con un limite ben definito

  • Applicazioni con confini naturali

  • Servizi con limiti di distanza

  • Contenuti con date di scadenza o soglie chiare

In un cercatore di eventi, gli eventi oltre una finestra futura di due settimane non appaiono affatto.

Per informazioni dettagliate su come ciascun decay ranker calcola i punteggi e i modelli di declino specifici, consultare la documentazione dedicata:

Esempio di implementazione

I ranker di decadimento possono essere applicati sia alla ricerca vettoriale standard che alle operazioni di ricerca ibrida in Milvus. Di seguito sono riportati i principali frammenti di codice per l'implementazione di questa funzione.

Prima di utilizzare le funzioni di decadimento, è necessario creare una collezione con campi numerici appropriati (come timestamp, distanze, ecc.) che verranno utilizzati per i calcoli di decadimento. Per gli esempi di lavoro completi, che includono l'impostazione della raccolta, la definizione dello schema e l'inserimento dei dati, consultare l'esercitazione: Implementare una classifica basata sul tempo in Milvus.

Creare un classificatore di decadimento

Per implementare il ranking di decadimento, occorre innanzitutto definire un oggetto Function con la configurazione appropriata:

from pymilvus import Function, FunctionType

# Create a decay function for timestamp-based decay
# Note: All time parameters must use the same unit as your collection data
decay_ranker = Function(
    name="time_decay",                  # Function identifier
    input_field_names=["timestamp"],    # Numeric field to use for decay
    function_type=FunctionType.RERANK,  # Must be set to RERANK for decay rankers
    params={
        "reranker": "decay",            # Specify decay reranker. Must be "decay"
        "function": "gauss",            # Choose decay function type: "gauss", "exp", or "linear"
        "origin": int(datetime.datetime(2025, 1, 15).timestamp()),    # Reference point (seconds)
        "scale": 7 * 24 * 60 * 60,      # 7 days in seconds (must match collection data unit)
        "offset": 24 * 60 * 60,         # 1 day no-decay zone (must match collection data unit)
        "decay": 0.5                    # Half score at scale distance
    }
)
import io.milvus.v2.service.vector.request.ranker.DecayRanker;

import java.time.ZoneId;
import java.time.ZonedDateTime;

ZonedDateTime zdt = ZonedDateTime.of(2025, 1, 25, 0, 0, 0, 0, ZoneId.systemDefault());

DecayRanker ranker = DecayRanker.builder()
        .name("time_decay")
        .inputFieldNames(Collections.singletonList("timestamp"))
        .function("gauss")
        .origin(zdt.toInstant().toEpochMilli())
        .scale(7 * 24 * 60 * 60)
        .offset(24 * 60 * 60)
        .decay(0.5)
        .build();


import {FunctionType } from "@zilliz/milvus2-sdk-node";

const decayRanker = {
  name: "time_decay",
  input_field_names: ["timestamp"],
  function_type: FunctionType.RERANK,
  params: {
    reranker: "decay",
    function: "gauss",
    origin: new Date(2025, 1, 15).getTime(),
    scale: 7 * 24 * 60 * 60,
    offset: 24 * 60 * 60,
    decay: 0.5,
  },
};

// go
# restful

Parametro

Richiesto?

Descrizione

Valore/Esempio

name

Identificatore della funzione utilizzata durante l'esecuzione delle ricerche. Scegliere un nome descrittivo e pertinente al caso d'uso.

"time_decay"

input_field_names

Campo numerico per il calcolo del punteggio di decadimento. Determina quale attributo dei dati sarà usato per calcolare il decadimento (ad esempio, timestamp per il decadimento basato sul tempo, coordinate per il decadimento basato sulla posizione).

Deve essere un campo della collezione che contiene valori numerici rilevanti. Supporta INT8/16/32/64, FLOAT, DOUBLE.

["timestamp"]

function_type

Specifica il tipo di funzione creata.

Deve essere impostato su RERANK per tutti i classificatori di decadimento.

FunctionType.RERANK

params.reranker

Specifica il metodo di reranking da utilizzare.

Deve essere impostato su "decay" per abilitare la funzionalità di ranking di decadimento.

"decay"

params.function

Specifica quale ranker matematico di decadimento applicare. Determina la forma della curva del declino della rilevanza.

Vedere la sezione Scegliere il ranker di decadimento giusto per una guida alla selezione della funzione appropriata.

"gauss" "exp", o "linear"

params.origin

Punto di riferimento dal quale viene calcolato il punteggio di decadimento. Gli elementi a questo valore ricevono il massimo punteggio di rilevanza.

Per il decadimento basato sul tempo, l'unità di tempo deve corrispondere ai dati della raccolta.

  • Per i timestamp: l'ora corrente (ad esempio, int(time.time())).

  • Per la geolocalizzazione: le coordinate attuali dell'utente.

params.scale

Distanza o tempo in cui la rilevanza scende al valore decay. Controlla la velocità con cui la rilevanza diminuisce.

Per il decadimento basato sul tempo, l'unità di tempo deve corrispondere ai dati di raccolta.

Valori più grandi creano un declino più graduale della rilevanza; valori più piccoli creano un declino più ripido.

  • Per il tempo: periodo in secondi (ad esempio, 7 * 24 * 60 * 60 per 7 giorni).

  • Per la distanza: metri (ad esempio, 5000 per 5 km).

params.offset

No

Crea una "zona di non decadimento" intorno a origin dove gli elementi mantengono il punteggio pieno (punteggio di decadimento = 1,0).

Per il decadimento basato sul tempo, l'unità di tempo deve corrispondere ai dati di raccolta.

Gli elementi all'interno di questo intervallo di origin mantengono la massima rilevanza.

  • Per il tempo: periodo in secondi (ad esempio, 24 * 60 * 60 per 1 giorno).

  • Per la distanza: metri (ad esempio, 500 per 500 m).

params.decay

No

Valore del punteggio alla distanza scale, controlla la ripidità della curva. Valori più bassi creano curve di declino più ripide; valori più alti creano curve di declino più graduali.

Deve essere compreso tra 0 e 1.

0.5 (valore predefinito)

Dopo aver definito il ranker di decadimento, è possibile applicarlo durante le operazioni di ricerca passandolo al parametro ranker:

# Use the decay function in standard vector search
results = milvus_client.search(
    collection_name,
    data=[your_query_vector], # Replace with your query vector
    anns_field="vector_field",
    limit=10,
    output_fields=["document", "timestamp"],  # Include the decay field in outputs to see values
    ranker=decay_ranker,                      # Apply the decay ranker here
    consistency_level="Strong"
)
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
import io.milvus.v2.service.vector.request.data.EmbeddedText;

SearchReq searchReq = SearchReq.builder()
        .collectionName(COLLECTION_NAME)
        .data(Collections.singletonList(new EmbeddedText("search query")))
        .annsField("vector_field")
        .limit(10)
        .outputFields(Arrays.asList("document", "timestamp"))
        .functionScore(FunctionScore.builder()
                .addFunction(ranker)
                .build())
        .build();
SearchResp searchResp = client.search(searchReq);
const result = await milvusClient.search({
  collection_name: "collection_name",
  data: [your_query_vector], // Replace with your query vector
  anns_field: "dense",
  limit: 10,
  output_fields: ["document", "timestamp"],
  rerank: ranker,
  consistency_level: "Strong",
});
// go
# restful