Lire en anglais

Partager via


Génération d’annonces améliorée par l’IA à l’aide d’Azure Cosmos DB for MongoDB vCore

Dans ce guide, nous démontrons comment créer du contenu publicitaire dynamique qui trouve un écho parmi votre public en utilisant Heelie, notre assistant AI personnalisé. Grâce à l’utilisation d’Azure Cosmos DB for MongoDB vCore, nous exploitons la fonctionnalité de recherche de similarité vectorielle pour analyser et faire correspondre des descriptions d’inventaire aux sujets publicitaires. Le processus est rendu possible via la génération de vecteurs pour des descriptions d’inventaire en tirant parti des incorporations OpenAI, ce qui améliore de manière significative leur profondeur sémantique. Ces vecteurs sont ensuite stockés et indexés au sein de la ressource Cosmos DB for MongoDB vCore. Lors de la génération du contenu pour les publicités, nous vectorisons le sujet publicitaire pour trouver les meilleurs éléments d’inventaire correspondants. Cette opération est suivie d’un processus de génération augmentée de récupération (RAG) quand les principales correspondances sont envoyées à OpenAI pour élaborer une publicité innovante. Le codebase complet pour l’application est disponible dans un référentiel GitHub pour votre référence.

Fonctionnalités

  • Recherche de similarité vectorielle : utilise la puissante recherche de similarité vectorielle d’Azure Cosmos DB for MongoDB vCore pour améliorer les fonctionnalités de recherche sémantique, ce qui facilite la recherche d’éléments d’inventaire pertinents en fonction du contenu des publicités.
  • Incorporations OpenAI : utilise les incorporations de pointe d’OpenAI pour générer des vecteurs pour les descriptions d’inventaire. Cette approche permet d’obtenir des correspondances enrichies sémantiquement et plus nuancées entre l’inventaire et le contenu publicitaire.
  • Génération de contenu : emploie les modèles de langage avancés d’OpenAI pour générer des publicités intéressantes et axées sur les tendances. Cette méthode veille à ce que le contenu soit non seulement pertinent, mais aussi captivant pour le public cible.

Prérequis

  • Azure OpenAI : nous allons configurer la ressource Azure OpenAI. L’accès à ce service n’est actuellement disponible que par application uniquement. Vous pouvez demander l’accès à Azure OpenAI en complétant le formulaire à l’adresse https://aka.ms/oai/access. Une fois que vous avez accès, effectuez les étapes suivantes :
    • Créez une ressource Azure OpenAI en suivant ce démarrage rapide.
    • Déployez un modèle completions et un modèle embeddings.
      • Pour obtenir plus d’informations sur les completions, accédez ici.
      • Pour obtenir plus d’informations sur les embeddings, accédez ici.
    • Notez le nom de votre point de terminaison, de votre clé et de votre déploiement.
  • Ressource Cosmos DB for MongoDB vCore : commençons par créer une ressource Azure Cosmos DB for MongoDB vCore gratuitement en suivant ce guide de démarrage rapide.
    • Notez les détails de la connexion.
  • Environnement Python (>= version 3.9) avec des packages tels que numpy, openai, pymongo, python-dotenv, azure-core, azure-cosmos, tenacity et gradio.
  • Téléchargez le fichier de données et enregistrez-le dans un dossier de données désigné.

Exécution du script

Avant de nous lancer dans la partie intéressante de la génération de publicités améliorées par l’IA, nous devons configurer notre environnement. Cette configuration implique l’installation des packages nécessaires pour veiller à ce que notre script fonctionne sans problème. Voici un guide pas à pas pour tout préparer.

1.1. Installer les packages nécessaires

Nous devons d’abord installer quelques packages Python. Ouvrez votre terminal et exécutez les commandes suivantes :

Bash
 pip install numpy
 pip install openai==1.2.3
 pip install pymongo
 pip install python-dotenv
 pip install azure-core
 pip install azure-cosmos
 pip install tenacity
 pip install gradio
 pip show openai

1.2 Configuration des clients Azure et OpenAI

Après l’installation des packages nécessaires, l’étape suivante implique la configuration de nos clients OpenAI et Azure pour le script, ce qui est essentiel pour l’authentification de nos demandes aux services d’API OpenAI et d’Azure.

Python
import json
import time
import openai

from dotenv import dotenv_values
from openai import AzureOpenAI

# Configure the API to use Azure as the provider
openai.api_type = "azure"
openai.api_key = "<AZURE_OPENAI_API_KEY>"  # Replace with your actual Azure OpenAI API key
openai.api_base = "https://<OPENAI_ACCOUNT_NAME>.openai.azure.com/"  # Replace with your OpenAI account name
openai.api_version = "2023-06-01-preview"

# Initialize the AzureOpenAI client with your API key, version, and endpoint
client = AzureOpenAI(
    api_key=openai.api_key,
    api_version=openai.api_version,
    azure_endpoint=openai.api_base
)

Architecture de solution

architecture de la solution

2. Création d’incorporations et configuration de Cosmos DB

Après la configuration de notre environnement et du client OpenAI, nous passons à la partie centrale de notre projet de génération d’une publicité améliorée par l’IA. Le code suivant crée des incorporations vectorielles à partir de descriptions textuelles de produits et configure notre base de données dans Azure Cosmos DB for MongoDB vCore pour stocker et rechercher ces incorporations.

2.1 Créer des incorporations

Pour générer des publicités innovantes, nous devons d’abord comprendre les éléments de notre inventaire. Nous effectuons ceci en créant des incorporations vectorielles à partir des descriptions de nos éléments, ce qui nous permet de capturer leur signification sémantique sous une forme que les machines peuvent comprendre et traiter. Voici comment vous pouvez créer des incorporations vectorielles pour une description d’élément en tirant parti d’OpenAI :

Python
import openai

def generate_embeddings(text):
    try:
        response = client.embeddings.create(
            input=text, model="text-embedding-ada-002")
        embeddings = response.data[0].embedding
        return embeddings
    except Exception as e:
        print(f"An error occurred: {e}")
        return None

embeddings = generate_embeddings("Shoes for San Francisco summer")

if embeddings is not None:
    print(embeddings)

La fonction récupère une entrée de texte, telle qu’une description de produit, et utilise la méthode client.embeddings.create de l’API OpenAI afin de générer une incorporation vectorielle pour ce texte. Nous utilisons le modèle text-embedding-ada-002 ici, mais vous pouvez choisir d’autres modèles basés sur vos besoins. Si le processus est une réussite, il imprime les incorporations générées. Sinon, il gère les exceptions en imprimant un message d’erreur.

3. Connecter et configurer Azure Cosmos DB for MongoDB vCore

Une fois nos incorporations prêtes, l’étape suivante consiste à les stocker et les indexer dans une base de données qui prend en charge la recherche de similarité vectorielle. Azure Cosmos DB for MongoDB vCore est idéal pour cette tâche, car il est spécialement conçu pour stocker vos données transactionnelles et effectuer une recherche vectorielle au même endroit.

3.1 Configurer la connexion

Pour la connexion à Cosmos DB, nous utilisons la bibliothèque pymongo qui nous permet d’interagir facilement avec MongoDB. L’extrait de code suivant établit une connexion à notre instance Cosmos DB for MongoDB vCore :

Python
import pymongo

# Replace <USERNAME>, <PASSWORD>, and <VCORE_CLUSTER_NAME> with your actual credentials and cluster name
mongo_conn = "mongodb+srv://<USERNAME>:<PASSWORD>@<VCORE_CLUSTER_NAME>.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000"
mongo_client = pymongo.MongoClient(mongo_conn)

Remplacez <USERNAME>, <PASSWORD> et <VCORE_CLUSTER_NAME> par votre nom d’utilisateur MongoDB, mot de passe et nom de cluster vCore réels, respectivement.

4. Configuration de la base de données et de l’index vectoriel dans Cosmos DB

Une fois la connexion à Azure Cosmos DB établie, l’étape suivante implique la configuration de votre base de données et de la collection, puis la création d’un index vectoriel pour activer un nombre de recherches de similarité vectorielle suffisant. Examinons ces étapes en détail.

4.1 Configurer la base de données et la collection

Nous créons d’abord une base de données et une collection au sein de notre instance Cosmos DB. Voici comment :

Python
DATABASE_NAME = "AdgenDatabase"
COLLECTION_NAME = "AdgenCollection"

mongo_client.drop_database(DATABASE_NAME)
db = mongo_client[DATABASE_NAME]
collection = db[COLLECTION_NAME]

if COLLECTION_NAME not in db.list_collection_names():
    # Creates a unsharded collection that uses the DBs shared throughput
    db.create_collection(COLLECTION_NAME)
    print("Created collection '{}'.\n".format(COLLECTION_NAME))
else:
    print("Using collection: '{}'.\n".format(COLLECTION_NAME))

4.2 Créer un index vectoriel

Pour effectuer des recherches de similarité vectorielle efficaces dans notre collection, nous devons créer un index vectoriel. Cosmos DB prend en charge différents types d’index vectoriels et nous en évoquons deux ici : IVF et HNSW.

IVF

IVF est l’acronyme d’Inverted File Index (Index de fichier inversé). Il constitue l’algorithme d’indexation vectorielle par défaut qui fonctionne sur tous les niveaux de cluster. Il s’agit d’une approche des plus proches voisins approximatifs (ANN) qui utilise le clustering pour accélérer la recherche de vecteurs similaires dans un jeu de données. Pour créer un index IVF, utilisez la commande suivante :

JavaScript
db.command({
  'createIndexes': COLLECTION_NAME,
  'indexes': [
    {
      'name': 'vectorSearchIndex',
      'key': {
        "contentVector": "cosmosSearch"
      },
      'cosmosSearchOptions': {
        'kind': 'vector-ivf',
        'numLists': 1,
        'similarity': 'COS',
        'dimensions': 1536
      }
    }
  ]
});

Important

Vous ne pouvez créer qu’un seul index par propriété vectorielle. C’est-à-dire que vous ne pouvez pas créer plus d’un index qui pointe vers la même propriété vectorielle. Si vous souhaitez modifier le type d’index (par exemple, passer d’IVF à HNSW), vous devez annuler l’index en premier avant de créer un index.

HNSW

HNSW signifie Hierarchical Navigable Small World. Il s’agit d’une structure de données basée sur des graphiques qui partitionne des vecteurs en clusters et sous-clusters. Avec HNSW, vous pouvez effectuer une recherche approximative rapide du plus proche voisin à des vitesses plus élevées avec plus d’exactitude. HNSW est une méthode approximative (ANN). Voici comment le configurer :

JavaScript
db.command(
{ 
    "createIndexes": "ExampleCollection",
    "indexes": [
        {
            "name": "VectorSearchIndex",
            "key": {
                "contentVector": "cosmosSearch"
            },
            "cosmosSearchOptions": { 
                "kind": "vector-hnsw", 
                "m": 16, # default value 
                "efConstruction": 64, # default value 
                "similarity": "COS", 
                "dimensions": 1536
            } 
        } 
    ] 
}
)

Note

L’indexation HNSW est uniquement disponible sur le niveau de cluster M40 et supérieur.

5. Insérer des données à une collection

Insérez maintenant les données d’inventaire, qui incluent des descriptions et leurs incorporations vectorielles correspondantes, dans la collection nouvellement créée. Pour insérer des données dans notre collection, nous utilisons la méthode insert_many() fournie par la bibliothèque pymongo. La méthode nous permet d’insérer plusieurs documents à la fois dans la collection. Nos données sont stockées dans un fichier JSON que nous chargeons, puis insérons dans la base de données.

Téléchargez le fichier shoes_with_vectors.json du référentiel GitHub et stockez-le dans un répertoire data au sein du dossier de votre projet.

Python
data_file = open(file="./data/shoes_with_vectors.json", mode="r") 
data = json.load(data_file)
data_file.close()

result = collection.insert_many(data)

print(f"Number of data points added: {len(result.inserted_ids)}")

6. Recherche vectorielle dans Cosmos DB for MongoDB vCore

Une fois nos données correctement chargées, nous pouvons maintenant appliquer la puissance de la recherche vectorielle pour trouver les éléments les plus pertinents en fonction d’une requête. L’index vectoriel créé plus tôt nous permet d’effectuer des recherches sémantiques au sein de notre jeu de données.

Pour effectuer une recherche vectorielle, nous définissons une fonction vector_search qui prend une requête et le nombre de résultats à retourner. La fonction génère un vecteur pour la requête en utilisant la fonction generate_embeddings définie plus tôt, puis utilise la fonctionnalité $search de Cosmos DB pour trouver les éléments correspondants les plus proches en fonction de leurs incorporations vectorielles.

Python
# Function to assist with vector search
def vector_search(query, num_results=3):
    
    query_vector = generate_embeddings(query)

    embeddings_list = []
    pipeline = [
        {
            '$search': {
                "cosmosSearch": {
                    "vector": query_vector,
                    "numLists": 1,
                    "path": "contentVector",
                    "k": num_results
                },
                "returnStoredSource": True }},
        {'$project': { 'similarityScore': { '$meta': 'searchScore' }, 'document' : '$$ROOT' } }
    ]
    results = collection.aggregate(pipeline)
    return results

6.2 Effectuer une requête de recherche vectorielle

Enfin, nous exécutons notre fonction de recherche vectorielle avec une requête spécifique et traitons les résultats pour les afficher :

Python
query = "Shoes for Seattle sweater weather"
results = vector_search(query, 3)

print("\nResults:\n")
for result in results: 
    print(f"Similarity Score: {result['similarityScore']}")  
    print(f"Title: {result['document']['name']}")  
    print(f"Price: {result['document']['price']}")  
    print(f"Material: {result['document']['material']}") 
    print(f"Image: {result['document']['img_url']}") 
    print(f"Purchase: {result['document']['purchase_url']}\n")

7. Génération de contenu publicitaire avec GPT-4 et DALL.E

Nous associons tous les composants développés pour élaborer des publicités innovantes, en employant GPT-4 d’OpenAI pour le texte et DALL E 3 pour les images. Conjugués aux résultats de la recherche vectorielle, ils forment une publicité complète. Nous introduisons également Heelie, notre assistant intelligent, chargé de créer des slogans publicitaires intéressants. Via le code à venir, vous voyez Heelie en action qui améliorer notre processus de création publicitaire.

Python
from openai import OpenAI

def generate_ad_title(ad_topic):
    system_prompt = '''
    You are Heelie, an intelligent assistant for generating witty and cativating tagline for online advertisement.
        - The ad campaign taglines that you generate are short and typically under 100 characters.
    '''

    user_prompt = f'''Generate a catchy, witty, and short sentence (less than 100 characters) 
                    for an advertisement for selling shoes for {ad_topic}'''
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt},
    ]

    response = client.chat.completions.create(
        model="gpt-4",
        messages=messages
    )
    
    return response.choices[0].message.content

def generate_ad_image(ad_topic):
    daliClient = OpenAI(
        api_key="<DALI_API_KEY>"
    )

    image_prompt = f'''
        Generate a photorealistic image of an ad campaign for selling {ad_topic}. 
        The image should be clean, with the item being sold in the foreground with an easily identifiable landmark of the city in the background.
        The image should also try to depict the weather of the location for the time of the year mentioned.
        The image should not have any generated text overlay.
    '''

    response = daliClient.images.generate(
        model="dall-e-3",
        prompt= image_prompt,
        size="1024x1024",
        quality="standard",
        n=1,
        )

    return response.data[0].url

def render_html_page(ad_topic):

    # Find the matching shoes from the inventory
    results = vector_search(ad_topic, 4)
    
    ad_header = generate_ad_title(ad_topic)
    ad_image_url = generate_ad_image(ad_topic)


    with open('./data/ad-start.html', 'r', encoding='utf-8') as html_file:
        html_content = html_file.read()

    html_content += f'''<header>
            <h1>{ad_header}</h1>
        </header>'''    

    html_content += f'''
            <section class="ad">
            <img src="{ad_image_url}" alt="Base Ad Image" class="ad-image">
        </section>'''

    for result in results: 
        html_content += f''' 
        <section class="product">
            <img src="{result['document']['img_url']}" alt="{result['document']['name']}" class="product-image">
            <div class="product-details">
                <h3 class="product-title" color="gray">{result['document']['name']}</h2>
                <p class="product-price">{"$"+str(result['document']['price'])}</p>
                <p class="product-description">{result['document']['description']}</p>
                <a href="{result['document']['purchase_url']}" class="buy-now-button">Buy Now</a>
            </div>
        </section>
        '''

    html_content += '''</article>
                    </body>
                    </html>'''

    return html_content

8. Exemple complet

Pour rendre notre génération publicitaire interactive, nous employons Gradio, une bibliothèque Python pour créer des interfaces utilisateur web simples. Nous définissons une interface utilisateur qui permet aux utilisateurs d’entrer des sujets publicitaires, puis génère dynamiquement et affiche la publicité obtenue.

Python
import gradio as gr

css = """
    button { background-color: purple; color: red; }
    <style>
    </style>
"""

with gr.Blocks(css=css, theme=gr.themes.Default(spacing_size=gr.themes.sizes.spacing_sm, radius_size="none")) as demo:
    subject = gr.Textbox(placeholder="Ad Keywords", label="Prompt for Heelie!!")
    btn = gr.Button("Generate Ad")
    output_html = gr.HTML(label="Generated Ad HTML")

    btn.click(render_html_page, [subject], output_html)

    btn = gr.Button("Copy HTML")

if __name__ == "__main__":
    demo.launch()   

Sortie

Écran de sortie

Étape suivante