Partage via


Filtres dans les requêtes vectorielles

Vous pouvez définir un mode de filtre vectoriel sur une requête vectorielle pour spécifier si vous souhaitez filtrer avant ou après l’exécution de la requête.

Les filtres déterminent l’étendue d’une requête de vecteur. Les filtres sont définis et itérés sur des champs chaîne et numériques non-vecteur attribués comme filterable dans l’index, mais le but d’un filtre détermine ce sur quoi la requête vectorielle s’exécute : l’espace entier dans lequel rechercher ou le contenu d’un résultat de recherche.

Cet article décrit chaque mode de filtrage et fournit des conseils sur le moment où il convient de l'utiliser.

Mode préfiltre

Le préfiltrage applique des filtres avant l’exécution de la requête, ce qui réduit la zone de surface de recherche sur laquelle l’algorithme de recherche vectorielle recherche du contenu similaire. Dans une requête vectorielle, preFilter est la valeur par défaut.

Diagram of prefilters.

Mode post-filtre

Le post-filtrage applique des filtres après l'exécution de la requête, ce qui réduit les résultats de la recherche.

Diagram of post-filters.

Test d’évaluation des modes de filtre vectoriel

Pour comprendre les conditions dans lesquelles un mode de filtre fonctionne mieux que l’autre, nous avons exécuté une série de tests pour évaluer les résultats des requêtes sur des index de petite, moyenne et grande taille.

  • Petit (100 000 documents, index de 2,5 Go, 1536 dimensions)
  • Moyen (1 million de documents, index de 25 Go, 1536 dimensions)
  • Large (1 milliard de documents, index de 1,9 To, 96 dimensions)

Pour les charges de travail petites et moyennes, nous avons utilisé un service Standard 2 (S2) avec une partition et un réplica. Pour la charge de travail importante, nous avons utilisé un service Standard 3 (S3) avec 12 partitions et une réplique.

Les index ont une construction identique : un champ clé, un champ vectoriel, un champ de texte et un champ filtrable numérique. L’index suivant est défini avec la syntaxe 2023-07-01-preview.

def get_index_schema(self, index_name, dimensions):
    return {
        "name": index_name,
        "fields": [
            {"name": "id", "type": "Edm.String", "key": True, "searchable": True},
            {"name": "content_vector", "type": "Collection(Edm.Single)", "dimensions": dimensions,
              "searchable": True, "retrievable": True, "filterable": False, "facetable": False, "sortable": False,
              "vectorSearchConfiguration": "defaulthnsw"},
            {"name": "text", "type": "Edm.String", "searchable": True, "filterable": False, "retrievable": True,
              "sortable": False, "facetable": False},
            {"name": "score", "type": "Edm.Double", "searchable": False, "filterable": True,
              "retrievable": True, "sortable": True, "facetable": True}
        ],
        "vectorSearch":
        {
            "algorithmConfigurations": [
                {"name": "defaulthnsw", "kind": "hnsw", "hnswParameters": {"metric": "euclidean"}}
            ]
        }
    }

Dans les requêtes, nous avons utilisé un filtre identique pour les opérations de préfiltrage et de post-filtre. Nous avons utilisé un filtre simple pour nous assurer que les variations de performance étaient dues au mode de filtrage et non à la complexité du filtre.

Les résultats ont été mesurés dans les requêtes par seconde (QPS).

Éléments importants à retenir

  • Le préfiltrage est presque toujours plus lent que le postfiltrage, sauf sur les petits index où les performances sont approximativement égales.

  • Sur des ensembles de données plus importants, le préfiltrage est beaucoup plus lent.

  • Pourquoi est-ce que le préfiltrer la valeur par défaut s’il est presque toujours plus lent ? Le préfiltrage garantit que les résultats k sont retournés s’ils existent dans l’index, où le biais favorise le rappel et la précision par rapport à la vitesse.

  • Le postfiltrage est destiné aux clients qui :

    • vitesse de valeur sur la sélection (postfiltrage peut retourner moins de k résultats)
    • utiliser des filtres qui ne sont pas trop sélectifs
    • ont des index d'une taille suffisante pour que les performances du préfiltrage soient inacceptables

Détails

  • Compte tenu d’un jeu de données avec 100 000 vecteurs à 1536 dimensions :

    • Lors du filtrage de plus de 30 % du jeu de données, le préfiltrage et le postfiltrage étaient comparables.
    • Lors du filtrage inférieur à 0,1 % du jeu de données, le préfiltrage était d’environ 50 % plus lent que le postfiltrage.
  • Étant donné un ensemble de données comprenant 1 million de vecteurs à 1536 dimensions :

    • Lors du filtrage de plus de 30 % du jeu de données, le préfiltrage était d’environ 30 % plus lent.
    • Lorsque le filtrage porte sur moins de 2 % de l'ensemble de données, le préfiltrage est environ sept fois plus lent.
  • Étant donné un ensemble de données comprenant 1 milliard de vecteurs à 96 dimensions :

    • Lors du filtrage de plus de 5 % du jeu de données, le préfiltrage était d’environ 50 % plus lent.
    • Lorsque le filtrage porte sur moins de 10 % de l'ensemble de données, le préfiltrage est environ sept fois plus lent.

Le graphique suivant montre le QPS relatif au préfiltre, calculé en tant que QPS préfiltré divisé par QPS postfilter.

Chart showing QPS performance for small, medium, and large indexes for relative QPS.

L’axe vertical est QPS de préfiltrage sur QPS de postfiltrage. Par exemple, une valeur de 0,0 signifie que le préfiltrage est 100 % plus lent, 0,5 sur l'axe vertical signifie que le préfiltrage est 50 % plus lent, 1,0 signifie que le préfiltrage et le post-filtrage sont équivalents.

L’axe horizontal représente le taux de filtrage ou le pourcentage de documents candidats après l’application du filtre. Par exemple, 1.00% signifie qu’un pourcentage du corpus de recherche a été sélectionné par les critères de filtre.