SingleStore est un puissant système de base de données multi-modèles et une plateforme conçue pour prendre en charge une grande variété de cas d’utilisation commerciale. Ses fonctionnalités distinctives permettent aux entreprises de unifier plusieurs systèmes de base de données en une seule plateforme, réduisant ainsi le coût total de possession (TCO) et simplifiant les flux de travail des développeurs en éliminant le besoin d’outils d’intégration complexes.
Dans cet article, nous explorerons comment SingleStore peut transformer les campagnes d’email pour une entreprise d’analyse web, permettant la création de contenu d’email personnalisé et hautement ciblé.
Le fichier notebook utilisé dans l’article est disponible sur GitHub.
Introduction
Une entreprise d’analyse web s’appuie sur des campagnes d’email pour interagir avec les clients. Cependant, une approche générique pour cibler les clients manque souvent d’opportunités pour maximiser le potentiel commercial. Une solution plus efficace consisterait à utiliser un grand modèle linguistique (LLM) pour créer des messages d’email personnalisés.
Considérez un scénario où les données de comportement des utilisateurs sont stockées dans une base de données NoSQL comme MongoDB, tandis que des documents précieux résident dans une base de données vectorielle, telle que Pinecone. Gérer ces multiples systèmes peut devenir complexe et gourmand en ressources, soulignant le besoin d’une solution unifiée.
SingleStore, une base de données multi-modèle polyvalente, prend en charge divers formats de données, y compris JSON, et offre des fonctions vectorielles intégrées. Il s’intègre parfaitement avec les LLMs, ce qui en fait une alternative puissante à la gestion de plusieurs systèmes de bases de données. Dans cet article, nous allons démontrer comment SingleStore peut facilement remplacer à la fois MongoDB et Pinecone, simplifiant les opérations sans compromettre la fonctionnalité.
Dans notre application exemple, nous utiliserons un LLM pour générer des e-mails uniques pour nos clients. Pour aider le LLM à apprendre comment cibler nos clients, nous utiliserons plusieurs sociétés d’analyse bien connues comme matériel d’apprentissage pour le LLM.
Nous personnaliserons davantage le contenu en fonction du comportement de l’utilisateur. Les données clients sont stockées dans MongoDB. Différentes étapes du comportement de l’utilisateur sont stockées dans Pinecone. Le comportement de l’utilisateur permettra au LLM de générer des e-mails personnalisés. Enfin, nous consoliderons les données stockées dans MongoDB et Pinecone en utilisant SingleStore.
Créer un compte SingleStore Cloud
Un article précédent a montré les étapes pour créer un compte Cloud SingleStore gratuit. Nous utiliserons le niveau Standard et prendrons les noms par défaut pour le Groupe de l’Espace de travail et l’Espace de travail. Nous activerons également SingleStore Kai.
Nous stockerons notre clé API OpenAI et notre clé API Pinecone dans le coffre-fort de secrets en utilisant OPENAI_API_KEY
et PINECONE_API_KEY
, respectivement.
Importer le Notebook
Nous allons télécharger le cahier depuis GitHub.
Dans le volet de navigation de gauche du portail cloud SingleStore, nous allons sélectionner « DÉVELOPPER » > « Studio de données. »
En haut à droite de la page web, nous allons sélectionner « Nouveau cahier » > « Importer depuis un fichier. » Nous utiliserons l’assistant pour localiser et importer le cahier que nous avons téléchargé depuis GitHub.
Exécuter le cahier
Modèle d’email générique
Nous commencerons par générer des modèles d’email génériques, puis utiliserons un LLM pour les transformer en messages personnalisés pour chaque client. De cette façon, nous pouvons adresser chaque destinataire par son nom et les introduire aux avantages de notre plateforme d’analyse web.
Nous pouvons générer un email générique comme suit:
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)
Par exemple, Alice verrait le message suivant:
Hey Alice,
Check out our web analytics platform, it's Awesome!
It's perfect for your needs. Buy it now!
- Marketer John
D’autres utilisateurs recevraient le même message, mais avec leur nom respectif.
2. Ajout d’un Grand Modèle de Langue (LLM)
Nous pouvons facilement intégrer un LLM dans notre application en lui fournissant un rôle et en lui donnant quelques informations, comme suit:
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.
"""
Nous allons créer une fonction pour appeler le 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
En parcourant la liste des utilisateurs et en appelant le LLM, des emails uniques sont produits:
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
}
)
Par exemple, voici ce qu’Alice pourrait voir:
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
Des emails tout aussi uniques seront générés pour les autres utilisateurs.
3. Personnalisation du Contenu de l’Email Selon le Comportement de l’Utilisateur
En catégorisant les utilisateurs en fonction de leurs étapes de comportement, nous pouvons personnaliser davantage le contenu de l’e-mail pour répondre à leurs besoins spécifiques. Un LLM aidera à créer des e-mails qui encouragent les utilisateurs à progresser à travers différentes étapes, améliorant ainsi leur compréhension et leur utilisation des différents services.
Actuellement, les données des utilisateurs sont stockées dans une base de données MongoDB avec une structure d’enregistrement similaire à ce qui suit :
{
'_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
}
Nous nous connecterons à MongoDB pour obtenir les données comme suit :
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)
Nous remplacerons <password>
et <host>
par les valeurs de MongoDB Atlas.
Nous avons plusieurs étapes de comportement des utilisateurs :
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]
En utilisant les données sur les étapes de comportement, nous demanderons au LLM de personnaliser davantage l’e-mail comme suit :
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
}
)
Par exemple, voici un e-mail généré pour 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. Personnalisation supplémentaire du contenu de l’e-mail
Pour soutenir la progression des utilisateurs, nous utiliserons les plongements vectoriels de Pinecone, nous permettant de diriger les utilisateurs vers la documentation pertinente pour chaque étape. Ces plongements facilitent le guidage des utilisateurs vers les ressources essentielles et améliorent encore leurs interactions avec notre produit.
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()
Nous créerons les plongements comme suit :
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
Nous rechercherons des correspondances dans Pinecone comme suit :
def search_pinecone(embedding):
match = pc_index.query(
vector = [embedding],
top_k = 1,
include_metadata = True
)["matches"][0]["metadata"]
return match["content"], match["parent"]
En utilisant les données, nous pouvons demander au LLM de personnaliser davantage l’e-mail, comme suit :
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
}
)
Par exemple, voici un e-mail généré pour 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.
Nous pouvons voir que nous avons affiné le modèle générique et développé des e-mails très ciblés.
Utilisation de SingleStore
Au lieu de gérer des systèmes de base de données séparés, nous simplifierons nos opérations en utilisant SingleStore. Avec son support pour JSON, le texte et les embeddings vectoriels, nous pouvons stocker efficacement toutes les données nécessaires en un seul endroit, réduisant les coûts totaux de possession et simplifiant nos processus de développement.
Nous ingérerons les données de MongoDB en utilisant un pipeline similaire au suivant :
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;
Nous remplacerons <primary>
, <secondary>
, <secondary>
et <password>
par les valeurs de MongoDB Atlas.
La table des clients sera créée par le pipeline. Les embeddings vectoriels pour les étapes de comportement peuvent être créés comme suit :
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)
Nous aurons besoin d’une table pour stocker les données :
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
);
Ensuite, nous pouvons sauvegarder les données dans la table :
df.to_sql(
"docs_splits",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
Nous rechercherons des correspondances dans SingleStore comme suit :
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()
En utilisant les données, nous pouvons demander au LLM de personnaliser l’e-mail comme suit :
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,
}
)
Par exemple, voici un e-mail généré pour 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.
Résumé
À travers cette démonstration pratique, nous avons vu comment SingleStore améliore nos campagnes d’e-mails avec ses capacités multi-modèles et sa personnalisation basée sur l’IA. En utilisant SingleStore comme notre unique source de vérité, nous avons simplifié nos flux de travail et nous assurons que nos campagnes d’e-mails offrent un impact maximal et une valeur à nos clients.
Remerciements
Je remercie Wes Kennedy pour le code de démonstration original, qui a été adapté pour cet article.
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app