Filtros en consultas vectoriales

Puedes establecer un modos de filtro vectorial en una consulta vectorial para especificar si quieres filtrar antes o después de la ejecución de la consulta.

Los filtros determinan el ámbito de una consulta vectorial. Los filtros se establecen e iteran los campos numéricos y de cadena que se atribuyen como filterable en el índice, pero el propósito del filtro determina sobre qué se ejecuta la consulta vectorial: todo el espacio que se puede buscar o el contenido de un resultado de búsqueda.

En este artículo se describe cada modo de filtro y se proporcionan instrucciones sobre cuándo usar cada uno.

Modo de filtro previo

El filtrado previo aplica filtros antes de la ejecución de la consulta, lo que reduce el área expuesta de búsqueda sobre la que el algoritmo del vector de búsqueda busca contenido similar. En una consulta vectorial, preFilter es el valor predeterminado.

Diagram of prefilters.

Modo postfiltro

El filtrado posterior aplica filtros después de la ejecución de la consulta, lo que limita los resultados de la búsqueda.

Diagram of post-filters.

Punto de referencia de comparación de modos de filtro vectorial

Para comprender las condiciones en las que un modo de filtro funciona mejor que el otro, hemos ejecutado una serie de pruebas para evaluar los resultados de las consultas en índices pequeños, medianos y grandes.

  • Pequeño (100 000 documentos, índice de 2,5 GB, 1536 dimensiones)
  • Mediando (1 millón de documentos, índice de 25 GB, 1536 dimensiones)
  • Grande (Mil millones de documentos, índice de 1.9 GB, 96 dimensiones)

Para las cargas de trabajo pequeñas y medianas, usamos un servicio Standard 2 (S2) con una partición y una réplica. Para la carga de trabajo grande, usamos un servicio Standard 3 (S3) con 12 particiones y una réplica.

Los índices tenían una construcción idéntica: un campo clave, un campo vectorial, un campo de texto y un campo filtrable numérico. El siguiente índice se define mediante la sintaxis 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"}}
            ]
        }
    }

En las consultas, hemos usado un filtro idéntico para las operaciones de prefiltro y postfiltro. Usamos un filtro sencillo para asegurarnos de que las variaciones en el resultado se deben al modo de filtrado y no a la complejidad del filtro.

Los resultados se midieron en consultas por segundo (QPS).

Puntos clave

  • El filtrado previo es casi siempre más lento que el posterior, excepto en índices pequeños en los que el rendimiento es aproximadamente igual.

  • En conjuntos de datos más grandes, el filtrado previo es más lento.

  • ¿Por qué el valor predeterminado es el filtrado previo si casi siempre es más lento? El filtrado previo garantiza que k resultados se devuelvas si existen en el índice, donde el sesgo favorece la recuperación y la precisión con respecto a la velocidad.

  • El filtrado posterior es para los clientes que:

    • valoran la velocidad por encima de la selección (el filtrado posterior puede devolver menos de k resultados)
    • usan filtros que no son demasiado selectivos
    • tienen índices de tamaño suficiente, de modo que el rendimiento del prefiltro es inaceptable

Detalles

  • Si tenemos un conjunto de datos con 100 000 vectores en 1536 dimensiones:

    • Al filtrar más del 30 % del conjunto de datos, el filtrado previo y el posterior fueron similares.
    • Al filtrar menos del 0,1 % del conjunto de datos, el filtrado previo fue aproximadamente un 50 % más lento que el posterior.
  • Si tenemos un conjunto de datos con 1 millón de vectores en 1536 dimensiones:

    • Al filtrar más del 30 % del conjunto de datos, el filtrado previo fue aproximadamente un 30 % más lento.
    • Al filtrar menos del 2 % del conjunto de datos, el filtrado previo fue aproximadamente siete veces más lento.
  • Si tenemos un conjunto de datos con mil millones de vectores en 96 dimensiones:

    • Al filtrar más del 5 % del conjunto de datos, el filtrado previo fue aproximadamente un 50 % más lento.
    • Al filtrar menos del 10 % del conjunto de datos, el filtrado previo fue aproximadamente siete veces más lento.

En el gráfico siguiente se muestran las QPS relativo al prefiltro, calculadas como QPS de prefiltro divididas por QPS de postfiltro.

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

El eje vertical es QPS de prefiltro sobre QPS de postfiltro. Por ejemplo, un valor de 0,0 significa que el filtrado previo es un 100 % más lento, 0,5 en el eje vertical significa que el filtrado previo es un 50 % más lento, 1,0 significa que el filtrado previo y el filtrado posterior son equivalentes.

El eje horizontal representa la tasa de filtrado o el porcentaje de documentos candidatos después de aplicar el filtro. Por ejemplo, 1.00% significa que el criterio de filtro seleccionó un porcentaje del corpus de búsqueda.