SingleStore è un potente sistema di database multi-modello e piattaforma progettata per supportare una vasta gamma di casi d’uso aziendali. Le sue caratteristiche distintive consentono alle aziende di unificare più sistemi di database in una singola piattaforma, riducendo il Costo Totale di Possesso (TCO) e semplificando i flussi di lavoro degli sviluppatori eliminando la necessità di strumenti di integrazione complessi.
In questo articolo, esploreremo come SingleStore possa trasformare le campagne email per una società di analisi web, consentendo la creazione di contenuti email personalizzati e altamente mirati.
Il file del notebook utilizzato nell’articolo è disponibile su GitHub.
Introduzione
Una società di analisi web si affida alle campagne email per coinvolgere i clienti. Tuttavia, un approccio generico al targeting dei clienti spesso perde opportunità per massimizzare il potenziale commerciale. Una soluzione più efficace coinvolgerebbe l’uso di un grande modello linguistico (LLM) per creare messaggi email personalizzati.
Consideriamo uno scenario in cui i dati relativi al comportamento degli utenti sono memorizzati in un database NoSQL come MongoDB, mentre preziosa documentazione risiede in un database vettoriale, come Pinecone. Gestire questi sistemi multipli può diventare complesso e intensivo dal punto di vista delle risorse, evidenziando la necessità di una soluzione unificata.
SingleStore, un database multi-modello versatile, supporta vari formati di dati, inclusi JSON, e offre funzioni vettoriali integrate. Si integra senza soluzione di continuità con LLM, rendendolo un’alternativa potente per gestire più sistemi di database. In questo articolo, dimostreremo quanto sia facile per SingleStore sostituire sia MongoDB che Pinecone, semplificando le operazioni senza compromettere la funzionalità.
Nella nostra applicazione di esempio, utilizzeremo un LLM per generare email uniche per i nostri clienti. Per aiutare il LLM a imparare come mirare ai nostri clienti, utilizzeremo diverse aziende di analisi ben note come materiale didattico per il LLM.
Personalizzeremo ulteriormente i contenuti in base al comportamento dell’utente. I dati dei clienti sono memorizzati in MongoDB. Diverse fasi del comportamento dell’utente sono memorizzate in Pinecone. Il comportamento dell’utente permetterà al LLM di generare email personalizzate. Infine, consolideremo i dati memorizzati in MongoDB e Pinecone utilizzando SingleStore.
Crea un Account SingleStore Cloud
Un articolo precedente ha mostrato i passaggi per creare un account gratuito SingleStore Cloud. Utilizzeremo il Livello Standard e useremo i nomi predefiniti per il Gruppo Spazio di Lavoro e lo Spazio di Lavoro. Abiliteremo anche SingleStore Kai.
Memorizzeremo la nostra chiave API di OpenAI e la chiave API di Pinecone nella riserva segreta utilizzando rispettivamente OPENAI_API_KEY
e PINECONE_API_KEY
.
Importa il Notebook
Scaricheremo il notebook da GitHub.
Dal riquadro di navigazione a sinistra nel portale cloud di SingleStore, selezioneremo “SVILUPPA” > “Data Studio.”
Nell’angolo in alto a destra della pagina web, selezioneremo “Nuovo Notebook” > “Importa Da File.” Utilizzeremo la procedura guidata per individuare e importare il notebook scaricato da GitHub.
Eseguire il Notebook
Modello Email Generico
Inizieremo generando modelli di email generiche e poi utilizzeremo un LLM per trasformarle in messaggi personalizzati per ciascun cliente. In questo modo, possiamo rivolgerci a ciascun destinatario per nome e presentargli i vantaggi della nostra piattaforma di analisi web.
Possiamo generare un’email generica come segue:
people = ["Alice", "Bob", "Charlie", "David", "Emma"]
for person in people:
message = (
f"Hey {person},\n"
"Check out our web analytics platform, it's Awesome!\n"
"It's perfect for your needs. Buy it now!\n"
"- Marketer John"
)
print(message)
print("_" * 100)
Ad esempio, Alice vedrebbe il seguente messaggio:
Hey Alice,
Check out our web analytics platform, it's Awesome!
It's perfect for your needs. Buy it now!
- Marketer John
Gli altri utenti riceverebbero lo stesso messaggio, ma con il loro nome rispettivamente.
2. Aggiunta di un Modello di Linguaggio Ampio (LLM)
Possiamo facilmente integrare un LLM nella nostra applicazione fornendogli un ruolo e fornendogli alcune informazioni, come segue:
system_message = """
You are a helpful assistant.
My name is Marketer John.
You help write the body of an email for a fictitious company called 'Awesome Web Analytics'.
This is a web analytics company that is similar to the top 5 web analytics companies (perform a web search to determine the current top 5 web analytics companies).
The goal is to write a custom email to users to get them interested in our services.
The email should be less than 150 words.
Address the user by name.
End with my signature.
"""
Creeremo una funzione per chiamare il LLM:
def chatgpt_generate_email(prompt, person):
conversation = [
{"role": "system", "content": prompt},
{"role": "user", "content": person},
{"role": "assistant", "content": ""}
]
response = openai_client.chat.completions.create(
model = "gpt-4o-mini",
messages = conversation,
temperature = 1.0,
max_tokens = 800,
top_p = 1,
frequency_penalty = 0,
presence_penalty = 0
)
assistant_reply = response.choices[0].message.content
return assistant_reply
Scorrendo l’elenco degli utenti e chiamando il LLM si generano email uniche:
openai_client = OpenAI()
# Define a list to store the responses
emails = []
# Loop through each person and generate the conversation
for person in people:
email = chatgpt_generate_email(system_message, person)
emails.append(
{
"person": person,
"assistant_reply": email
}
)
Ad esempio, questo è ciò che potrebbe vedere Alice:
Person: Alice
Subject: Unlock Your Website's Potential with Awesome Web Analytics!
Hi Alice,
Are you ready to take your website to new heights? At Awesome Web Analytics, we provide cutting-edge insights that empower you to make informed decisions and drive growth.
With our powerful analytics tools, you can understand user behavior, optimize performance, and boost conversions—all in real-time! Unlike other analytics platforms, we offer personalized support to guide you every step of the way.
Join countless satisfied customers who have transformed their online presence. Discover how we stack up against competitors like Google Analytics, Adobe Analytics, and Matomo, but with a focus on simplicity and usability.
Let us help you turn data into your greatest asset!
Best,
Marketer John
Awesome Web Analytics
Saranno generate email altrettanto uniche per gli altri utenti.
3. Personalizzazione del Contenuto dell’Email Con il Comportamento dell’Utente
Classificando gli utenti in base alle fasi del comportamento, possiamo ulteriormente personalizzare i contenuti delle email per allinearli alle loro esigenze specifiche. Un LLM assisterà nella creazione di email che incoraggiano gli utenti a progredire attraverso diverse fasi, migliorando in definitiva la loro comprensione e utilizzo di vari servizi.
Attualmente, i dati degli utenti sono memorizzati in un database MongoDB con una struttura del record simile alla seguente:
{
'_id': ObjectId('64afb3fda9295d8421e7a19f'),
'first_name': 'James',
'last_name': 'Villanueva',
'company_name': 'Foley-Turner',
'stage': 'generating a tracking code',
'created_date': 1987-11-09T12:43:26.000+00:00
}
Ci collegheremo a MongoDB per ottenere i dati nel seguente modo:
try:
mongo_client = MongoClient("mongodb+srv://admin:<password>@<host>/?retryWrites=true&w=majority")
mongo_db = mongo_client["mktg_email_demo"]
collection = mongo_db["customers"]
print("Connected successfully")
except Exception as e:
print(e)
Sostituiremo <password>
e <host>
con i valori da MongoDB Atlas.
Abbiamo diverse fasi del comportamento degli utenti:
stages = [
"getting started",
"generating a tracking code",
"adding tracking to your website",
"real-time analytics",
"conversion tracking",
"funnels",
"user segmentation",
"custom event tracking",
"data export",
"dashboard customization"
]
def find_next_stage(current_stage):
current_index = stages.index(current_stage)
if current_index < len(stages) - 1:
return stages[current_index + 1]
else:
return stages[current_index]
Utilizzando i dati sulle fasi del comportamento, chiederemo all’LLM di personalizzare ulteriormente l’email nel seguente modo:
limit = 5
emails = []
for record in collection.find(limit = limit):
fname, stage = record.get("first_name"), record.get("stage")
next_stage = find_next_stage(stage)
system_message = f"""
You are a helpful assistant, who works for me, Marketer John at Awesome Web Analytics.
You help write the body of an email for a fictitious company called 'Awesome Web Analytics'.
We are a web analytics company similar to the top 5 web analytics companies.
We have users at various stages in our product's pipeline, and we want to send them helpful emails to encourage further usage of our product.
Please write an email for {fname} who is on stage {stage} of the onboarding process.
The next stage is {next_stage}.
Ensure the email describes the benefits of moving to the next stage.
Limit the email to 1 paragraph.
End the email with my signature.
"""
email = chatgpt_generate_email(system_message, fname)
emails.append(
{
"fname": fname,
"stage": stage,
"next_stage": next_stage,
"email": email
}
)
Ad esempio, ecco un’email generata per Michael:
First Name: Michael
Stage: funnels
Next Stage: user segmentation
Subject: Unlock Deeper Insights with User Segmentation!
Hi Michael,
Congratulations on successfully navigating the funnel stage of our onboarding process! As you move forward to user segmentation, you'll discover how this powerful tool will enable you to categorize your users based on their behaviors and demographics. By understanding your audience segments better, you can create tailored experiences that increase engagement and optimize conversions. This targeted approach not only enhances your marketing strategies but also drives meaningful results and growth for your business. We're excited to see how segmentation will elevate your analytics efforts!
Best,
Marketer John
Awesome Web Analytics
4. Personalizzazione Ulteriore dei Contenuti delle Email
Per supportare il progresso dell’utente, utilizzeremo gli embedding vettoriali di Pinecone, permettendoci di indirizzare gli utenti alla documentazione rilevante per ciascuna fase. Questi embedding rendono semplice guidare gli utenti verso risorse essenziali e migliorare ulteriormente le loro interazioni con il nostro prodotto.
pc = Pinecone(
api_key = pc_api_key
)
index_name = "mktg-email-demo"
if any(index["name"] == index_name for index in pc.list_indexes()):
pc.delete_index(index_name)
pc.create_index(
name = index_name,
dimension = dimensions,
metric = "euclidean",
spec = ServerlessSpec(
cloud = "aws",
region = "us-east-1"
)
)
pc_index = pc.Index(index_name)
pc.list_indexes()
Creeremo gli embedding nel seguente modo:
def get_embeddings(text):
text = text.replace("\n", " ")
try:
response = openai_client.embeddings.create(
input = text,
model = "text-embedding-3-small"
)
return response.data[0].embedding, response.usage.total_tokens, "success"
except Exception as e:
print(e)
return "", 0, "failed"
id_counter = 1
ids_list = []
for stage in stages:
embedding, tokens, status = get_embeddings(stage)
parent = id_counter - 1
pc_index.upsert([
{
"id": str(id_counter),
"values": embedding,
"metadata": {"content": stage, "parent": str(parent)}
}
])
ids_list.append(str(id_counter))
id_counter += 1
Cercheremo corrispondenze in Pinecone nel seguente modo:
def search_pinecone(embedding):
match = pc_index.query(
vector = [embedding],
top_k = 1,
include_metadata = True
)["matches"][0]["metadata"]
return match["content"], match["parent"]
Utilizzando i dati, possiamo chiedere all’LLM di personalizzare ulteriormente l’email, nel seguente modo:
limit = 5
emails = []
for record in collection.find(limit = limit):
fname, stage = record.get("first_name"), record.get("stage")
# Get the current and next stages with their embedding
this_stage = next((item for item in stages_w_embed if item["stage"] == stage), None)
next_stage = next((item for item in stages_w_embed if item["stage"] == find_next_stage(stage)), None)
if not this_stage or not next_stage:
continue
# Get content
cur_content, cur_permalink = search_pinecone(this_stage["embedding"])
next_content, next_permalink = search_pinecone(next_stage["embedding"])
system_message = f"""
You are a helpful assistant.
I am Marketer John at Awesome Web Analytics.
We are similar to the current top web analytics companies.
We have users at various stages of using our product, and we want to send them helpful emails to encourage them to use our product more.
Write an email for {fname}, who is on stage {stage} of the onboarding process.
The next stage is {next_stage['stage']}.
Ensure the email describes the benefits of moving to the next stage, and include this link: https://github.com/VeryFatBoy/mktg-email-flow/tree/main/docs/{next_content.replace(' ', '-')}.md.
Limit the email to 1 paragraph.
End the email with my signature: 'Best Regards, Marketer John.'
"""
email = chatgpt_generate_email(system_message, fname)
emails.append(
{
"fname": fname,
"stage": stage,
"next_stage": next_stage["stage"],
"email": email
}
)
Ad esempio, ecco un’email generata per Melissa:
First Name: Melissa
Stage: getting started
Next Stage: generating a tracking code
Subject: Take the Next Step with Awesome Web Analytics!
Hi Melissa,
We're thrilled to see you getting started on your journey with Awesome Web Analytics! The next step is generating your tracking code, which will allow you to start collecting valuable data about your website visitors. With this data, you can gain insights into user behavior, optimize your marketing strategies, and ultimately drive more conversions. To guide you through this process, check out our detailed instructions here: [Generating a Tracking Code](https://github.com/VeryFatBoy/mktg-email-flow/tree/main/docs/generating-a-tracking-code.md). We're here to support you every step of the way!
Best Regards,
Marketer John.
Possiamo vedere che abbiamo perfezionato il modello generico e sviluppato email piuttosto mirate.
Utilizzando SingleStore
Invece di gestire sistemi di database separati, ottimizzeremo le nostre operazioni utilizzando SingleStore. Con il supporto per JSON, testo e incorporamenti vettoriali, possiamo memorizzare in modo efficiente tutti i dati necessari in un unico posto, riducendo il TCO e semplificando i nostri processi di sviluppo.
Ingeriremo i dati da MongoDB utilizzando un pipeline simile al seguente:
USE mktg_email_demo;
CREATE LINK mktg_email_demo.link AS MONGODB
CONFIG '{"mongodb.hosts": "<primary>:27017, <secondary>:27017, <secondary>:27017",
"collection.include.list": "mktg_email_demo.*",
"mongodb.ssl.enabled": "true",
"mongodb.authsource": "admin",
"mongodb.members.auto.discover": "false"}'
CREDENTIALS '{"mongodb.user": "admin",
"mongodb.password": "<password>"}';
CREATE TABLES AS INFER PIPELINE AS LOAD DATA LINK mktg_email_demo.link '*' FORMAT AVRO;
START ALL PIPELINES;
Sostituiremo <primary>
, <secondary>
, <secondary>
e <password>
con i valori da MongoDB Atlas.
La tabella dei clienti sarà creata dal pipeline. Gli incorporamenti vettoriali per le fasi di comportamento possono essere creati come segue:
df_list = []
id_counter = 1
for stage in stages:
embedding, tokens, status = get_embeddings(stage)
parent = id_counter - 1
stage_df = pd.DataFrame(
{
"id": [id_counter],
"content": [stage],
"embedding": [embedding],
"parent": [parent]
}
)
df_list.append(stage_df)
id_counter += 1
df = pd.concat(df_list, ignore_index = True)
Averemo bisogno di una tabella per memorizzare i dati:
USE mktg_email_demo;
DROP TABLE IF EXISTS docs_splits;
CREATE TABLE IF NOT EXISTS docs_splits (
id INT,
content TEXT,
embedding VECTOR(:dimensions),
parent INT
);
Successivamente, possiamo salvare i dati nella tabella:
df.to_sql(
"docs_splits",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
Cercheremo corrispondenze in SingleStore come segue:
def search_s2(vector):
query = """
SELECT content, parent
FROM docs_splits
ORDER BY (embedding <-> :vector) ASC
LIMIT 1
"""
with db_connection.connect() as con:
result = con.execute(text(query), {"vector": str(vector)})
return result.fetchone()
Utilizzando i dati, possiamo chiedere al LLM di personalizzare l’email come segue:
limit = 5
emails = []
# Create a connection
with db_connection.connect() as con:
query = "SELECT _more :> JSON FROM customers LIMIT :limit"
result = con.execute(text(query), {"limit": limit})
for customer in result:
customer_data = customer[0]
fname, stage = customer_data["first_name"], customer_data["stage"]
# Retrieve current and next stage embeddings
this_stage = next((item for item in stages_w_embed if item["stage"] == stage), None)
next_stage = next((item for item in stages_w_embed if item["stage"] == find_next_stage(stage)), None)
if not this_stage or not next_stage:
continue
# Get content
cur_content, cur_permalink = search_s2(this_stage["embedding"])
next_content, next_permalink = search_s2(next_stage["embedding"])
# Create the system message
system_message = f"""
You are a helpful assistant.
I am Marketer John at Awesome Web Analytics.
We are similar to the current top web analytics companies.
We have users that are at various stages in using our product, and we want to send them helpful emails to get them to use our product more.
Write an email for {fname} who is on stage {stage} of the onboarding process.
The next stage is {next_stage['stage']}.
Ensure the email describes the benefits of moving to the next stage, then always share this link: https://github.com/VeryFatBoy/mktg-email-flow/tree/main/docs/{next_content.replace(' ', '-')}.md.
Limit the email to 1 paragraph.
End the email with my signature: 'Best Regards, Marketer John.'
"""
email = chatgpt_generate_email(system_message, fname)
emails.append(
{
"fname": fname,
"stage": stage,
"next_stage": next_stage["stage"],
"email": email,
}
)
Ad esempio, ecco un’email generata per Joseph:
First Name: Joseph
Stage: generating a tracking code
Next Stage: adding tracking to your website
Subject: Take the Next Step in Your Analytics Journey!
Hi Joseph,
Congratulations on generating your tracking code! The next step is to add tracking to your website, which is crucial for unlocking the full power of our analytics tools. By integrating the tracking code, you will start collecting valuable data about your visitors, enabling you to understand user behavior, optimize your website, and drive better results for your business. Ready to get started? Check out our detailed guide here: [Adding Tracking to Your Website](https://github.com/VeryFatBoy/mktg-email-flow/tree/main/docs/adding-tracking-to-your-website.md).
Best Regards,
Marketer John.
Riepilogo
Attraverso questa dimostrazione pratica, abbiamo visto come SingleStore migliorare le nostre campagne email con le sue capacità multi-modello e personalizzazione basata sull’IA. Utilizzando SingleStore come nostra unica fonte di verità, abbiamo semplificato i nostri flussi di lavoro e garantito che le nostre campagne email offrano massimo impatto e valore ai nostri clienti.
Riconoscimenti
Ringrazio Wes Kennedy per il codice demo originale, adattato per questo articolo.
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app