SingleStore é um poderoso sistema de banco de dados multi-modelo e plataforma projetada para suportar uma ampla variedade de casos de uso empresarial. Suas características distintas permitem que as empresas unifiquem múltiplos sistemas de banco de dados em uma única plataforma, reduzindo o Custo Total de Propriedade (TCO) e simplificando os fluxos de trabalho dos desenvolvedores ao eliminar a necessidade de ferramentas de integração complexas.
Neste artigo, exploraremos como o SingleStore pode transformar campanhas de e-mail para uma empresa de análise da web, possibilitando a criação de conteúdo de e-mail personalizado e altamente direcionado.
O arquivo de notebook usado no artigo está disponível no GitHub.
Introdução
Uma empresa de análise da web depende de campanhas de e-mail para se envolver com os clientes. No entanto, uma abordagem genérica para segmentar clientes frequentemente deixa de aproveitar oportunidades para maximizar o potencial de negócios. Uma solução mais eficaz envolveria o uso de um modelo de linguagem grande (LLM) para criar mensagens de e-mail personalizadas.
Considere um cenário em que dados de comportamento do usuário são armazenados em um banco de dados NoSQL como o MongoDB, enquanto documentação valiosa reside em um banco de dados vetorial, como o Pinecone. Gerenciar esses múltiplos sistemas pode se tornar complexo e intensivo em recursos, destacando a necessidade de uma solução unificada.
O SingleStore, um banco de dados multi-modelo versátil, suporta vários formatos de dados, incluindo JSON, e oferece funções de vetor integradas. Ele se integra perfeitamente com LLMs, tornando-se uma alternativa poderosa para gerenciar vários sistemas de banco de dados. Neste artigo, demonstraremos como o SingleStore pode substituir facilmente tanto o MongoDB quanto o Pinecone, simplificando operações sem comprometer a funcionalidade.
No nosso exemplo de aplicação, usaremos um LLM para gerar e-mails únicos para nossos clientes. Para ajudar o LLM a aprender como segmentar nossos clientes, usaremos várias empresas de análise bem conhecidas como material de aprendizagem para o LLM.
Vamos personalizar ainda mais o conteúdo com base no comportamento do usuário. Os dados do cliente são armazenados no MongoDB. Diferentes estágios do comportamento do usuário são armazenados no Pinecone. O comportamento do usuário permitirá que o LLM gere e-mails personalizados. Por fim, consolidaremos os dados armazenados no MongoDB e Pinecone usando o SingleStore.
Crie uma Conta na Nuvem do SingleStore
Um artigo anterior mostrou os passos para criar uma conta gratuita na Nuvem do SingleStore. Usaremos o Tier Padrão e manteremos os nomes padrão para o Grupo de Espaço de Trabalho e Espaço de Trabalho. Também ativaremos o SingleStore Kai.
Armazenaremos nossa Chave da API do OpenAI e a Chave da API do Pinecone no cofre de segredos usando OPENAI_API_KEY
e PINECONE_API_KEY
, respectivamente.
Importe o Notebook
Vamos baixar o caderno do GitHub.
No painel de navegação à esquerda no portal de nuvem do SingleStore, vamos selecionar “DESENVOLVER” > “Data Studio.”
No canto superior direito da página web, vamos selecionar “Novo Caderno” > “Importar do Arquivo.” Vamos usar o assistente para localizar e importar o caderno que baixamos do GitHub.
Executar o Caderno
Modelo Genérico de Email
Vamos começar gerando modelos genéricos de email e depois usar um LLM para transformá-los em mensagens personalizadas para cada cliente. Dessa forma, podemos abordar cada destinatário pelo nome e apresentá-los aos benefícios de nossa plataforma de análise web.
Podemos gerar um email genérico da seguinte maneira:
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)
Por exemplo, Alice veria a seguinte mensagem:
Hey Alice,
Check out our web analytics platform, it's Awesome!
It's perfect for your needs. Buy it now!
- Marketer John
Outros usuários receberiam a mesma mensagem, mas com seus respectivos nomes.
2. Adicionando um Grande Modelo de Linguagem (LLM)
Podemos facilmente incorporar um LLM em nossa aplicação fornecendo a ele uma função e fornecendo algumas informações, da seguinte forma:
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.
"""
Vamos criar uma função para chamar o 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
Percorrer a lista de usuários e chamar o LLM produz emails únicos:
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
}
)
Por exemplo, isso é o que Alice poderia ver:
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
Emails igualmente únicos serão gerados para os outros usuários.
3. Personalizando o Conteúdo do Email com Comportamento do Usuário
Ao categorizar os usuários com base em suas etapas de comportamento, podemos personalizar ainda mais o conteúdo do e-mail para se alinhar com suas necessidades específicas. Um LLM ajudará a criar e-mails que incentivam os usuários a progredir por diferentes etapas, melhorando assim sua compreensão e uso de vários serviços.
No momento, os dados do usuário são armazenados em um banco de dados MongoDB com uma estrutura de registro semelhante à seguinte:
{
'_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
}
Nós nos conectaremos ao MongoDB para obter os dados da seguinte forma:
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)
Vamos substituir <password>
e <host>
pelos valores do MongoDB Atlas.
Temos várias etapas de comportamento do usuário:
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]
Usando os dados sobre as etapas de comportamento, pediremos ao LLM para personalizar ainda mais o e-mail da seguinte forma:
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
}
)
Por exemplo, aqui está um e-mail gerado para 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. Personalização Adicional do Conteúdo do E-mail
Para apoiar o progresso do usuário, usaremos os embeddings vetoriais do Pinecone, permitindo-nos direcionar os usuários para a documentação relevante de cada etapa. Esses embeddings tornam fácil orientar os usuários para recursos essenciais e aprimorar ainda mais suas interações com nosso produto.
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()
Vamos criar os embeddings da seguinte forma:
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
Vamos pesquisar o Pinecone em busca de correspondências da seguinte forma:
def search_pinecone(embedding):
match = pc_index.query(
vector = [embedding],
top_k = 1,
include_metadata = True
)["matches"][0]["metadata"]
return match["content"], match["parent"]
Usando os dados, podemos pedir ao LLM para personalizar ainda mais o e-mail, da seguinte forma:
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
}
)
Por exemplo, aqui está um e-mail gerado para 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.
Podemos ver que refinamos o modelo genérico e desenvolvemos e-mails bastante direcionados.
Usando SingleStore
Em vez de gerenciar sistemas de banco de dados separados, vamos otimizar nossas operações usando o SingleStore. Com seu suporte para JSON, texto e incorporações vetoriais, podemos armazenar eficientemente todos os dados necessários em um só lugar, reduzindo o TCO e simplificando nossos processos de desenvolvimento.
Vamos ingerir os dados do MongoDB usando um pipeline semelhante ao seguinte:
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;
Vamos substituir <primary>
, <secondary>
, <secondary>
e <password>
pelos valores do MongoDB Atlas.
A tabela de clientes será criada pelo pipeline. As incorporações vetoriais para as etapas de comportamento podem ser criadas da seguinte maneira:
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)
Vamos precisar de uma tabela para armazenar os dados:
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
);
Em seguida, podemos salvar os dados na tabela:
df.to_sql(
"docs_splits",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
Vamos pesquisar no SingleStore por correspondências da seguinte maneira:
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()
Usando os dados, podemos pedir ao LLM para personalizar o e-mail da seguinte maneira:
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,
}
)
Por exemplo, aqui está um e-mail gerado para 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.
Resumo
Através desta demonstração prática, vimos como o SingleStore melhora nossas campanhas de e-mail com suas capacidades multi-modelo e personalização orientada por IA. Usando o SingleStore como nossa única fonte de verdade, simplificamos nossos fluxos de trabalho e garantimos que nossas campanhas de e-mail entreguem o máximo impacto e valor aos nossos clientes.
Agradecimentos
Agradeço a Wes Kennedy pelo código original da demonstração, que foi adaptado para este artigo.
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app