Exécuter une recherche hybride de similarité vectorielle

Ce document explique comment effectuer des recherches hybrides dans AlloyDB pour PostgreSQL, qui combine la recherche de texte, la correspondance des mots clés, la recherche vectorielle et la similarité sémantique à l'aide de l'extension vector, qui est une extension pgvector PostgreSQL standard personnalisée pour AlloyDB. La recherche hybride vous permet de récupérer des résultats très pertinents en utilisant à la fois des correspondances exactes de mots clés et du contenu sémantiquement similaire.

Pour effectuer une recherche hybride dans AlloyDB pour PostgreSQL, vous devez créer un index vectoriel et un index de recherche textuelle dans votre table. Vous combinerez ensuite les résultats des deux recherches et les reclasserez de manière à présenter les informations les plus pertinentes.

Créer un index GIN

Un index GIN (Generalized Inverted Index) est un type d'index spécialisé optimisé pour la recherche dans des valeurs composites, telles que les tableaux, les données JSONB et les données de recherche en texte intégral.

Pour créer un index GIN sur vos données textuelles afin d'effectuer une recherche en texte intégral, exécutez la commande suivante :

CREATE INDEX INDEX_NAME ON TABLE USING GIN (to_tsvector('english', COLUMN_NAME));

Remplacez les éléments suivants :

  • INDEX_NAME : nom de l'index que vous souhaitez créer, par exemple my-gin-index.

  • TABLE : table à laquelle ajouter l'index.

  • COLUMN_NAME : colonne qui stocke les données textuelles que vous souhaitez rechercher.

Créer un index ScaNN

Pour appliquer un index arborescent à deux niveaux à l'aide de l'algorithme ScaNN à une colonne contenant des embeddings vectoriels stockés, exécutez la requête LDD suivante :

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE);

Remplacez les éléments suivants :

  • INDEX_NAME : nom de l'index que vous souhaitez créer, par exemple my-scann-index. Les noms d'index sont partagés dans votre base de données. Assurez-vous que chaque nom d'index est unique pour chaque table de votre base de données.

  • TABLE : table à laquelle ajouter l'index.

  • EMBEDDING_COLUMN : colonne qui stocke les données vector.

  • DISTANCE_FUNCTION : fonction de distance à utiliser avec cet index. Choisissez l'une des options suivantes :

    • Distance L2 : l2

    • Produit scalaire : dot_product

    • Distance de cosinus : cosine

  • NUM_LEAVES_VALUE : nombre de partitions à appliquer à cet index. Définissez une valeur comprise entre 1 et 1 048 576. Pour savoir comment déterminer cette valeur, consultez Régler un index ScaNN.

Pour en savoir plus sur les différentes configurations d'index ScaNN, consultez Créer un index ScaNN. Vous pouvez également créer un index HNSW.

Effectuer une recherche hybride à l'aide de la fusion de classement réciproque

La recherche hybride consiste à effectuer des recherches vectorielles et textuelles distinctes, puis à combiner et reclasser les résultats à l'aide de la fusion de classement réciproque (RRF). La RRF est un algorithme basé sur le classement qui combine plusieurs listes classées de résultats de recherche en une seule liste classée en attribuant un score à chaque document. Ce score est basé sur le classement réciproque du RRF dans toutes les listes contributrices. Les documents les mieux classés bénéficient d'une contribution plus importante. Utilisez la requête SQL suivante pour combiner la recherche en texte intégral et la recherche hybride, et reclasser les résultats :

        WITH vector_search AS (
            SELECT id,
                RANK () OVER (ORDER BY embedding <=> google_ml.embedding('MODEL_ID', 'TEXT')) AS rank
                FROM TABLE
                ORDER BY embedding <=> google_ml.embedding('MODEL_ID', 'TEXT') LIMIT 10
        ),
        text_search AS (
            SELECT id,
                RANK () OVER (ORDER BY ts_rank(to_tsvector('english', COLUMN_NAME), to_tsquery(KEYWORD)) desc)
            FROM TABLE
            WHERE to_tsvector('english', COLUMN_NAME) @@ to_tsquery(KEYWORD)
            ORDER BY ts_rank(to_tsvector('english', COLUMN_NAME), to_tsquery(KEYWORD)) desc
            LIMIT 10
        )
        SELECT
            COALESCE(vector_search.id, text_search.id) AS id,
            COALESCE(1.0 / (60 + vector_search.rank), 0.0) + COALESCE(1.0 / (60 + text_search.rank), 0.0) AS rrf_score
        FROM vector_search FULL OUTER JOIN text_search ON vector_search.id = text_search.id
        ORDER BY rrf_score DESC
        LIMIT 5;

Remplacez les éléments suivants :

  • MODEL_ID : ID du modèle à interroger.

    Si vous utilisez Vertex AI Model Garden, spécifiez text-embedding-005 comme ID de modèle. Il s'agit des modèles cloud qu'AlloyDB peut utiliser pour les embeddings textuels. Pour en savoir plus, consultez Embeddings textuels.

  • TABLE : table contenant vos données.

  • TEXT : texte à traduire en embedding vectoriel.

  • KEYWORD : mot clé que vous souhaitez rechercher.

  • COLUMN_NAME : colonne qui stocke les données textuelles que vous souhaitez rechercher.

Explication de la requête de recherche hybride et de l'expression de table commune (CTE) associée :

  • CTE vector_search : effectue une recherche de similarité vectorielle standard, en classant les résultats par distance de cosinus et en leur attribuant un classement. Elle récupère les 10 produits les plus similaires d'un point de vue sémantique.
  • CTE text_search : exécute une recherche textuelle à l'aide de to_tsvector et to_tsquery, calcule la pertinence avec ts_rank et récupère les 10 correspondances textuelles les plus pertinentes.
  • CTE Final SELECT Statement : joint les résultats des recherches vectorielle et textuelle à l'aide d'un FULL OUTER JOIN, sélectionne l'ID du produit, calcule le score RRF, trie les résultats par score et récupère les cinq premiers résultats.

Étape suivante