Visão geral do Decay RankerCompatible with Milvus 2.6.x

Na pesquisa vetorial tradicional, os resultados são classificados puramente pela similaridade vetorial - a proximidade dos vetores no espaço matemático. Mas em aplicações do mundo real, o que torna o conteúdo verdadeiramente relevante depende muitas vezes de mais do que apenas a semelhança semântica.

Considere estes cenários quotidianos:

  • Uma pesquisa de notícias em que o artigo de ontem deve ter uma classificação mais elevada do que um artigo semelhante de há três anos

  • Um localizador de restaurantes que dá prioridade a locais a 5 minutos de distância em vez daqueles que requerem uma viagem de 30 minutos

  • Uma plataforma de comércio eletrónico que dá prioridade aos produtos mais populares, mesmo quando são ligeiramente menos semelhantes à consulta de pesquisa

Todos estes cenários partilham uma necessidade comum: equilibrar a semelhança de vectores com outros factores numéricos como o tempo, a distância ou a popularidade.

Os Decay Rankers do Milvus respondem a esta necessidade ajustando as classificações de pesquisa com base em valores de campo numéricos. Permitem-lhe equilibrar a semelhança vetorial com a "frescura", a "proximidade" ou outras propriedades numéricas dos seus dados, criando experiências de pesquisa mais intuitivas e contextualmente relevantes.

Notas de utilização

  • A classificação de decaimento não pode ser utilizada com pesquisas de agrupamento.

  • O campo utilizado para a classificação de decaimento tem de ser numérico (INT8, INT16, INT32, INT64, FLOAT, ou DOUBLE).

  • Cada classificador de desvalorização só pode utilizar um campo numérico.

  • Consistência da unidade de tempo: Ao utilizar a classificação de decaimento baseada no tempo, as unidades dos parâmetros origin, scale e offset devem corresponder às unidades utilizadas nos dados da sua coleção:

    • Se a sua coleção armazena carimbos de data/hora em segundos, utilize segundos para todos os parâmetros

    • Se a sua coleção armazena carimbos de data/hora em milissegundos, utilize milissegundos para todos os parâmetros

    • Se a sua coleção armazena carimbos de data/hora em microssegundos, utilize microssegundos para todos os parâmetros

Como funciona

A classificação decrescente melhora a pesquisa vetorial tradicional ao incorporar factores numéricos como o tempo ou a distância geográfica no processo de classificação. O processo inteiro segue estas etapas:

Etapa 1: Calcular as pontuações de similaridade normalizadas

Primeiro, o Milvus calcula e normaliza as pontuações de similaridade dos vectores para garantir uma comparação consistente:

  • Para as métricas de distância L2 e JACCARD (em que valores mais baixos indicam maior semelhança):

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

    Isto transforma as distâncias em pontuações de semelhança entre 0-1, em que quanto maior for, melhor.

  • Para as métricas IP, COSINE e BM25 (em que pontuações mais altas já indicam melhores correspondências): As pontuações são usadas diretamente sem normalização.

Etapa 2: Calcular as pontuações de decaimento

Em seguida, o Milvus calcula uma pontuação de deterioração com base no valor do campo numérico (como carimbo de data/hora ou distância) utilizando o classificador de deterioração selecionado:

  • Cada classificador de deterioração transforma valores numéricos brutos em pontuações de relevância normalizadas entre 0-1

  • A pontuação de deterioração representa o grau de relevância de um item com base na sua "distância" do ponto ideal

A fórmula de cálculo específica varia consoante o tipo de classificador de deterioração. Para obter detalhes sobre como calcular uma pontuação de decaimento, consulte as páginas dedicadas ao Decaimento gaussiano, Decaimento exponencial e Decaimento linear.

Etapa 3: Calcular as pontuações finais

Finalmente, o Milvus combina a pontuação de similaridade normalizada e a pontuação de decaimento para produzir a pontuação de classificação final:

final_score = normalized_similarity_score × decay_score

Nos casos de pesquisa híbrida (combinando múltiplos campos vectoriais), Milvus utiliza a pontuação máxima de similaridade normalizada entre os pedidos de pesquisa:

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

Por exemplo, se um artigo de investigação tiver uma pontuação de 0,82 na similaridade vetorial e 0,91 na recuperação de texto com base no BM25 numa pesquisa híbrida, o Milvus utiliza 0,91 como pontuação de similaridade de base antes de aplicar o fator de decaimento.

Classificação decrescente em ação

Vejamos a classificação decrescente num cenário prático - pesquisa de "artigos de investigação de IA" com decrescimento baseado no tempo:

Neste exemplo, as pontuações de decaimento reflectem a forma como a relevância diminui com o tempo - os documentos mais recentes recebem pontuações mais próximas de 1,0, os documentos mais antigos recebem pontuações mais baixas. Estes valores são calculados utilizando um classificador de decaimento específico. Para obter detalhes, consulte Escolher o classificador de deterioração correto.

Artigo

Similaridade do vetor

Pontuação de similaridade normalizada

Data de publicação

Pontuação de decaimento

Pontuação final

Classificação final

Papel A

Alta

0,85 (COSINE)

2 semanas atrás

0.80

0.68

2

Papel B

Muito elevado

0,92 (COSINE)

6 meses atrás

0.45

0.41

3

Papel C

Média

0.75 (COSINE)

1 dia atrás

0.98

0.74

1

Papel D

Médio-Alto

0.76 (COSINE)

3 semanas atrás

0.70

0.53

4

Sem o decay reranking, o Documento B teria a classificação mais elevada com base na semelhança vetorial pura (0,92). No entanto, com a classificação decrescente aplicada:

  • O artigo C salta para a posição #1 apesar da similaridade média porque é muito recente (publicado ontem)

  • O artigo B desce para a posição #3, apesar da excelente semelhança, porque é relativamente antigo

  • O artigo D utiliza a distância L2 (em que quanto menor for, melhor), pelo que a sua pontuação é normalizada de 1,2 para 0,76 antes de aplicar a desclassificação

Escolher o classificador de decaimento correto

A Milvus oferece diferentes classificadores de desvalorização - gauss, exp, linear, cada um concebido para casos de utilização específicos:

Classificador de decaimento

Caraterísticas

Casos de uso ideais

Cenário de exemplo

Gaussiano (gauss)

Declínio gradual natural que se estende moderadamente

  • Pesquisas gerais que requerem resultados equilibrados

  • Aplicações em que os utilizadores têm uma noção intuitiva da distância

  • Quando a distância moderada não deve penalizar severamente os resultados

Numa pesquisa de restaurantes, os locais de qualidade a 3 km de distância permanecem detectáveis, embora com uma classificação inferior às opções mais próximas

Exponencial (exp)

Diminui rapidamente no início, mas mantém uma cauda longa

  • Feeds de notícias em que a atualidade é fundamental

  • Redes sociais onde o conteúdo fresco deve dominar

  • Quando a proximidade é fortemente preferida, mas os itens excecionalmente distantes devem permanecer visíveis

Numa aplicação de notícias, as histórias de ontem têm uma classificação muito mais elevada do que o conteúdo de uma semana atrás, mas ainda podem aparecer artigos mais antigos altamente relevantes

Linear (linear)

Declínio consistente e previsível com um corte claro

  • Aplicações com limites naturais

  • Serviços com limites de distância

  • Conteúdos com datas de expiração ou limites claros

Num localizador de eventos, os eventos para além de uma janela futura de duas semanas simplesmente não aparecem

Para obter informações detalhadas sobre como cada classificador de decaimento calcula as pontuações e os padrões de declínio específicos, consulte a documentação dedicada:

Exemplo de implementação

Os classificadores de decaimento podem ser aplicados tanto à pesquisa vetorial padrão como às operações de pesquisa híbrida em Milvus. Abaixo estão os principais trechos de código para implementar esse recurso.

Antes de utilizar as funções de decaimento, deve primeiro criar uma coleção com campos numéricos apropriados (como carimbos de data/hora, distâncias, etc.) que serão utilizados para cálculos de decaimento. Para obter exemplos de trabalho completos, incluindo a configuração da coleção, a definição do esquema e a inserção de dados, consulte Tutorial: Implementar classificação baseada no tempo em Milvus.

Criar um classificador de decaimento

Para implementar a classificação de decaimento, primeiro defina um objeto Function com a configuração apropriada:

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

Necessário?

Descrição

Valor/Exemplo

name

Sim

Identificador da sua função utilizado na execução de pesquisas. Escolha um nome descritivo relevante para o seu caso de utilização.

"time_decay"

input_field_names

Sim

Campo numérico para cálculo da pontuação de decaimento. Determina que atributo de dados será utilizado para calcular a deterioração (por exemplo, carimbos de data/hora para deterioração baseada no tempo, coordenadas para deterioração baseada na localização).

Tem de ser um campo na sua coleção que contenha valores numéricos relevantes. Suporta INT8/16/32/64, FLOAT, DOUBLE.

["timestamp"]

function_type

Sim

Especifica o tipo de função que está a ser criada.

Tem de ser definido como RERANK para todos os classificadores de decaimento.

FunctionType.RERANK

params.reranker

Sim

Especifica o método de classificação a utilizar.

Tem de ser definido para "decay" para ativar a funcionalidade de classificação decrescente.

"decay"

params.function

Sim

Especifica qual o classificador matemático de redução a aplicar. Determina a forma da curva de declínio da relevância.

Consulte a secção Escolher o classificador de desvalorização correto para obter orientação sobre como selecionar a função adequada.

"gauss", "exp", ou "linear"

params.origin

Sim

Ponto de referência a partir do qual a pontuação de decaimento é calculada. Os itens neste valor recebem pontuações de relevância máxima.

Para a desvalorização baseada no tempo, a unidade de tempo deve corresponder aos seus dados de recolha.

  • Para carimbos de data/hora: hora atual (por exemplo, int(time.time()))

  • Para geolocalização: coordenadas actuais do utilizador

params.scale

Sim

Distância ou tempo em que a relevância cai para o valor decay. Controla a rapidez com que a relevância diminui.

Para a diminuição baseada no tempo, a unidade de tempo deve corresponder aos seus dados de recolha.

Valores maiores criam um declínio mais gradual na relevância; valores menores criam um declínio mais acentuado.

  • Para o tempo: período em segundos (por exemplo, 7 * 24 * 60 * 60 durante 7 dias)

  • Para a distância: metros (por exemplo, 5000 para 5km)

params.offset

Não

Cria uma "zona sem decaimento" à volta de origin onde os itens mantêm as pontuações completas (pontuação de decaimento = 1,0).

Para a deterioração baseada no tempo, a unidade de tempo deve corresponder aos seus dados de recolha.

Os itens dentro deste intervalo do origin mantêm a relevância máxima.

  • Para tempo: período em segundos (por exemplo, 24 * 60 * 60 durante 1 dia)

  • Para distância: metros (por exemplo, 500 para 500m)

params.decay

Não

Valor da pontuação na distância scale, controla a inclinação da curva. Os valores mais baixos criam curvas de declínio mais acentuadas; os valores mais altos criam curvas de declínio mais graduais.

Deve estar entre 0 e 1.

0.5 (predefinição)

Depois de definir o seu classificador de decaimento, pode aplicá-lo durante as operações de pesquisa, passando-o para o 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