Visión general de Decay RankerCompatible with Milvus 2.6.x

En la búsqueda vectorial tradicional, los resultados se clasifican únicamente por similitud vectorial, es decir, por la coincidencia de los vectores en el espacio matemático. Pero en las aplicaciones del mundo real, lo que hace que un contenido sea realmente relevante a menudo depende de algo más que de la similitud semántica.

Considere estas situaciones cotidianas:

  • Una búsqueda de noticias en la que el artículo de ayer debería estar mejor clasificado que un artículo similar de hace tres años.

  • Un buscador de restaurantes que da prioridad a los locales situados a 5 minutos de distancia frente a los que requieren un trayecto de 30 minutos en coche.

  • Una plataforma de comercio electrónico que potencie los productos de moda aunque sean ligeramente menos similares a la consulta de búsqueda.

Todos estos escenarios comparten una necesidad común: equilibrar la similitud vectorial con otros factores numéricos como el tiempo, la distancia o la popularidad.

Los clasificadores de decrecimiento de Milvus responden a esta necesidad ajustando las clasificaciones de búsqueda en función de los valores de los campos numéricos. Le permiten equilibrar la similitud vectorial con la "frescura", la "cercanía" u otras propiedades numéricas de sus datos, creando experiencias de búsqueda más intuitivas y contextualmente relevantes.

Notas de uso

  • La clasificación por decaimiento no puede utilizarse con búsquedas agrupadas.

  • El campo utilizado para la clasificación por decaimiento debe ser numérico (INT8, INT16, INT32, INT64, FLOAT, o DOUBLE).

  • Cada clasificador sólo puede utilizar un campo numérico.

  • Coherencia de la unidad de tiempo: Al utilizar la clasificación por tiempo, las unidades de los parámetros origin, scale y offset deben coincidir con las unidades utilizadas en los datos de la colección:

    • Si su colección almacena las marcas de tiempo en segundos, utilice segundos para todos los parámetros.

    • Si su colección almacena marcas de tiempo en milisegundos, utilice milisegundos para todos los parámetros.

    • Si su colección almacena las marcas de tiempo en microsegundos, utilice microsegundos para todos los parámetros.

Funcionamiento

La clasificación por decaimiento mejora la búsqueda vectorial tradicional incorporando factores numéricos como el tiempo o la distancia geográfica en el proceso de clasificación. El proceso completo sigue las siguientes etapas

Etapa 1: Calcular las puntuaciones de similitud normalizadas

En primer lugar, Milvus calcula y normaliza las puntuaciones de similitud de los vectores para garantizar una comparación coherente:

  • Para las métricas de distancia L2 y JACCARD (donde los valores más bajos indican mayor similitud):

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

    Esto transforma las distancias en puntuaciones de similitud entre 0-1, donde mayor es mejor.

  • Para las métricas IP, COSINE y BM25 (donde las puntuaciones más altas ya indican mejores coincidencias): Las puntuaciones se utilizan directamente sin normalización.

Etapa 2: Calcular las puntuaciones de decaimiento

A continuación, Milvus calcula una puntuación de descomposición basada en el valor numérico del campo (como la marca de tiempo o la distancia) utilizando el clasificador de descomposición seleccionado:

  • Cada decay ranker transforma los valores numéricos brutos en puntuaciones de relevancia normalizadas entre 0-1

  • La puntuación de descomposición representa la relevancia de un elemento en función de su "distancia" respecto al punto ideal.

La fórmula de cálculo específica varía en función del tipo de clasificador. Para más detalles sobre cómo calcular una puntuación de descomposición, consulte las páginas dedicadas a la descomposición gaussiana, la descomposición exponencial y la descomposición lineal.

Etapa 3: Calcular las puntuaciones finales

Por último, Milvus combina la puntuación de similitud normalizada y la puntuación de decaimiento para producir la puntuación de clasificación final:

final_score = normalized_similarity_score × decay_score

En los casos de búsqueda híbrida (que combina múltiples campos vectoriales), Milvus toma la máxima puntuación de similitud normalizada entre las peticiones de búsqueda:

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

Por ejemplo, si un artículo de investigación obtiene una puntuación de 0,82 a partir de la similitud vectorial y de 0,91 a partir de la recuperación de texto basada en BM25 en una búsqueda híbrida, Milvus utiliza 0,91 como puntuación de similitud base antes de aplicar el factor de decaimiento.

Decay ranking en acción

Veamos la clasificación por decaimiento en un escenario práctico: la búsqueda de "artículos de investigación sobre inteligencia artificial" con un decaimiento basado en el tiempo:

En este ejemplo, las puntuaciones reflejan cómo disminuye la relevancia con el tiempo: los artículos más recientes reciben puntuaciones cercanas a 1,0 y los más antiguos, puntuaciones más bajas. Estos valores se calculan utilizando un clasificador de decaimiento específico. Para más información, consulte Elegir el clasificador de deterioro adecuado.

Artículo

Vector de similitud

Puntuación de similitud normalizada

Fecha de publicación

Decaimiento

Puntuación final

Clasificación final

Artículo A

Alto

0.85 (COSINE)

Hace 2 semanas

0.80

0.68

2

Papel B

Muy alto

0.92 (COSINE)

Hace 6 meses

0.45

0.41

3

Papel C

Medio

0.75 (COSINE)

Hace 1 día

0.98

0.74

1

Papel D

Medio-Alto

0,76 (COSINE)

hace 3 semanas

0.70

0.53

4

Sin la reordenación por decaimiento, el documento B ocuparía el primer lugar en función de la similitud vectorial pura (0,92). Sin embargo, si se aplica la reordenación por decaimiento:

  • El artículo C salta a la posición nº 1 a pesar de su similitud media porque es muy reciente (publicado ayer).

  • El artículo B cae a la posición nº 3 a pesar de su excelente similitud porque es relativamente antiguo.

  • El artículo D utiliza la distancia L2 (donde menor es mejor), por lo que su puntuación se normaliza de 1,2 a 0,76 antes de aplicar el decaimiento.

Elija el clasificador correcto

Milvus ofrece distintos clasificadores de decaimiento - gauss, exp, linear, cada uno diseñado para casos de uso específicos:

Decay Ranker

Características

Casos de uso ideales

Ejemplo

Gaussiano (gauss)

Declive gradual de sensación natural que se extiende moderadamente

  • Búsquedas generales que requieren resultados equilibrados

  • Aplicaciones en las que los usuarios tienen un sentido intuitivo de la distancia

  • Cuando una distancia moderada no debería penalizar gravemente los resultados

En una búsqueda de restaurantes, los locales de calidad situados a 3 km de distancia siguen siendo localizables, aunque con una clasificación inferior a las opciones cercanas

Exponencial (exp)

Disminuye rápidamente al principio, pero mantiene una larga cola

  • Noticias en las que la actualidad es fundamental

  • Redes sociales, donde debe dominar el contenido fresco

  • Cuando se prefiere la proximidad, pero los artículos excepcionalmente distantes deben permanecer visibles

En una aplicación de noticias, las historias de ayer se clasifican mucho mejor que el contenido de hace una semana, pero los artículos antiguos de gran relevancia pueden seguir apareciendo.

Lineal (linear)

Descenso constante y predecible con un límite claro.

  • Aplicaciones con límites naturales

  • Servicios con límites de distancia

  • Contenido con fechas de caducidad o umbrales claros

En un buscador de eventos, los eventos más allá de una ventana futura de dos semanas simplemente no aparecen en absoluto

Para obtener información detallada sobre cómo calcula las puntuaciones cada clasificador de decaimiento y los patrones de decaimiento específicos, consulte la documentación dedicada:

Ejemplo de aplicación

Los clasificadores de decaimiento pueden aplicarse tanto a la búsqueda vectorial estándar como a las operaciones de búsqueda híbrida en Milvus. A continuación se muestran los fragmentos de código clave para implementar esta función.

Antes de utilizar las funciones de decaimiento, primero debe crear una colección con los campos numéricos apropiados (como marcas de tiempo, distancias, etc.) que se utilizarán para los cálculos de decaimiento. Para ver ejemplos de trabajo completos que incluyan la configuración de la colección, la definición del esquema y la inserción de datos, consulte Tutorial: Implementar la clasificación basada en el tiempo en Milvus.

Crear un clasificador de decaimiento

Para implementar la clasificación por decaimiento, primero defina un objeto Function con la configuración apropiada:

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

Parámetro

¿Requerido?

Descripción

Valor/Ejemplo

name

Identificador de la función utilizada al ejecutar búsquedas. Elija un nombre descriptivo relevante para su caso de uso.

"time_decay"

input_field_names

Campo numérico para el cálculo de la puntuación del decaimiento. Determina qué atributo de datos se utilizará para calcular la descomposición (por ejemplo, marcas de tiempo para la descomposición basada en el tiempo, coordenadas para la descomposición basada en la ubicación).

Debe ser un campo de su colección que contenga valores numéricos relevantes. Admite INT8/16/32/64, FLOAT, DOUBLE.

["timestamp"]

function_type

Especifica el tipo de función que se está creando.

Debe establecerse en RERANK para todos los clasificadores de descomposición.

FunctionType.RERANK

params.reranker

Especifica el método de renumeración que se va a utilizar.

Debe establecerse en "decay" para habilitar la función de clasificación por decaimiento.

"decay"

params.function

Especifica el clasificador matemático que se aplicará. Determina la forma de la curva de descenso de relevancia.

Consulte la sección Elegir el clasificador de decaimiento adecuado para obtener orientación sobre la selección de la función adecuada.

"gauss" "exp" o "linear"

params.origin

Punto de referencia a partir del cual se calcula la puntuación del deterioro. Los artículos con este valor reciben la máxima puntuación de relevancia.

Para el decaimiento basado en el tiempo, la unidad de tiempo debe coincidir con sus datos de recopilación.

  • Para marcas de tiempo: hora actual (por ejemplo, int(time.time()))

  • Para la geolocalización: coordenadas actuales del usuario

params.scale

Distancia o tiempo en el que la relevancia desciende hasta el valor decay. Controla la rapidez con la que disminuye la relevancia.

Para el decaimiento basado en el tiempo, la unidad de tiempo debe coincidir con sus datos de recopilación.

Los valores más altos crean una disminución más gradual de la relevancia; los valores más pequeños crean una disminución más pronunciada.

  • Para el tiempo: periodo en segundos (por ejemplo, 7 * 24 * 60 * 60 durante 7 días)

  • Para la distancia: metros (por ejemplo, 5000 para 5km)

params.offset

Sin

Crea una "zona de no decaimiento" alrededor de origin en la que los elementos mantienen su puntuación completa (puntuación de decaimiento = 1,0).

Para la descomposición basada en el tiempo, la unidad de tiempo debe coincidir con sus datos de recogida.

Los artículos dentro de este rango de origin mantienen la máxima relevancia.

  • Para el tiempo: periodo en segundos (por ejemplo, 24 * 60 * 60 durante 1 día)

  • Para la distancia: metros (por ejemplo, 500 para 500m)

params.decay

Sin

Valor de puntuación en la distancia scale, controla la inclinación de la curva. Los valores más bajos crean curvas de descenso más pronunciadas; los valores más altos crean curvas de descenso más graduales.

Debe estar entre 0 y 1.

0.5 (por defecto)

Después de definir tu decay ranker, puedes aplicarlo durante las operaciones de búsqueda pasándolo al parámetro 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