Generazione di annunci avanzati con intelligenza artificiale con Azure Cosmos DB per vCore MongoDB
In questa guida viene illustrato come creare contenuto pubblicitario dinamico che riecheggia il pubblico usando l'assistente per l'intelligenza artificiale personalizzato, Heelie. Usando Azure Cosmos DB per MongoDB vCore, vengono sfruttate le funzionalità di ricerca di somiglianza vettoriale per analizzare e associare semanticamente le descrizioni dell'inventario agli argomenti degli annunci pubblicitari. Il processo è reso possibile generando vettori per le descrizioni dell'inventario usando incorporamenti OpenAI, che migliorano significativamente la loro profondità semantica. Questi vettori vengono quindi archiviati e indicizzati all'interno della risorsa vCore di Cosmos DB per MongoDB. Quando si generano contenuti per annunci pubblicitari, si vettorizza l'argomento dell'annuncio per trovare gli articoli di inventario corrispondenti migliori. Questo è seguito da un processo di generazione aumentata (RAG) di recupero, in cui le prime corrispondenze vengono inviate a OpenAI per creare un annuncio accattivante. L'intera codebase per l'applicazione è disponibile in un repository GitHub per riferimento.
Funzionalità
- Ricerca di somiglianza vettoriale: usa la potente ricerca di somiglianza vettoriale di Azure Cosmos DB per MongoDB vCore per migliorare le funzionalità di ricerca semantica, semplificando la ricerca degli elementi di inventario pertinenti in base al contenuto degli annunci pubblicitari.
- Incorporamenti OpenAI: usa gli incorporamenti all'avanguardia di OpenAI per generare vettori per le descrizioni dell'inventario. Questo approccio consente corrispondenze più sfumate e semanticamente avanzate tra l'inventario e il contenuto dell'annuncio.
- Generazione di contenuti: usa i modelli linguistici avanzati di OpenAI per generare annunci coinvolgenti incentrati sulle tendenze. Questo metodo garantisce che il contenuto non solo sia rilevante, ma anche accattivante per il pubblico di destinazione.
Prerequisiti
Azure OpenAI: configurare la risorsa OpenAI di Azure. L'accesso a questo servizio è attualmente disponibile solo per l'applicazione. È possibile richiedere l'accesso a OpenAI di Azure completando il modulo all'indirizzo https://aka.ms/oai/access. Dopo aver ottenuto l'accesso, completare la procedura seguente:
- Creare una risorsa OpenAI di Azure seguendo questa guida introduttiva.
- Distribuire un
completions
e unembeddings
modello - Prendere nota dei nomi di endpoint, chiave e distribuzione.
Risorsa vCore di Cosmos DB per MongoDB: per iniziare, creare una risorsa vCore di Azure Cosmos DB per MongoDB gratuitamente seguendo questa guida introduttiva .
- Prendere nota dei dettagli della connessione (stringa di connessione).
Ambiente Python (>= 3.9 versione) con pacchetti come
numpy
,azure-core
openai
python-dotenv
azure-cosmos
pymongo
,tenacity
, e .gradio
Scaricare il file di dati e salvarlo in una cartella di dati designata.
Esecuzione dello script
Prima di approfondire la parte interessante della generazione di annunci avanzati con intelligenza artificiale, è necessario configurare l'ambiente. Questa configurazione comporta l'installazione dei pacchetti necessari per garantire che lo script venga eseguito senza problemi. Ecco una guida dettagliata per preparare tutto.
1.1 Installare i pacchetti necessari
In primo luogo, è necessario installare alcuni pacchetti Python. Aprire il terminale ed eseguire i comandi seguenti:
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 Configurazione di OpenAI e client di Azure
Dopo aver installato i pacchetti necessari, il passaggio successivo prevede la configurazione dei client OpenAI e Azure per lo script, fondamentale per l'autenticazione delle richieste all'API OpenAI e ai servizi di 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
)
Architettura della soluzione
2. Creazione di incorporamenti e configurazione di Cosmos DB
Dopo aver configurato l'ambiente e il client OpenAI, passiamo alla parte principale del progetto di generazione di annunci avanzati con intelligenza artificiale. Il codice seguente crea incorporamenti vettoriali da descrizioni di testo dei prodotti e configura il database in Azure Cosmos DB per MongoDB vCore per archiviare e cercare questi incorporamenti.
2.1 Creare incorporamenti
Per generare annunci accattivanti, è prima necessario comprendere gli articoli nell'inventario. A questo scopo, creiamo incorporamenti vettoriali dalle descrizioni degli elementi, che ci consente di acquisire il loro significato semantico in una forma che i computer possono comprendere ed elaborare. Ecco come creare incorporamenti vettoriali per una descrizione di un elemento usando Azure 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 funzione accetta un input di testo, ad esempio una descrizione del prodotto, e usa il client.embeddings.create
metodo dell'API OpenAI per generare un incorporamento vettoriale per tale testo. In questo caso viene usato il text-embedding-ada-002
modello, ma è possibile scegliere altri modelli in base alle esigenze. Se il processo ha esito positivo, stampa gli incorporamenti generati; in caso contrario, gestisce le eccezioni stampando un messaggio di errore.
3. Connettersi e configurare Cosmos DB per mongoDB vCore
Con gli incorporamenti pronti, il passaggio successivo consiste nell'archiviarli e indicizzarli in un database che supporta la ricerca di somiglianza vettoriale. Azure Cosmos DB per MongoDB vCore è ideale per questa attività perché è progettato per archiviare i dati transazionali ed eseguire ricerche vettoriali in un'unica posizione.
3.1 Configurare la connessione
Per connettersi a Cosmos DB, si usa la libreria pymongo, che consente di interagire facilmente con MongoDB. Il frammento di codice seguente stabilisce una connessione con l'istanza vCore di Cosmos DB per MongoDB:
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)
Sostituire <USERNAME>
, <PASSWORD>
e <VCORE_CLUSTER_NAME>
con il nome effettivo del cluster MongoDB, password e vCore rispettivamente.
4. Configurazione del database e dell'indice vettoriale in Cosmos DB
Dopo aver stabilito una connessione ad Azure Cosmos DB, i passaggi successivi implicano la configurazione del database e della raccolta e quindi la creazione di un indice vettoriale per abilitare ricerche efficienti di somiglianza vettoriale. Esaminiamo questi passaggi.
4.1 Configurare il database e la raccolta
Creare prima di tutto un database e una raccolta all'interno dell'istanza di Cosmos DB. Esegui la procedura seguente:
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 Creare l'indice vettoriale
Per eseguire ricerche efficienti di somiglianza vettoriale all'interno della raccolta, è necessario creare un indice vettoriale. Cosmos DB supporta diversi tipi di indici vettoriali e di seguito vengono illustrati due: IVF e HNSW.
IVF
IVF è l'acronimo di Inverted File Index, è l'algoritmo di indicizzazione vettoriale predefinito, che funziona su tutti i livelli del cluster. Si tratta di un approccio approssimativo dei vicini più vicini (ANN) che usa il clustering per velocizzare la ricerca di vettori simili in un set di dati. Per creare un indice IVF, usare il comando seguente:
db.command({
'createIndexes': COLLECTION_NAME,
'indexes': [
{
'name': 'vectorSearchIndex',
'key': {
"contentVector": "cosmosSearch"
},
'cosmosSearchOptions': {
'kind': 'vector-ivf',
'numLists': 1,
'similarity': 'COS',
'dimensions': 1536
}
}
]
});
Importante
È possibile creare un solo indice per proprietà vettoriale. Ciò significa che non è possibile creare più indici che puntano alla stessa proprietà vettoriale. Se si desidera modificare il tipo di indice , ad esempio da IVF a HNSW, è necessario eliminare l'indice prima di creare un nuovo indice.
HNSW
HNSW è l'acronimo di Hierarchical Navigable Small World, una struttura di dati basata su grafo che suddivide i vettori in cluster e sottocluster. Con HNSW, è possibile eseguire una ricerca rapida e approssimativa del vicino più prossimo, a velocità più elevate e con maggiore precisione. HNSW è un metodo approssimativo (ANN). Ecco come eseguire la configurazione:
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
}
}
]
}
)
Nota
L'indicizzazione HNSW è disponibile solo nei livelli del cluster M40 e versioni successive.
5. Inserire i dati nella raccolta
Inserire ora i dati di inventario, che includono descrizioni e incorporamenti vettoriali corrispondenti, nella raccolta appena creata. Per inserire dati nella raccolta, viene usato il insert_many()
metodo fornito dalla pymongo
libreria. Il metodo consente di inserire più documenti nella raccolta contemporaneamente. I dati vengono archiviati in un file JSON, che verrà caricato e quindi inserito nel database.
Scaricare il file shoes_with_vectors.json dal repository GitHub e archiviarlo in una data
directory all'interno della cartella del progetto.
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. Ricerca vettoriale in Cosmos DB per MongoDB vCore
Dopo il caricamento dei dati, è ora possibile applicare la potenza della ricerca vettoriale per trovare gli elementi più rilevanti in base a una query. L'indice vettoriale creato in precedenza consente di eseguire ricerche semantiche all'interno del set di dati.
6.1 Esecuzione di una ricerca vettoriale
Per eseguire una ricerca vettoriale, viene definita una funzione vector_search
che accetta una query e il numero di risultati da restituire. La funzione genera un vettore per la query usando la generate_embeddings
funzione definita in precedenza, quindi usa la funzionalità di $search
Cosmos DB per trovare gli elementi corrispondenti più vicini in base ai relativi incorporamenti vettoriali.
# 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 Eseguire una query di ricerca vettoriale
Infine, si esegue la funzione di ricerca vettoriale con una query specifica ed elabora i risultati per visualizzarli:
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. Generazione di contenuti pubblicitari con GPT-4 e DALL. E
Combinamo tutti i componenti sviluppati per creare annunci accattivanti, impiegando GPT-4 di OpenAI per testo e DALL· E 3 per le immagini. Insieme ai risultati della ricerca vettoriale, formano un annuncio completo. Introduciamo anche Heelie, il nostro assistente intelligente, con l'incarico di creare tagline pubblicitarie coinvolgenti. Tramite il codice successivo, vedrai Heelie in azione, migliorando il processo di creazione degli annunci.
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. Mettere tutto insieme
Per rendere interattiva la generazione di annunci pubblicitari, si usa Gradio, una libreria Python per la creazione di interfacce utente Web semplici. Definiamo un'interfaccia utente che consente agli utenti di inserire argomenti pubblicitari e quindi genera e visualizza dinamicamente l'annuncio risultante.
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()