SingleStore es un potente sistema de base de datos multi-modelo y plataforma diseñada para soportar una amplia variedad de casos de uso empresarial. Sus características distintivas permiten a las empresas unificar múltiples sistemas de base de datos en una sola plataforma, reduciendo el Costo Total de Propiedad (TCO) y simplificando los flujos de trabajo de los desarrolladores al eliminar la necesidad de herramientas de integración complejas.
En este artículo, exploraremos cómo SingleStore puede transformar las campañas de correo electrónico para una empresa de análisis web, permitiendo la creación de contenido de correo electrónico personalizado y altamente dirigido.
El archivo de cuaderno utilizado en el artículo está disponible en GitHub.
Introducción
Una empresa de análisis web depende de las campañas de correo electrónico para interactuar con los clientes. Sin embargo, un enfoque genérico para dirigirse a los clientes a menudo pierde oportunidades para maximizar el potencial empresarial. Una solución más efectiva implicaría el uso de un modelo de lenguaje grande (LLM) para crear mensajes de correo electrónico personalizados.
Considere un escenario donde los datos de comportamiento de usuario se almacenan en una base de datos NoSQL como MongoDB, mientras que la documentación valiosa reside en una base de datos de vectores, como Pinecone. Gestionar estos sistemas múltiples puede volverse complejo y exigir muchos recursos, resaltando la necesidad de una solución unificada.
SingleStore, una base de datos versátil de múltiples modelos, admite varios formatos de datos, incluido JSON, y ofrece funciones vectoriales integradas. Se integra perfectamente con los LLM, lo que la convierte en una alternativa poderosa para administrar múltiples sistemas de bases de datos. En este artículo, demostraremos lo fácil que SingleStore puede reemplazar tanto a MongoDB como a Pinecone, simplificando las operaciones sin comprometer la funcionalidad.
En nuestra aplicación de ejemplo, utilizaremos un LLM para generar correos electrónicos únicos para nuestros clientes. Para ayudar al LLM a aprender a dirigirse a nuestros clientes, utilizaremos varias empresas de análisis conocidas como material de aprendizaje para el LLM.
Personalizaremos aún más el contenido según el comportamiento del usuario. Los datos de los clientes se almacenan en MongoDB. Diferentes etapas del comportamiento del usuario se almacenan en Pinecone. El comportamiento del usuario permitirá al LLM generar correos electrónicos personalizados. Finalmente, consolidaremos los datos almacenados en MongoDB y Pinecone utilizando SingleStore.
Crear una cuenta en la nube de SingleStore
Un artículo anterior mostró los pasos para crear una cuenta gratuita en la nube de SingleStore. Utilizaremos el Nivel Estándar y tomaremos los nombres predeterminados para el Grupo de Espacio de Trabajo y el Espacio de Trabajo. También habilitaremos SingleStore Kai.
Almacenaremos nuestra clave de API de OpenAI y la clave de API de Pinecone en el depósito de secretos utilizando OPENAI_API_KEY
y PINECONE_API_KEY
, respectivamente.
Importar el Cuaderno
Descargaremos el cuaderno desde GitHub.
Desde el panel de navegación izquierdo en el portal de la nube de SingleStore, seleccionaremos “DESARROLLAR” > “Estudio de Datos.”
En la parte superior derecha de la página web, seleccionaremos “Nuevo Cuaderno” > “Importar Desde Archivo.” Utilizaremos el asistente para localizar e importar el cuaderno que descargamos de GitHub.
Ejecutar el Cuaderno
Plantilla de Correo Electrónico Genérica
Comenzaremos generando plantillas de correo electrónico genéricas y luego utilizaremos un LLM para transformarlas en mensajes personalizados para cada cliente. De esta manera, podremos dirigirnos a cada destinatario por su nombre e introducirles a los beneficios de nuestra plataforma de análisis web.
Podemos generar un correo electrónico genérico de la siguiente manera:
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 ejemplo, Alice vería el siguiente mensaje:
Hey Alice,
Check out our web analytics platform, it's Awesome!
It's perfect for your needs. Buy it now!
- Marketer John
Los demás usuarios recibirían el mismo mensaje, pero con su nombre respectivamente.
2. Agregar un Modelo de Lenguaje Grande (LLM)
Podemos incorporar fácilmente un LLM en nuestra aplicación proporcionándole un rol y dándole algo de información, de la siguiente manera:
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.
"""
Crearemos una función para llamar al 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
Recorrer la lista de usuarios y llamar al LLM produce correos electrónicos ú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 ejemplo, esto es lo que podría ver 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
Correos igualmente únicos se generarán para los otros usuarios.
3. Personalizar el Contenido del Correo Electrónico Con el Comportamiento del Usuario
Al categorizar a los usuarios basándonos en las etapas de su comportamiento, podemos personalizar aún más el contenido del correo electrónico para que se ajuste a sus necesidades específicas. Un LLM ayudará a crear correos electrónicos que animen a los usuarios a avanzar a través de diferentes etapas, mejorando en última instancia su comprensión y uso de varios servicios.
Actualmente, los datos de usuario se almacenan en una base de datos MongoDB con una estructura de registro similar a la siguiente:
{
'_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
}
Nos conectaremos a MongoDB para obtener los datos de la siguiente manera:
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)
Reemplazaremos <password>
y <host>
con los valores de MongoDB Atlas.
Tenemos una serie de etapas de comportamiento de usuario:
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]
Utilizando los datos sobre las etapas de comportamiento, pediremos al LLM que personalice aún más el correo electrónico de la siguiente manera:
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 ejemplo, aquí hay un correo electrónico generado 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. Personalización Adicional del Contenido del Correo Electrónico
Para apoyar el progreso del usuario, utilizaremos los embeddings vectoriales de Pinecone, lo que nos permitirá dirigir a los usuarios a la documentación relevante para cada etapa. Estos embeddings facilitan guiar a los usuarios hacia recursos esenciales y mejorar aún más sus interacciones con nuestro producto.
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()
Crearemos los embeddings de la siguiente manera:
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
Buscaremos coincidencias en Pinecone de la siguiente manera:
def search_pinecone(embedding):
match = pc_index.query(
vector = [embedding],
top_k = 1,
include_metadata = True
)["matches"][0]["metadata"]
return match["content"], match["parent"]
Utilizando los datos, podemos pedir al LLM que personalice aún más el correo electrónico, de la siguiente manera:
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 ejemplo, aquí hay un correo electrónico generado 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 hemos refinado la plantilla genérica y desarrollado correos electrónicos bastante específicos.
Usando SingleStore
En lugar de administrar sistemas de bases de datos separados, optimizaremos nuestras operaciones utilizando SingleStore. Con su soporte para JSON, texto y vectores de incrustación, podemos almacenar eficientemente todos los datos necesarios en un solo lugar, reduciendo el TCO y simplificando nuestros procesos de desarrollo.
Vamos a ingresar los datos desde MongoDB utilizando un pipeline similar al siguiente:
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;
Reemplazaremos <primario>
, <secundario>
, <secundario>
y <contraseña>
con los valores de MongoDB Atlas.
La tabla de clientes será creada por el pipeline. Los vectores de incrustación para las etapas de comportamiento pueden ser creados de la siguiente manera:
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)
Necesitaremos una tabla para almacenar los datos:
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
);
Luego, podemos guardar los datos en la tabla:
df.to_sql(
"docs_splits",
con = db_connection,
if_exists = "append",
index = False,
chunksize = 1000
)
Buscaremos coincidencias en SingleStore de la siguiente manera:
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()
Utilizando los datos, podemos pedir al LLM que personalice el correo electrónico de la siguiente manera:
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 ejemplo, aquí hay un correo electrónico generado 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.
Resumen
A través de esta demostración práctica, hemos visto cómo SingleStore mejora nuestras campañas de correo electrónico con sus capacidades multi-modelo y personalización impulsada por IA. Utilizando SingleStore como nuestra única fuente de verdad, hemos simplificado nuestros flujos de trabajo y asegurado que nuestras campañas de correo electrónico entreguen el máximo impacto y valor a nuestros clientes.
Agradecimientos
Agradezco a Wes Kennedy por el código de demostración original, el cual fue adaptado para este artículo.
Source:
https://dzone.com/articles/how-to-build-a-chatgpt-super-app