SingleStore – мощная многомодельная система баз данных и платформа, разработанная для поддержки широкого спектра бизнес-кейсов. Ее характерные особенности позволяют бизнесу объединить несколько систем баз данных в единую платформу, снизить общую стоимость владения (TCO) и упростить рабочие процессы разработчиков, устраняя необходимость в сложных интеграционных инструментах.
В этой статье мы рассмотрим, как SingleStore может преобразить электронные рассылки для веб-аналитической компании, обеспечивая создание персонализированного и высокоточного контента для электронных писем.
Файл блокнота, используемый в статье, доступен на GitHub.
Введение
Веб-аналитическая компания полагается на электронные рассылки для взаимодействия с клиентами. Однако общий подход к таргетингу клиентов часто упускает возможности для максимизации бизнес-потенциала. Более эффективным решением было бы использование большой языковой модели (LLM) для создания персонализированных электронных сообщений.
Представим ситуацию, где данные о поведении пользователей хранятся в базе данных NoSQL, такой как MongoDB, в то время как ценные документы находятся в векторной базе данных, например, Pinecone. Управление этими множественными системами может стать сложным и ресурсоемким, подчеркивая необходимость в едином решении.
SingleStore, универсальная многомодельная база данных, поддерживает различные форматы данных, включая JSON, и предлагает встроенные векторные функции. Он без проблем интегрируется с LLM, делая его мощной альтернативой управлению несколькими системами баз данных. В этой статье мы продемонстрируем, насколько легко SingleStore может заменить как MongoDB, так и Pinecone, упрощая операции без ущерба функциональности.
В нашем примере приложения мы будем использовать LLM для генерации уникальных электронных писем для наших клиентов. Чтобы помочь LLM научиться целенаправленно обращаться к нашим клиентам, мы будем использовать несколько известных аналитических компаний в качестве учебного материала для LLM.
Мы также настроим контент на основе поведения пользователей. Данные клиентов хранятся в MongoDB. Различные этапы поведения пользователя хранятся в Pinecone. Поведение пользователя позволит LLM генерировать персонализированные электронные письма. Наконец, мы объединим данные, хранящиеся в MongoDB и Pinecone, используя SingleStore.
Создайте учетную запись в облаке SingleStore
В предыдущей статье показаны шаги по созданию бесплатной учетной записи в облаке SingleStore. Мы будем использовать Стандартный уровень и оставим имена по умолчанию для Группы Рабочих Пространств и Рабочего Пространства. Мы также включим SingleStore Kai.
Мы сохраняем наши ключи API OpenAI и 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, текста и векторных вложений, мы можем эффективно хранить все необходимые данные в одном месте, снижая общую стоимость владения и упрощая процессы разработки.
Мы будем загружать данные из 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.
Таблица клиентов будет создана конвейером. Векторные вложения для стадий поведения могут быть созданы следующим образом:
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,
}
)
Например, вот электронное письмо, сгенерированное для Джозефа:
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 улучшает наши электронные кампании благодаря своим возможностям мульти-моделирования и персонализации на основе искусственного интеллекта. Используя SingleStore в качестве нашего единственного источника правды, мы упростили наши рабочие процессы и обеспечили, что наши электронные кампании доставляют максимальный эффект и ценность нашим клиентам.
Благодарности
Я благодарю Веса Кеннеди за оригинальный демонстрационный код, адаптированный для этой статьи.
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app