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èleembeddings
. - 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
etgradio
. - 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 :
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.
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
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 :
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 :
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 :
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 :
db.runCommand({
'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 :
db.runCommand(
{
"createIndexes": "ExampleCollection",
"indexes": [
{
"name": "VectorSearchIndex",
"key": {
"contentVector": "cosmosSearch"
},
"cosmosSearchOptions": {
"kind": "vector-hnsw",
"m": 16, # default value
"efConstruction": 64, # default value
"similarity": "COS",
"dimensions": 1536
}
}
]
}
)
Remarque
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.
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.
6.1 Effectuer une recherche vectorielle
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.
# 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 :
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.
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.
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()