Aperçu de Decay RankerCompatible with Milvus 2.6.x

Dans la recherche vectorielle traditionnelle, les résultats sont classés uniquement en fonction de la similarité vectorielle, c'est-à-dire de la proximité des vecteurs dans l'espace mathématique. Mais dans les applications du monde réel, la pertinence d'un contenu ne dépend pas uniquement de la similarité sémantique.

Prenons l'exemple de ces scénarios quotidiens :

  • Une recherche d'actualités où l'article d'hier devrait être mieux classé qu'un article similaire datant d'il y a trois ans.

  • Un moteur de recherche de restaurants qui donne la priorité aux établissements situés à 5 minutes de chez vous plutôt qu'à ceux qui nécessitent 30 minutes de route.

  • Une plateforme de commerce électronique qui met en avant les produits en vogue même s'ils sont légèrement moins similaires à la requête de recherche.

Ces scénarios ont tous un besoin commun : équilibrer la similarité vectorielle avec d'autres facteurs numériques tels que le temps, la distance ou la popularité.

Les classeurs de décroissance de Milvus répondent à ce besoin en ajustant les classements de recherche sur la base des valeurs des champs numériques. Ils vous permettent d'équilibrer la similarité vectorielle avec la "fraîcheur", la "proximité" ou d'autres propriétés numériques de vos données, créant ainsi des expériences de recherche plus intuitives et contextuellement pertinentes.

Notes d'utilisation

  • Le classement par décroissance ne peut pas être utilisé avec les recherches par regroupement.

  • Le champ utilisé pour le classement par ordre de décroissance doit être numérique (INT8, INT16, INT32, INT64, FLOAT, ou DOUBLE).

  • Chaque classificateur ne peut utiliser qu'un seul champ numérique.

  • Cohérence des unités de temps: Lorsque vous utilisez un classement par ordre de décroissance basé sur le temps, les unités des paramètres origin, scale et offset doivent correspondre aux unités utilisées dans les données de votre collection :

    • Si votre collection stocke les horodatages en secondes, utilisez les secondes pour tous les paramètres.

    • Si votre collection stocke les horodatages en millisecondes, utilisez les millisecondes pour tous les paramètres.

    • Si votre collection stocke des horodatages en microsecondes, utilisez les microsecondes pour tous les paramètres.

Fonctionnement

Le classement par décroissance améliore la recherche vectorielle traditionnelle en incorporant des facteurs numériques tels que le temps ou la distance géographique dans le processus de classement. L'ensemble du processus suit les étapes suivantes :

Étape 1 : Calcul des scores de similarité normalisés

Tout d'abord, Milvus calcule et normalise les scores de similarité des vecteurs afin de garantir une comparaison cohérente :

  • Pour les mesures de distance L2 et JACCARD (où des valeurs plus faibles indiquent une plus grande similarité) :

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

    Les distances sont transformées en scores de similarité compris entre 0 et 1, la valeur la plus élevée étant la meilleure.

  • Pour les mesures IP, COSINE et BM25 (où des scores plus élevés indiquent déjà de meilleures correspondances) : Les scores sont utilisés directement sans normalisation.

Étape 2 : Calcul des scores de dégradation

Ensuite, Milvus calcule un score de désintégration basé sur la valeur de champ numérique (comme l'horodatage ou la distance) à l'aide du classificateur de désintégration sélectionné :

  • Chaque classificateur de désintégration transforme les valeurs numériques brutes en scores de pertinence normalisés compris entre 0 et 1

  • Le score de décroissance représente le degré de pertinence d'un élément en fonction de sa "distance" par rapport au point idéal.

La formule de calcul spécifique varie en fonction du type de classificateur de décroissance. Pour plus de détails sur le calcul d'un score de décroissance, reportez-vous aux pages consacrées à la décroissance gaussienne, à la décroissance exponentielle et à la décroissance linéaire.

Étape 3 : Calcul des scores finaux

Enfin, Milvus combine le score de similarité normalisé et le score de décroissance pour produire le score de classement final :

final_score = normalized_similarity_score × decay_score

En cas de recherche hybride (combinaison de plusieurs champs vectoriels), Milvus prend le score de similarité normalisé maximal parmi les requêtes de recherche :

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

Par exemple, si un document de recherche obtient un score de 0,82 pour la similarité vectorielle et un score de 0,91 pour la recherche de texte basée sur BM25 dans une recherche hybride, Milvus utilise 0,91 comme score de similarité de base avant d'appliquer le facteur de décroissance.

Le classement par décroissance en action

Voyons le classement par décroissance dans un scénario pratique : la recherche de "documents de recherche sur l'IA" avec une décroissance basée sur le temps :

Dans cet exemple, les scores de décroissance reflètent la manière dont la pertinence diminue avec le temps - les articles plus récents obtiennent des scores plus proches de 1,0, tandis que les articles plus anciens obtiennent des scores plus faibles. Ces valeurs sont calculées à l'aide d'un classificateur de décroissance spécifique. Pour plus d'informations, reportez-vous à la section Choisir le bon classificateur de décroissance.

Article

Similitude vectorielle

Score de similarité normalisé

Date de publication

Score de décroissance

Score final

Rang final

Papier A

Élevé

0,85 (COSINE)

il y a 2 semaines

0.80

0.68

2

Papier B

Très élevé

0,92 (COSINE)

Il y a 6 mois

0.45

0.41

3

Papier C

Moyen

0,75 (COSINE)

1 jour ago

0.98

0.74

1

Papier D

Moyenne-élevée

0.76 (COSINE)

il y a 3 semaines

0.70

0.53

4

Sans le classement par décroissance, le document B serait le mieux classé sur la base de la similarité vectorielle pure (0,92). Cependant, avec l'application du decay reranking :

  • l'article C passe en première position malgré une similarité moyenne parce qu'il est très récent (publié hier)

  • L'article B passe en troisième position malgré une excellente similarité, car il est relativement ancien.

  • L'article D utilise la distance L2 (plus elle est faible, mieux c'est), et son score est donc normalisé de 1,2 à 0,76 avant l'application de la décroissance.

Choisir le bon classificateur de désintégration

Milvus propose différents classeurs de décroissance - gauss, exp, linear, chacun conçu pour des cas d'utilisation spécifiques :

Classeur de désintégration

Caractéristiques

Cas d'utilisation idéaux

Exemple de scénario

Gaussien (gauss)

Déclin progressif et naturel qui s'étend modérément

  • Recherches générales nécessitant des résultats équilibrés

  • Applications où les utilisateurs ont un sens intuitif de la distance

  • Lorsque la distance modérée ne doit pas pénaliser gravement les résultats

Dans une recherche de restaurant, les établissements de qualité situés à 3 km restent accessibles, bien qu'ils soient moins bien classés que les établissements situés à proximité.

Exponentiel (exp)

Diminue rapidement au début, mais conserve une longue traîne

  • Fils d'actualité où la récence est essentielle

  • Médias sociaux où le contenu frais doit dominer

  • Lorsque la proximité est fortement privilégiée mais que des articles exceptionnellement éloignés doivent rester visibles

Dans une application d'actualités, les articles d'hier se classent beaucoup mieux que le contenu de la semaine précédente, mais des articles plus anciens très pertinents peuvent encore apparaître.

Linéaire (linear)

Déclin cohérent et prévisible avec une limite claire.

  • Applications avec des frontières naturelles

  • Services avec des limites de distance

  • Contenu avec des dates d'expiration ou des seuils clairs

Dans un outil de recherche d'événements, les événements au-delà d'une fenêtre future de deux semaines n'apparaissent tout simplement pas.

Pour obtenir des informations détaillées sur la manière dont chaque outil de classement calcule les scores et les modèles de déclin spécifiques, reportez-vous à la documentation correspondante :

Exemple de mise en œuvre

Les classificateurs de décroissance peuvent être appliqués aux opérations de recherche vectorielle standard et de recherche hybride dans Milvus. Vous trouverez ci-dessous les principaux extraits de code pour la mise en œuvre de cette fonctionnalité.

Avant d'utiliser les fonctions de décroissance, vous devez d'abord créer une collection avec les champs numériques appropriés (comme les horodatages, les distances, etc.) qui seront utilisés pour les calculs de décroissance. Pour des exemples de travail complets comprenant la configuration de la collection, la définition du schéma et l'insertion de données, reportez-vous au didacticiel : Mise en œuvre du classement basé sur le temps dans Milvus.

Création d'un classeur de décroissance

Pour mettre en œuvre le classement par décroissance, définissez d'abord un objet Function avec la configuration appropriée :

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

Paramètres

Nécessaire ?

Description de l'objet

Valeur/Exemple

name

Oui

Identifiant de la fonction utilisée lors de l'exécution des recherches. Choisissez un nom descriptif correspondant à votre cas d'utilisation.

"time_decay"

input_field_names

Oui

Champ numérique pour le calcul du score de décroissance. Détermine l'attribut de données qui sera utilisé pour le calcul de la dégradation (par exemple, les horodatages pour la dégradation basée sur le temps, les coordonnées pour la dégradation basée sur l'emplacement).

Il doit s'agir d'un champ de votre collection qui contient des valeurs numériques pertinentes. Prend en charge INT8/16/32/64, FLOAT, DOUBLE.

["timestamp"]

function_type

Oui

Spécifie le type de fonction créée.

Doit être défini sur RERANK pour tous les classeurs de désintégration.

FunctionType.RERANK

params.reranker

Oui

Spécifie la méthode de reclassement à utiliser.

Doit être défini sur "decay" pour activer la fonctionnalité de classement par décroissance.

"decay"

params.function

Oui

Spécifie le classeur mathématique de décroissance à appliquer. Détermine la forme de la courbe de décroissance de la pertinence.

Voir la section Choisir le bon classificateur de décroissance pour obtenir des conseils sur la sélection de la fonction appropriée.

"gauss" "exp", ou "linear"

params.origin

Oui

Point de référence à partir duquel le score de décroissance est calculé. Les éléments situés à cette valeur reçoivent des scores de pertinence maximums.

Pour la désintégration basée sur le temps, l'unité de temps doit correspondre à vos données de collecte.

  • Pour les horodatages : l'heure actuelle (par exemple, int(time.time())).

  • Pour la géolocalisation : les coordonnées actuelles de l'utilisateur.

params.scale

Oui

Distance ou temps à partir duquel la pertinence chute jusqu'à la valeur decay. Contrôle la vitesse à laquelle la pertinence diminue.

Dans le cas d'un déclin basé sur le temps, l'unité de temps doit correspondre à vos données de collecte.

Des valeurs plus élevées entraînent une baisse plus progressive de la pertinence ; des valeurs plus faibles entraînent une baisse plus marquée.

  • Pour le temps : période en secondes (par exemple, 7 * 24 * 60 * 60 pendant 7 jours).

  • Pour la distance : mètres (par exemple, 5000 pour 5 km).

params.offset

Non

Crée une "zone de non-décroissance" autour de origin où les éléments conservent leur score complet (score de décroissance = 1,0).

Pour la désintégration basée sur le temps, l'unité de temps doit correspondre à vos données de collecte.

Les éléments situés dans cette zone du site origin conservent une pertinence maximale.

  • Pour le temps : période en secondes (par exemple, 24 * 60 * 60 pour 1 jour).

  • Pour la distance : mètres (par exemple, 500 pour 500m)

params.decay

Non

Valeur du score à la distance scale, contrôle l'inclinaison de la courbe. Des valeurs plus faibles créent des courbes de déclin plus raides ; des valeurs plus élevées créent des courbes de déclin plus progressives.

Doit être compris entre 0 et 1.

0.5 (par défaut)

Après avoir défini votre classificateur de décroissance, vous pouvez l'appliquer lors des opérations de recherche en le passant au paramètre 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