SingleStoreは、幅広いビジネスユースケースをサポートするために設計された強力なマルチモデルデータベースシステムおよびプラットフォームです。その特長的な機能により、企業は複数のデータベースシステムを単一のプラットフォームに統合し、総所有コスト(TCO)を削減し、複雑な統合ツールの必要性を排除することで、開発者のワークフローを簡素化できます。
本記事では、SingleStoreがWeb解析会社の電子メールキャンペーンを変革し、パーソナライズされた高精度な電子メールコンテンツの作成を可能にする方法について探っていきます。
記事で使用されているノートブックファイルは、GitHubで入手可能です。
はじめに
Web解析会社は顧客との関係を築くために電子メールキャンペーンを活用しています。しかし、顧客をターゲットにするための一般的なアプローチでは、ビジネスの潜在能力を最大限に活用する機会を逃してしまうことがよくあります。より効果的な解決策は、大規模言語モデル(LLM)を使用してパーソナライズされた電子メールメッセージを作成することです。
ユーザーの行動データがMongoDBなどのNoSQLデータベースに格納されている一方で、貴重な文書はPineconeなどのベクトルデータベースに存在していると考えてください。これらの複数のシステムを管理することは複雑でリソースが多く必要とされることがあり、統合された解決策の必要性を浮き彫りにします。
SingleStoreは多目的なマルチモデルデータベースで、JSONを含むさまざまなデータ形式をサポートし、組み込みのベクトル関数を提供しています。LLMsとシームレスに統合され、複数のデータベースシステムを管理する強力な代替手段となります。この記事では、SingleStoreがMongoDBとPineconeの両方を簡素化し、機能性を損なうことなく置き換える方法を示します。
この例のアプリケーションでは、LLMを使用して顧客向けのユニークな電子メールを生成します。LLMが顧客をターゲットする方法を学習するために、複数の有名な分析会社をLLMの学習資料として使用します。
さらに、ユーザーの行動に基づいてコンテンツをカスタマイズします。顧客データはMongoDBに格納されます。ユーザーの行動の異なる段階はPineconeに格納されます。ユーザーの行動により、LLMはパーソナライズされた電子メールを生成することができます。最後に、SingleStoreを使用してMongoDBとPineconeに格納されているデータを統合します。
SingleStore Cloudアカウントを作成します
以前の記事では、無料のSingleStore Cloudアカウントを作成する手順が示されています。Standard Tierを使用し、Workspace GroupとWorkspaceのデフォルト名を使用します。また、SingleStore Kaiを有効にします。
OpenAI APIキーとPinecone APIキーを秘密のボールトにOPENAI_API_KEY
とPINECONE_API_KEY
を使用して格納します。
ノートブックをインポートします
GitHubからノートブックをダウンロードします。
SingleStoreクラウドポータルの左側のナビゲーションペインから、「DEVELOP」>「Data Studio」を選択します。
ウェブページの右上部で、「New Notebook」>「Import From File」を選択します。GitHubからダウンロードしたノートブックをインポートするためにウィザードを使用します。
ノートブックを実行します。
汎用メールテンプレート
まず、汎用の電子メールテンプレートを生成し、それをLLMを使用して各顧客向けのパーソナライズされたメッセージに変換します。これにより、各受信者の名前でアプローチし、Web分析プラットフォームの利点を紹介できます。
以下のようにして汎用の電子メールを生成できます:
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)
例えば、Aliceは次のメッセージを見ることになります:
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
}
)
例えば、これが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
他のユーザーにも同様にユニークなメールが生成されます。
3. ユーザーの行動に応じた電子メールコンテンツのカスタマイズ
ユーザーの行動段階に基づいてユーザーをカテゴリ分けすることで、特定のニーズに合わせたEメールコンテンツをさらにカスタマイズできます。 LLMは、異なる段階を進行するユーザーを促進するためのEメール作成を支援し、最終的にはさまざまなサービスの理解と使用を向上させます。
現在、ユーザーデータは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にEメールをさらにカスタマイズするよう依頼します:
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
}
)
たとえば、次はMichael向けに生成されたEメールです:
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. Eメールコンテンツのさらなるカスタマイズ
ユーザーの進捗をサポートするために、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にEメールをさらにカスタマイズするよう依頼できます:
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
}
)
たとえば、次はMelissa向けに生成されたEメールです:
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.
一般的なテンプレートを洗練させ、ターゲットを絞ったEメールを開発しました。
SingleStoreを使用
別々のデータベースシステムを管理する代わりに、SingleStoreを使用して業務を効率化します。JSON、テキスト、ベクトル埋め込みをサポートしているため、すべての必要なデータを効率的に1か所に保存し、TCOを削減し、開発プロセスを簡素化できます。
次のようなパイプラインを使用して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>
を置換します。
顧客テーブルはパイプラインによって作成されます。行動段階のベクトル埋め込みは次のように作成できます:
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()
データを使用して、LLMに電子メールのカスタマイズを依頼します:
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,
}
)
たとえば、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.
概要
この実践的デモンストレーションを通じて、SingleStoreがマルチモデル機能とAI駆動のパーソナライゼーションにより、電子メールキャンペーンを改善する方法がわかりました。SingleStoreを真実の唯一の情報源として使用することで、ワークフローを簡素化し、電子メールキャンペーンが顧客に最大の影響と価値を提供することを確認しました。
謝辞
この記事用に適応されたオリジナルのデモコードを提供してくれたWes Kennedyに感謝します。
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app