SingleStore היא מערכת מסד נתונים רב-דגמית ופלטפורמה עוצמתית המיועדת לתמוך במגוון רחב של מקרי שימוש עסקיים. תכונות הבולטות שלה מאפשרות לעסקים לאחד מערכות מסד נתונים מרובות לתוך פלטפורמה אחת, מה שמפחית את עלות הרכישה הכוללת (TCO) ומפשטת את תהליכי העבודה של מפתחים על ידי הסרת צורך בכלים מורכבים לאינטגרציה.
במאמר זה, נבחן איך SingleStore יכולה לשנות את קמפייני האימייל עבור חברת ניתוח אינטרנט, ולאפשר יצירת תוכן אימייל אישי וממוקד מאוד.
קובץ המחברת שהועשה שימוש בו במאמר זמין ב־GitHub.
הקדמה
חברת ניתוח אינטרנט מתירה על קמפייני אימייל כדי להיות בקשר עם לקוחות. אך גישה גנרית לקידום לקוחות לעתים קרובות מוּשפָּכת הזדמנויות למקסם את הפוטנציאל העסקי. פתרון יעיל יותר היה כולל ביצור הודעות אימייל אישיות באמצעות מודל שפה גדול (LLM).
שקול תרחיש שבו נתוני התנהגות המשתמש מאוחסנים במסד נתונים NoSQL כמו MongoDB, בעוד התיעוד המועיל מתגורר במסד נתונים וקטורי, כמו Pinecone. ניהול של מערכות מרובות אלה יכול להפוך למורכב ולאכזב ממשאבים, ומדגיש את הצורך בפתרון מאוחד.
SingleStore, מסד נתונים רב דטה ורסטילי, תומך בפורמטים שונים של נתונים, כולל JSON, ומציע פונקציות וקטור מובנות. הוא משתלב בקלות עם LLMs, מה שהופך אותו לאלטרנטיבה חזקה לניהול מערכות מסד נתונים מרובות. במאמר זה, נדגים כיצד SingleStore יכול בקלות להחליף את MongoDB ו-Pinecone, ולפשט פעולות מבלי לפגוע בפונקציונליות.
באפליקצית הדוגמה שלנו, נשתמש ב-LLM כדי ליצור כתובות דוא"ל ייחודיות עבור לקוחותינו. כדי לעזור ל-LLM ללמוד כיצד לקבוץ את לקוחותינו, נשתמש במספר חברות ניתוח ידועות כחומר לימוד ל-LLM.
נתאים תוכן נוסף בהתאמה להתנהגות המשתמש. נתוני הלקוחות מאוחסנים ב-MongoDB. שלבים שונים של התנהגות המשתמש מאוחסנים ב-Pinecone. התנהגות המשתמש תאפשר ל-LLM ליצור דואות אישיות. לבסוף, נאחד את הנתונים שמאוחסנים ב-MongoDB וב-Pinecone באמצעות SingleStore.
צור חשבון ענן ב-SingleStore
מאמר קודם הראה את השלבים ליצירת חשבון ענן ב-SingleStore בחינם. נשתמש ב-טייר סטנדרטי ונקח את השמות הברירת מחדל לקבוצת המרחב ולמרחב. נאפשר גם את SingleStore Kai.
נאחסן את מפתח ה- API של OpenAI ואת מפתח ה- API של Pinecone ב-קספולת הסודות באמצעות OPENAI_API_KEY
ו־PINECONE_API_KEY
בהתאמה.
ייבא את המחברת
נוריד את המחברת מ-GitHub.
מהחלון הניווט השמאלי בפורטל הענן של SingleStore, נבחר "DEVELOP" > "Data Studio."
בפינה הימנית העליונה של דף האינטרנט, נבחר "New Notebook" > "Import From File." נשתמש בווייזרד כדי לאתר ולייבא את המחברת שהורדנו מ-GitHub.
הרץ את המחברת
תבנית דוא"ל גנרית
נתחיל ביצירת תבניות דוא"ל גנריות ולאחר מכן נשתמש ב-LLM כדי להפוך אותן להודעות מותאמות אישית עבור כל לקוח. כך נוכל לפנות לכל נמען בשמו ולהציג לו את היתרונות של פלטפורמת ניתוח האינטרנט שלנו.
נוכל ליצור דוא"ל גנרי כך:
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)
לדוגמה, אליס תראה את ההודעה הבאה:
Hey Alice,
Check out our web analytics platform, it's Awesome!
It's perfect for your needs. Buy it now!
- Marketer John
משתמשים אחרים יקבלו את אותה הודעה, אבל עם שמם, בהתאמה.
2. הוספת מודל שפה גדול (LLM)
נוכל בקלות להביא LLM לאפליקציה שלנו על ידי מתן תפקיד ואספקת מידע כלשהו, כך:
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.
"""
ניצור פונקציה לקרוא ל-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
חזרה ברשימת המשתמשים וקוראת ל-LLM מייצרת דוא"ל ייחודיים:
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
}
)
לדוגמה, כך זה מה שאליס עשויה לראות:
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
דוא"ל ייחודי באותה מידה ייוצר עבור שאר המשתמשים.
3. התאמת תוכן הדוא"ל בהתבסס על התנהגות המשתמש
בעל ידי סיווג משתמשים בהתאם לשלבי ההתנהגות שלהם, נוכל להתאים עוד יותר את תוכן המיילים כדי להתאים לצרכים הספציפיים שלהם. LLM יסייע ביצירת מיילים שמעודדים משתמשים להתקדם בין שלבים שונים, ובסופו של דבר לשפר את ההבנה והשימוש שלהם בשירותים שונים.
כעת, נתוני המשתמשים מאוחסנים במסד נתונים של MongoDB עם מבנה רשומות דומה למפורט להלן:
{
'_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
}
נחבר ל-MongoDB כדי לקבל את הנתונים כפי שמפורט להלן:
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)
נחליף את <password>
ואת <host>
עם הערכים מ-MongoDB Atlas.
יש לנו מספר שלבי התנהגות של משתמשים:
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]
באמצעות הנתונים על שלבי ההתנהגות, נבקש מה-LLM להתאים עוד יותר את המייל כך:
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
}
)
לדוגמה, הנה מייל שנוצר עבור מייקל:
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. התאמת תוכן המיילים עוד יותר
כדי לתמוך בהתקדמות המשתמש, נשתמש בהטמעות הווקטוריות של Pinecone, מה שיאפשר לנו להנחות את המשתמשים לתיעוד רלוונטי לכל שלב. ההטמעות הללו מקלות את ההנחיה של המשתמשים לעבר משאבים חיוניים ומביאות לשיפור נוסף באינטראקציות שלהם עם המוצר שלנו.
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()
ניצור את ההטמעות כפי שמפורט להלן:
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
נחפש ב-Pinecone עבור התאמות כך:
def search_pinecone(embedding):
match = pc_index.query(
vector = [embedding],
top_k = 1,
include_metadata = True
)["matches"][0]["metadata"]
return match["content"], match["parent"]
באמצעות הנתונים, נוכל לבקש מה-LLM להתאים עוד יותר את המייל, כך:
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
}
)
לדוגמה, הנה מייל שנוצר עבור מליסה:
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.
אנחנו רואים שהצלחנו לחדד את התבנית הכללית ולפתח מיילים ממוקדים מאוד.
באמצעות SingleStore
במקום לנהל מערכות מסד נתונים נפרדות, נקל שורת הפעולה שלנו על ידי שימוש ב-SingleStore. עם תמיכתו ב-JSON, טקסט ו- vector embeddings, אנו יכולים לאחסן ביעילות את כל המידע הדרוש במקום אחד, מה שמוריד את עלות הבעלות ומפשט את תהליכי הפיתוח שלנו.
ניבא את הנתונים מ-MongoDB באמצעות צינור עבודה דומה לזה הבא:
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;
נחליף <primary>
, <secondary>
, <secondary>
ו- <password>
עם הערכים מ-MongoDB Atlas.
טבלת הלקוח תיווצר על ידי הצינור. ה-vector embeddings לשלבי ההתנהגות ניתן ליצור כך:
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)
נצטרך טבלה לאחסן את הנתונים:
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
);
לאחר מכן, נוכל לשמור את הנתונים בטבלה:
df.to_sql(
"docs_splits",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
נחפש ב-SingleStore להתאמות כך:
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()
על ידי הנתונים, נוכל לבקש מ-LMM להתאים אישית את האימייל כך:
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,
}
)
לדוגמה, הנה אימייל שנוצר עבור יוסף:
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.
סיכום
דרך הדגמה המעשית הזו, ראינו כיצד SingleStore משפר את קמפייני האימייל שלנו עם יכולות הרב-מודל וההתאמה האישית באמצעות AI. בשימוש ב-SingleStore כמקור האמת היחיד שלנו, הפשטנו את זרימות העבודה שלנו והבטחנו כי קמפייני האימייל שלנו מספקים תועלת וערך מקסימליים ללקוחותינו.
תודות
אני מודה ל-Wes Kennedy על קוד הדמו המקורי, שהתאים למאמר זה.
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app