Introduction aux bases de données vectorielles et à l’utilisation de l’IA pour le référencement

Une base de données vectorielle est une collection de données où chaque donnée est stockée sous la forme d’un vecteur (numérique). Un vecteur représente un objet ou une entité, comme une image, une personne, un lieu, etc. dans un espace abstrait à N dimensions.

Les vecteurs, tels qu’ils sont expliqués dans le chapitre précédentsont essentiels pour identifier la façon dont les entités sont liées et peuvent être utilisés pour trouver leur similarité sémantique. Cela peut être appliqué de plusieurs façons pour le référencement – comme le regroupement de mots-clés ou de contenus similaires (à l’aide de kNN).

Dans cet article, nous allons découvrir quelques façons d’appliquer l’IA au référencement, notamment en trouvant du contenu sémantiquement similaire pour les liens internes. Cela peut vous aider à affiner votre stratégie de contenu à une époque où les moteurs de recherche sont de plus en plus souvent des moteurs de recherche. s’appuient de plus en plus sur les LLM.

Vous pouvez également lire un article précédent de cette série sur la manière de trouver des la cannibalisation des mots-clés à l’aide de l’intégration de texte d’OpenAI.

Plongeons ici pour commencer à construire la base de notre outil.

Comprendre les bases de données vectorielles

Si vous avez des milliers d’articles et que vous voulez trouver la similarité sémantique la plus proche pour votre requête cible, vous ne pouvez pas créer des embeddings vectoriels pour tous les articles à la volée pour les comparer, car c’est très inefficace.

Pour que cela soit possible, il faudrait générer les vector embeddings une seule fois et les conserver dans une base de données que l’on peut interroger pour trouver l’article le plus proche.

C’est ce que font les bases de données vectorielles : il s’agit de types particuliers de bases de données qui stockent les encastrements (vecteurs).

Lorsque vous interrogez la base de données, contrairement aux bases de données traditionnelles, elles effectuent les opérations suivantes correspondance de similarité cosinus et renvoie les vecteurs (dans le cas présent, les articles) les plus proches d’un autre vecteur (dans le cas présent, un mot-clé) interrogé.

Voici à quoi cela ressemble:

Exemple d’enregistrement de texte dans la base de données vectorielle.

Dans la base de données vectorielle, vous pouvez voir les vecteurs avec les métadonnées stockées, que nous pouvons facilement interroger en utilisant le langage de programmation de notre choix.

Dans cet article, nous utiliserons Pomme de pin en raison de sa facilité de compréhension et de sa simplicité d’utilisation, mais il existe d’autres fournisseurs tels que Chroma, BigQueryou Qdrant que vous pouvez consulter.

Entrons dans le vif du sujet.

1. Créer une base de données vectorielle

Tout d’abord, créez un compte sur Pinecone et créez un index avec une configuration de « text-embedding-ada-002 » avec « cosinus » comme métrique pour mesurer la distance vectorielle. Vous pouvez donner n’importe quel nom à l’index, nous l’appelleronsarticle-index-all-ada‘.

Création d'une base de données vectorielle Création d’une base de données vectorielle.

Cette interface d’aide ne sert qu’à vous assister lors de la configuration. Si vous souhaitez stocker l’intégration de vecteurs Vertex AI, vous devez définir ‘dimensions’ à 768 dans l’écran de configuration pour correspondre à la dimensionnalité par défaut et vous pouvez stocker des vecteurs de texte Vertex AI (vous pouvez définir une valeur de dimension allant de 1 à 768 pour économiser la mémoire).

Dans cet article, nous allons apprendre à utiliser les fonctions ‘text-embedding-ada-002’ et ‘text-embedding-ada-002’ d’OpenAi. Vertex AI de Google Modèles « text-embedding-005 ».

Une fois créée, nous avons besoin d’une clé API pour pouvoir nous connecter à la base de données en utilisant l’URL hôte de la base de données vectorielle.

Ensuite, vous devrez utiliser Jupyter Notebook. Si vous ne l’avez pas installé, suivez les instructions suivantes ce guide pour l’installer et lancez ensuite cette commande (ci-dessous) dans le terminal de votre PC pour installer tous les paquets nécessaires.

pip install openai google-cloud-aiplatform google-auth pandas pinecone-client tabulate ipython numpy

Et n’oubliez pas que ChatGPT est très utile lorsque vous rencontrez des problèmes pendant le codage !

2. Exporter vos articles depuis votre CMS

Ensuite, nous devons préparer un fichier d’exportation CSV des articles de votre CMS. Si vous utilisez WordPress, vous pouvez utiliser un plugin pour le faire. des exportations personnalisées.

Notre objectif final étant de construire un outil de liaison interne, nous devons décider quelles données doivent être transférées dans la base de données vectorielle en tant que métadonnées. Essentiellement, le filtrage basé sur les métadonnées agit comme une couche supplémentaire d’orientation de la recherche, en l’alignant sur l’orientation générale de la base de données vectorielles. cadre RAG en intégrant des connaissances externes, ce qui contribuera à améliorer la qualité de la recherche.

Par exemple, si nous éditons un article sur le « PPC » et que nous voulons insérer un lien vers l’expression « Keyword Research », nous pouvons spécifier dans notre outil que « Category=PPC ». Cela permettra à l’outil d’interroger uniquement les articles de la catégorie « PPC », garantissant ainsi un lien précis et contextuellement pertinent, ou nous pouvons vouloir créer un lien vers l’expression « la plus récente mise à jour de Google » et limiter la correspondance uniquement aux articles d’actualité en utilisant « Type » et publiés cette année.

Dans notre cas, nous allons exporter :

  • Titre.
  • Catégorie.
  • Type.
  • Date de publication.
  • Année de publication.
  • Permalink.
  • Meta Description.
  • Contenu.

Pour obtenir les meilleurs résultats, nous concaténerons les champs titre et méta-description, car ils constituent la meilleure représentation de l’article que nous puissions vectoriser et sont idéaux pour l’intégration et la création de liens internes.

L’utilisation du contenu complet de l’article pour l’intégration peut réduire la précision et diluer la pertinence des vecteurs.

Cela est dû au fait qu’un seul encastrement de grande taille tente de représenter plusieurs sujets couverts par l’article en même temps, ce qui conduit à une représentation moins ciblée et moins pertinente. Regroupement stratégies (découpage de l’article en rubriques naturelles ou en segments sémantiquement significatifs) doivent être appliquées, mais ce n’est pas l’objet de cet article.

Voici l’article exemple de fichier d’exportation que vous pouvez télécharger et utiliser pour notre exemple de code ci-dessous.

2. Insérer les encodages de texte d’OpenAi dans la base de données vectorielle

En supposant que vous disposiez déjà d’une base de données clé API OpenAICe code génère des embeddings vectoriels à partir du texte et les insère dans la base de données vectorielle de Pinecone.

import pandas as pd
from openai import OpenAI
from pinecone import Pinecone
from IPython.display import clear_output

# Setup your OpenAI and Pinecone API keys
openai_client = OpenAI(api_key='YOUR_OPENAI_API_KEY')  # Instantiate OpenAI client
pinecone = Pinecone(api_key='YOUR_PINECON_API_KEY')

# Connect to an existing Pinecone index
index_name = "article-index-all-ada"
index = pinecone.Index(index_name)

def generate_embeddings(text):
    """
    Generates an embedding for the given text using OpenAI's API.
    Returns None if text is invalid or an error occurs.
    """
    try:
        if not text or not isinstance(text, str):
            raise ValueError("Input text must be a non-empty string.")

        result = openai_client.embeddings.create(
            input=text,
            model="text-embedding-ada-002"
        )

        clear_output(wait=True)  # Clear output for a fresh display

        if hasattr(result, 'data') and len(result.data) > 0:
            print("API Response:", result)
            return result.data[0].embedding
        else:
            raise ValueError("Invalid response from the OpenAI API. No data returned.")

    except ValueError as ve:
        print(f"ValueError: {ve}")
        return None
    except Exception as e:
        print(f"An error occurred while generating embeddings: {e}")
        return None

# Load your articles from a CSV
df = pd.read_csv('Sample Export File.csv')

# Process each article
for idx, row in df.iterrows():
    try:
        clear_output(wait=True)
        content = row["Content"]
        vector = generate_embeddings(content)

        if vector is None:
            print(f"Skipping article ID {row['ID']} due to empty or invalid embedding.")
            continue

        index.upsert(vectors=[
            (
                row['Permalink'],  # Unique ID
                vector,            # The embedding
                {
                    'title': row['Title'],
                    'category': row['Category'],
                    'type': row['Type'],
                    'publish_date': row['Publish Date'],
                    'publish_year': row['Publish Year']
                }
            )
        ])
    except Exception as e:
        clear_output(wait=True)
        print(f"Error processing article ID {row['ID']}: {str(e)}")

print("Embeddings are successfully stored in the vector database.")

Vous devez créer un fichier notebook et le copier-coller, puis télécharger le fichier CSV ‘Sample Export File.csv’ dans le même dossier.

Projet JupyterProjet Jupyter.

Une fois que c’est fait, cliquez sur le bouton Run et cela commencera à pousser tous les vecteurs d’intégration de texte dans l’index. article-index-all-ada que nous avons créé dans la première étape.

Exécution du scriptExécution du script.

Vous verrez le texte du journal de sortie des vecteurs d’intégration. Une fois le script terminé, il affichera un message à la fin indiquant qu’il a été exécuté avec succès. Maintenant, allez vérifier votre index dans la Pinecone et vous verrez votre s’y trouvent.

3. Trouver un article correspondant à un mot-clé

Essayons maintenant de trouver un article correspondant au mot-clé.

Créez un nouveau fichier notebook et copiez-collez ce code.

from openai import OpenAI
from pinecone import Pinecone
from IPython.display import clear_output
from tabulate import tabulate  # Import tabulate for table formatting

# Setup your OpenAI and Pinecone API keys
openai_client = OpenAI(api_key='YOUR_OPENAI_API_KEY')  # Instantiate OpenAI client
pinecone = Pinecone(api_key='YOUR_OPENAI_API_KEY')

# Connect to an existing Pinecone index
index_name = "article-index-all-ada"
index = pinecone.Index(index_name)


# Function to generate embeddings using OpenAI's API
def generate_embeddings(text):
    """
    Generates an embedding for a given text using OpenAI's API.

    """
    try:
        if not text or not isinstance(text, str):
            raise ValueError("Input text must be a non-empty string.")

        result = openai_client.embeddings.create(
            input=text,
            model="text-embedding-ada-002"
        )

        # Debugging: Print the response to understand its structure
        clear_output(wait=True)
        #print("API Response:", result)

        if hasattr(result, 'data') and len(result.data) > 0:
            return result.data[0].embedding
        else:
            raise ValueError("Invalid response from the OpenAI API. No data returned.")

    except ValueError as ve:
        print(f"ValueError: {ve}")
        return None

    except Exception as e:
        print(f"An error occurred while generating embeddings: {e}")
        return None

# Function to query the Pinecone index with keywords and metadata
def match_keywords_to_index(keywords):
    """
    Matches a list of keywords to the closest article in the Pinecone index, filtering by metadata dynamically.
    """
    results = []

    for keyword_pair in keywords:
        try:
            clear_output(wait=True)
            # Extract the keyword and category from the sub-array
            keyword = keyword_pair[0]
            category = keyword_pair[1]

            # Generate embedding for the current keyword
            vector = generate_embeddings(keyword)
            if vector is None:
                print(f"Skipping keyword '{keyword}' due to embedding error.")
                continue

            # Query the Pinecone index for the closest vector with metadata filter
            query_results = index.query(
                vector=vector,  # The embedding of the keyword
                top_k=1,  # Retrieve only the closest match
                include_metadata=True,  # Include metadata in the results
                filter={"category": category}  # Filter results by metadata category dynamically
            )

            # Store the closest match
            if query_results['matches']:
                closest_match = query_results['matches'][0]
                results.append({
                    'Keyword': keyword,  # The searched keyword
                    'Category': category,  # The category used for filtering
                    'Match Score': f"{closest_match['score']:.2f}",  # Similarity score (formatted to 2 decimal places)
                    'Title': closest_match['metadata'].get('title', 'N/A'),  # Title of the article
                    'URL': closest_match['id']  # Using 'id' as the URL
                })
            else:
                results.append({
                    'Keyword': keyword,
                    'Category': category,
                    'Match Score': 'N/A',
                    'Title': 'No match found',
                    'URL': 'N/A'
                })

        except Exception as e:
            clear_output(wait=True)
            print(f"Error processing keyword '{keyword}' with category '{category}': {e}")
            results.append({
                'Keyword': keyword,
                'Category': category,
                'Match Score': 'Error',
                'Title': 'Error occurred',
                'URL': 'N/A'
            })

    return results

# Example usage: Find matches for an array of keywords and categories
keywords = [["SEO Tools", "SEO"], ["TikTok", "TikTok"], ["SEO Consultant", "SEO"]]  # Replace with your keywords and categories
matches = match_keywords_to_index(keywords)

# Display the results in a table
print(tabulate(matches, headers="keys", tablefmt="fancy_grid"))

Nous essayons de trouver une correspondance pour ces mots-clés :

  • Outils SEO.
  • TikTok.
  • Consultant SEO.

Et voici le résultat que nous obtenons après avoir exécuté le code :

Trouver une correspondance pour le mot-clé dans la base de données vectorielleTrouver une correspondance pour l’expression du mot-clé dans la base de données vectorielle

Le tableau formaté en bas de page montre les articles les plus proches de nos mots-clés.

4. Insertion des intégrations de texte Google Vertex AI dans la base de données vectorielle

Faisons maintenant la même chose mais avec Google Vertex AItext-embedding-005’embedding’. Ce modèle est remarquable parce qu’il est développé par Google, les pouvoirs Recherche Vertex AIet est spécifiquement formé pour traiter les tâches de recherche et d’appariement des requêtes, ce qui le rend bien adapté à notre cas d’utilisation.

Vous pouvez même construire un widget de recherche interne et ajoutez-le à votre site web.

Commencez par vous connecter à Google Cloud Console et à créer un projet. Ensuite, à partir de l’écran bibliothèque API trouver Vertex AI API et l’activer.

Vertex AI APICapture d’écran de Google Cloud Console, décembre 2024

Configurez votre compte de facturation pour pouvoir utiliser Vertex AI en fonction de la tarification. $0.0002 pour 1 000 caractères (et offre 300 $ de crédits pour les nouveaux utilisateurs).

Une fois que vous l’avez défini, vous devez vous rendre à l’adresse suivante API Services &gt ; Credentials créez un compte de service, générez une clé et téléchargez-la au format JSON.

Renommez le fichier JSON en config.json et téléchargez-le (via l’icône de la flèche vers le haut) dans votre dossier de projet Jupyter Notebook.

Capture d'écran de Google Cloud Console, décembre 2024Capture d’écran de Google Cloud Console, décembre 2024

Dans la première étape de la configuration, créez une nouvelle base de données vectorielle appelée article-index-vertex en définissant manuellement la dimension 768.

Une fois créée, vous pouvez exécuter ce script pour commencer à générer des embeddings vectoriels à partir du même fichier d’exemple en utilisant Google Vertex AI. text-embedding-005 (vous pouvez choisir text-multilingual-embedding-002 si votre texte n’est pas en anglais).

import os
import sys
import time
import numpy as np
import pandas as pd
from typing import List, Optional

from google.auth import load_credentials_from_file
from google.cloud import aiplatform
from google.api_core.exceptions import ServiceUnavailable

from pinecone import Pinecone
from vertexai.language_models import TextEmbeddingModel, TextEmbeddingInput

# Set up your Google Cloud credentials
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "config.json"  # Replace with your JSON key file
credentials, project_id = load_credentials_from_file(os.environ["GOOGLE_APPLICATION_CREDENTIALS"])

# Initialize Pinecone
pinecone = Pinecone(api_key='YOUR_PINECON_API_KEY')  # Replace with your Pinecone API key
index = pinecone.Index("article-index-vertex")       # Replace with your Pinecone index name

# Initialize Vertex AI
aiplatform.init(project=project_id, credentials=credentials, location="us-central1")

def generate_embeddings(
    text: str,
    task: str = "RETRIEVAL_DOCUMENT",
    model_id: str = "text-embedding-005",
    dimensions: Optional[int] = 768
) -> Optional[List[float]]:
    if not text or not text.strip():
        print("Text input is empty. Skipping.")
        return None
    
    try:
        model = TextEmbeddingModel.from_pretrained(model_id)
        input_data = TextEmbeddingInput(text, task_type=task)
        vectors = model.get_embeddings([input_data], output_dimensionality=dimensions)
        return vectors[0].values
    except ServiceUnavailable as e:
        print(f"Vertex AI service is unavailable: {e}")
        return None
    except Exception as e:
        print(f"Error generating embeddings: {e}")
        return None


# Load data from CSV
data = pd.read_csv("Sample Export File.csv")         # Replace with your CSV file path

for idx, row in data.iterrows():
    try:
        permalink = str(row["Permalink"])
        content = row["Content"]
        embedding = generate_embeddings(content)
        
        if not embedding:
            print(f"Skipping article ID {row['ID']} due to empty or failed embedding.")
            continue
        
        print(f"Embedding for {permalink}: {embedding[:5]}...")
        sys.stdout.flush()
        
        index.upsert(vectors=[
            (
                permalink,
                embedding,
                {
                    'category': row['Category'],
                    'title': row['Title'],
                    'publish_date': row['Publish Date'],
                    'type': row['Type'],
                    'publish_year': row['Publish Year']
                }
            )
        ])
        time.sleep(1)  # Optional: Sleep to avoid rate limits
    except Exception as e:
        print(f"Error processing article ID {row['ID']}: {e}")

print("All embeddings are stored in the vector database.")


Vous verrez ci-dessous les logs des embeddings créés.

JournauxCapture d’écran de Google Cloud Console, décembre 2024

4. Recherche d’un article correspondant à un mot-clé à l’aide de Google Vertex AI

Faisons maintenant la même recherche de mots-clés avec Vertex AI. Il y a une petite nuance : vous devez utiliser « RETRIEVAL_QUERY » plutôt que « RETRIEVAL_DOCUMENT » comme argument lors de la génération d’embeddings de mots-clés, car nous essayons de rechercher un article (ou un document) qui correspond le mieux à notre phrase.

Types de tâches sont l’un des principaux avantages de Vertex AI par rapport aux modèles d’OpenAI.

Il garantit que les embeddings capturent l’intention des mots-clés, ce qui est important pour les liens internes, et améliore la pertinence et la précision des correspondances trouvées dans votre base de données vectorielle.

Utilisez ce script pour faire correspondre les mots-clés aux vecteurs.


import os
import pandas as pd
from google.cloud import aiplatform
from google.auth import load_credentials_from_file
from google.api_core.exceptions import ServiceUnavailable
from vertexai.language_models import TextEmbeddingModel

from pinecone import Pinecone
from tabulate import tabulate  # For table formatting

# Set up your Google Cloud credentials
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "config.json"  # Replace with your JSON key file
credentials, project_id = load_credentials_from_file(os.environ["GOOGLE_APPLICATION_CREDENTIALS"])

# Initialize Pinecone client
pinecone = Pinecone(api_key='YOUR_PINECON_API_KEY')  # Add your Pinecone API key
index_name = "article-index-vertex"  # Replace with your Pinecone index name
index = pinecone.Index(index_name)

# Initialize Vertex AI
aiplatform.init(project=project_id, credentials=credentials, location="us-central1")

def generate_embeddings(
    text: str,
    model_id: str = "text-embedding-005"
) -> list:
    """
    Generates embeddings for the input text using Google Vertex AI's embedding model.
    Returns None if text is empty or an error occurs.
    """
    if not text or not text.strip():
        print("Text input is empty. Skipping.")
        return None

    try:
        model = TextEmbeddingModel.from_pretrained(model_id)
        vector = model.get_embeddings([text])  # Removed 'task_type' and 'output_dimensionality'
        return vector[0].values
    except ServiceUnavailable as e:
        print(f"Vertex AI service is unavailable: {e}")
        return None
    except Exception as e:
        print(f"Error generating embeddings: {e}")
        return None


def match_keywords_to_index(keywords):
    """
    Matches a list of keyword-category pairs to the closest articles in the Pinecone index,
    filtering by metadata if specified.
    """
    results = []

    for keyword_pair in keywords:
        keyword = keyword_pair[0]
        category = keyword_pair[1]

        try:
            keyword_vector = generate_embeddings(keyword)

            if not keyword_vector:
                print(f"No embedding generated for keyword '{keyword}' in category '{category}'.")
                results.append({
                    'Keyword': keyword,
                    'Category': category,
                    'Match Score': 'Error/Empty',
                    'Title': 'No match',
                    'URL': 'N/A'
                })
                continue

            query_results = index.query(
                vector=keyword_vector,
                top_k=1,
                include_metadata=True,
                filter={"category": category}
            )

            if query_results['matches']:
                closest_match = query_results['matches'][0]
                results.append({
                    'Keyword': keyword,
                    'Category': category,
                    'Match Score': f"{closest_match['score']:.2f}",
                    'Title': closest_match['metadata'].get('title', 'N/A'),
                    'URL': closest_match['id']
                })
            else:
                results.append({
                    'Keyword': keyword,
                    'Category': category,
                    'Match Score': 'N/A',
                    'Title': 'No match found',
                    'URL': 'N/A'
                })

        except Exception as e:
            print(f"Error processing keyword '{keyword}' with category '{category}': {e}")
            results.append({
                'Keyword': keyword,
                'Category': category,
                'Match Score': 'Error',
                'Title': 'Error occurred',
                'URL': 'N/A'
            })

    return results

# Example usage: 
keywords = [["SEO Tools", "Tools"], ["TikTok", "TikTok"], ["SEO Consultant", "SEO"]]

matches = match_keywords_to_index(keywords)

# Display the results in a table
print(tabulate(matches, headers="keys", tablefmt="fancy_grid"))


Et vous verrez les scores générés :

Scores de correspondance de mots-clés produits par le modèle d'intégration de texte de Vertex AIScores de correspondance de mots-clés produits par le modèle d’intégration de texte de Vertex AI

Testez la pertinence de vos articles

Il s’agit d’un moyen simplifié (large) de vérifier la similarité sémantique de votre texte avec le mot-clé principal. Créez une intégration vectorielle de votre mot-clé de tête et le contenu entier de l’article via l’IA Vertex de Google et calculer une similarité en cosinus.

Si votre texte est trop long, vous devrez peut-être envisager de mettre en œuvre la fonction des stratégies de découpage.

    Un score proche de 1,0 (comme 0,8 ou 0,7). signifie que vous êtes assez proche sur ce sujet. Si votre score est plus faible, il se peut qu’une introduction trop longue, avec beaucoup d’éléments superficiels, entraîne une dilution de la pertinence et que le fait de la supprimer contribue à l’augmenter.

    Mais n’oubliez pas que toute modification apportée doit être judicieuse du point de vue de la rédaction et de l’expérience de l’utilisateur.

    Vous pouvez même procéder à une comparaison rapide en intégrant le contenu bien classé d’un concurrent et en vous comparant à lui.

    Cela vous permet d’aligner plus précisément votre contenu sur le sujet ciblé, ce qui peut vous aider à mieux vous classer.

    Il existe déjà des outils qui effectuent de telles tâchesmais l’acquisition de ces compétences vous permettra d’adopter une approche personnalisée adaptée à vos besoins et, bien sûr, de le faire gratuitement.

    Expérimenter par vous-même et acquérir ces compétences vous aidera à garder une longueur d’avance en matière d’IA SEO et à prendre des décisions éclairées.

    En guise de lectures complémentaires, je vous recommande de vous plonger dans ces excellents articles :

    Plus de ressources :


    Image en vedette : Aozorastock/Shutterstock

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *