vishal1278 commited on
Commit
93e917d
1 Parent(s): 4209994

added all code

Browse files
img/beetlejuice_greeter.png ADDED
img/canvas.png ADDED
img/digital_photo_gift.png ADDED
img/photo-keeper.png ADDED
img/photo_keeper.png ADDED
img/strung-beads.png ADDED
requirements.txt ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ annotated-types==0.7.0
3
+ anyio==4.4.0
4
+ argon2-cffi==23.1.0
5
+ argon2-cffi-bindings==21.2.0
6
+ arrow==1.3.0
7
+ asttokens==2.4.1
8
+ async-lru==2.0.4
9
+ attrs==24.2.0
10
+ babel==2.16.0
11
+ beautifulsoup4==4.12.3
12
+ bleach==6.1.0
13
+ certifi==2024.7.4
14
+ cffi==1.17.0
15
+ charset-normalizer==3.3.2
16
+ click==8.1.7
17
+ comm==0.2.2
18
+ contourpy==1.2.1
19
+ cycler==0.12.1
20
+ debugpy==1.8.5
21
+ decorator==5.1.1
22
+ defusedxml==0.7.1
23
+ distro==1.9.0
24
+ exceptiongroup==1.2.2
25
+ executing==2.0.1
26
+ fastapi==0.112.0
27
+ fastjsonschema==2.20.0
28
+ ffmpy==0.4.0
29
+ filelock==3.15.4
30
+ fonttools==4.53.1
31
+ fqdn==1.5.1
32
+ fsspec==2024.6.1
33
+ gradio==4.41.0
34
+ gradio_client==1.3.0
35
+ h11==0.14.0
36
+ httpcore==1.0.5
37
+ httpx==0.27.0
38
+ huggingface-hub==0.24.5
39
+ idna==3.7
40
+ importlib_resources==6.4.0
41
+ ipykernel==6.29.5
42
+ ipython==8.26.0
43
+ isoduration==20.11.0
44
+ jedi==0.19.1
45
+ Jinja2==3.1.4
46
+ jiter==0.5.0
47
+ json5==0.9.25
48
+ jsonpointer==3.0.0
49
+ jsonschema==4.23.0
50
+ jsonschema-specifications==2023.12.1
51
+ jupyter-events==0.10.0
52
+ jupyter-lsp==2.2.5
53
+ jupyter_client==8.6.2
54
+ jupyter_core==5.7.2
55
+ jupyter_server==2.14.2
56
+ jupyter_server_terminals==0.5.3
57
+ jupyterlab==4.2.4
58
+ jupyterlab_pygments==0.3.0
59
+ jupyterlab_server==2.27.3
60
+ kiwisolver==1.4.5
61
+ markdown-it-py==3.0.0
62
+ MarkupSafe==2.1.5
63
+ matplotlib==3.9.2
64
+ matplotlib-inline==0.1.7
65
+ mdurl==0.1.2
66
+ mistune==3.0.2
67
+ nbclient==0.10.0
68
+ nbconvert==7.16.4
69
+ nbformat==5.10.4
70
+ nest-asyncio==1.6.0
71
+ notebook_shim==0.2.4
72
+ numpy==2.0.1
73
+ openai==1.40.6
74
+ orjson==3.10.7
75
+ overrides==7.7.0
76
+ packaging==24.1
77
+ pandas==2.2.2
78
+ pandocfilters==1.5.1
79
+ parso==0.8.4
80
+ pexpect==4.9.0
81
+ pillow==10.4.0
82
+ platformdirs==4.2.2
83
+ prometheus_client==0.20.0
84
+ prompt_toolkit==3.0.47
85
+ psutil==6.0.0
86
+ ptyprocess==0.7.0
87
+ pure_eval==0.2.3
88
+ pycparser==2.22
89
+ pydantic==2.8.2
90
+ pydantic_core==2.20.1
91
+ pydub==0.25.1
92
+ Pygments==2.18.0
93
+ pyparsing==3.1.2
94
+ python-dateutil==2.9.0.post0
95
+ python-dotenv==1.0.1
96
+ python-json-logger==2.0.7
97
+ python-multipart==0.0.9
98
+ pytz==2024.1
99
+ PyYAML==6.0.2
100
+ pyzmq==26.1.0
101
+ referencing==0.35.1
102
+ requests==2.32.3
103
+ rfc3339-validator==0.1.4
104
+ rfc3986-validator==0.1.1
105
+ rich==13.7.1
106
+ rpds-py==0.20.0
107
+ ruff==0.5.7
108
+ semantic-version==2.10.0
109
+ Send2Trash==1.8.3
110
+ shellingham==1.5.4
111
+ six==1.16.0
112
+ sniffio==1.3.1
113
+ soupsieve==2.6
114
+ stack-data==0.6.3
115
+ starlette==0.37.2
116
+ terminado==0.18.1
117
+ tinycss2==1.3.0
118
+ tomli==2.0.1
119
+ tomlkit==0.12.0
120
+ tornado==6.4.1
121
+ tqdm==4.66.5
122
+ traitlets==5.14.3
123
+ typer==0.12.3
124
+ types-python-dateutil==2.9.0.20240316
125
+ typing_extensions==4.12.2
126
+ tzdata==2024.1
127
+ uri-template==1.3.0
128
+ urllib3==2.2.2
129
+ uvicorn==0.30.6
130
+ wcwidth==0.2.13
131
+ webcolors==24.8.0
132
+ webencodings==0.5.1
133
+ websocket-client==1.8.0
134
+ websockets==12.0
src/__init__.py ADDED
File without changes
src/app.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from PIL import Image
3
+
4
+ sys.path.append(".")
5
+ from utils import (
6
+ generate_dummy_data,
7
+ generate_summary,
8
+ generate_welcome_message,
9
+ )
10
+ from prompts import CAMPAIGN_DESCR
11
+
12
+ import gradio as gr
13
+
14
+
15
+ df = generate_dummy_data()
16
+ print(df)
17
+
18
+ campaign_names = list(CAMPAIGN_DESCR.keys())
19
+
20
+
21
+ def process_customer_selection(customer_name, campaign_name):
22
+ customer_data = df[df["Name"] == customer_name].iloc[0]
23
+ print(customer_data)
24
+ summary = generate_summary(customer_data)
25
+ message = generate_welcome_message(summary, campaign_name)
26
+
27
+ # select the appropriate hero image for each campaign
28
+ if campaign_name == "Summer Clearance":
29
+ campaign_image = "../img/strung-beads.png"
30
+ elif campaign_name == "Makehaul":
31
+ campaign_image = "../img/canvas.png"
32
+ elif campaign_name == "Lowest Prices Of the Season":
33
+ campaign_image = "../img/photo-keeper.png"
34
+ else:
35
+ print("Invalid Campaign Name")
36
+
37
+ image = Image.open(campaign_image)
38
+
39
+ return summary, message, image
40
+
41
+
42
+ def create_gradio_app():
43
+ customer_names = df["Name"].tolist()
44
+
45
+ interface = gr.Interface(
46
+ fn=process_customer_selection,
47
+ inputs=[
48
+ gr.Dropdown(choices=customer_names, label="Select a Customer"),
49
+ gr.Dropdown(choices=campaign_names, label="Select a Campaign"),
50
+ ],
51
+ outputs=[
52
+ gr.Textbox(label="Customer Summary [Input]"),
53
+ gr.Textbox(label="Personalized Welcome Message [Output]"),
54
+ gr.Image(label="Campaign Hero Product"),
55
+ ],
56
+ title="Personalized Email Content Generator",
57
+ )
58
+
59
+ interface.launch(share=True)
60
+
61
+
62
+ # Run the Gradio app
63
+ create_gradio_app()
src/prompts.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SYSTEM_PROMPT = (
2
+ f"You are a marketing manager who can create personalized messages for customers based on some transaction and segment data about them."
3
+ f"Make sure you mention the latest product that the customer purchased and also the customer's recency of purchase. However, don't mention the exact number of days. Just use qualitative words such as 'recently', 'a while ago', etc."
4
+ f"Recognize the customer's favorite department but don't mention the department name explicitly."
5
+ f"The message should be friendly and encourage the customer to make another purchase. Use the campaign hero product for this."
6
+ f"The message should be about 70 to 100 words long."
7
+ f"Remember to keep the message professional and respectful. Do not include any exclusive offers or discounts in the message."
8
+ f"Also generate the subject line for the email. The subject line should be about 5 to 10 words long."
9
+ f"The subject line may contain a relevant emoji or two."
10
+ f"Don't use the customer's name in the message or any other personal information."
11
+ f"In addition, please create a 'hero message' for this customer. The hero message is like a tagline to inspiring the customer. Here are a few examples: 'Craft it yourself', 'Express your creativity', 'Keep inspiring'. It should be less than six words long."
12
+ )
13
+
14
+ PERSONA_DESCR = {
15
+ "Artist": (
16
+ f"\nThe following type of message would appeal to this customer: "
17
+ f"Michaels helps you make what no one else can. "
18
+ f"Position the brand as a place for artists and creatives to bring their ideas to life with essentials at good value, with a bit of whimsy and magic to be discovered."
19
+ ),
20
+ "Creator": (
21
+ f"\nThe following type of message would appeal to this customer: "
22
+ f"Delight and inspire your biggest fans by giving them what they love, which is variety and inspiration. Explore ways to re-think product selection, notably in décor, to increase spend across the store."
23
+ ),
24
+ "Curator": (
25
+ f"\nThe following type of message would appeal to this customer: "
26
+ f"The curator cares about making their homes and spaces beautiful and unique. "
27
+ f"Show them that Michaels is the place to get that trend they’re inspired by without losing the unique touch that makes it their own."
28
+ ),
29
+ "Seeker": (
30
+ f"\nThe following type of message would appeal to this customer: "
31
+ f"Make their shopping experience quick and remove friction. "
32
+ f"They are busy, but motivated and enjoy a little retail therapy. "
33
+ f"Encourage projects and products that aren’t overly complicated, kits that eliminate multiple trips and planning, and fun for kids."
34
+ ),
35
+ }
36
+
37
+ CAMPAIGN_DESCR = {
38
+ "Summer Clearance": (
39
+ f"Campaign Name: Summer Clearance\n"
40
+ f"Campaign Objective: 'This campaign should encourage customers to shop now and get up to 70% off even more items during Clearance Event. This is an online-only event offering 70% off on all custom frame collections and other items.'\n"
41
+ ),
42
+ "Makehaul": (
43
+ f"Campaign Name: Makehaul\n"
44
+ f"Campaign Objective: 'This campaign offers BOGO (Buy One Get One Free) offers on thousands of items. Customers can get 70% off on all custom frames collections.'\n"
45
+ ),
46
+ "Lowest Prices Of the Season": (
47
+ f"Campaign Name: Lowest Prices Of the Season\n"
48
+ f"Campaign Objective: 'This campaign comes with the BEST offers on thousands of items. These offers are rare as they happen only three times a year.'\n"
49
+ ),
50
+ }
src/utils.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from openai import OpenAI
3
+ from dotenv import load_dotenv
4
+ import os
5
+
6
+ import sys
7
+
8
+ sys.path.append(".")
9
+ from prompts import SYSTEM_PROMPT, PERSONA_DESCR, CAMPAIGN_DESCR
10
+
11
+ load_dotenv("../.env")
12
+ client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
13
+
14
+
15
+ def generate_summary(customer_data):
16
+ customer_value = "high" if customer_data["Revenue"] >= 250 else "low"
17
+ customer_recency = "recent" if customer_data["Recency"] <= 60 else "not recent"
18
+
19
+ seg = customer_data["Segment"]
20
+ if seg == "Artist":
21
+ cust_seg_descr = PERSONA_DESCR["Artist"]
22
+ elif seg == "Creator":
23
+ cust_seg_descr = PERSONA_DESCR["Creator"]
24
+ elif seg == "Curator":
25
+ cust_seg_descr = PERSONA_DESCR["Curator"]
26
+ elif seg == "Seeker":
27
+ cust_seg_descr = PERSONA_DESCR["Seeker"]
28
+ else:
29
+ print("Invalid Segment")
30
+
31
+ summary = (
32
+ f"This is a {customer_value} value customer who has spent a total of {customer_data['Revenue']} dollars. "
33
+ f"Their most recent transaction was {customer_data['Recency']} days ago, which makes him/her a {customer_recency} customer. "
34
+ f"The latest product they purchased was {customer_data['LatestProduct']}. "
35
+ f"Their favorite department is {customer_data['FavoriteDepartment']}. "
36
+ f"{cust_seg_descr} ({seg})"
37
+ )
38
+ return summary
39
+
40
+
41
+ def generate_welcome_message(summary, campaign_name):
42
+ campaign_description = "The personalize message should align with the marketing campaign described below: "
43
+
44
+ if campaign_name == "Summer Clearance":
45
+ campaign_description += CAMPAIGN_DESCR["Summer Clearance"] + "\n"
46
+ elif campaign_name == "Makehaul":
47
+ campaign_description += CAMPAIGN_DESCR["Makehaul"] + "\n"
48
+ elif campaign_name == "Lowest Prices Of the Season":
49
+ campaign_description += CAMPAIGN_DESCR["Lowest Prices Of the Season"] + "\n"
50
+ else:
51
+ print("Invalid Campaign Name")
52
+
53
+ summary += f"{campaign_description}"
54
+
55
+ response = client.chat.completions.create(
56
+ model="gpt-4o-mini",
57
+ messages=[
58
+ {"role": "system", "content": SYSTEM_PROMPT},
59
+ {"role": "user", "content": summary},
60
+ ],
61
+ )
62
+
63
+ message = response.choices[0].message.content
64
+ return message
65
+
66
+
67
+ def generate_dummy_data():
68
+ data = {
69
+ "Name": [
70
+ "Alice",
71
+ "Bob",
72
+ "Charlie",
73
+ "David",
74
+ "Eva",
75
+ "Frank",
76
+ "Grace",
77
+ "Henry",
78
+ "Ivy",
79
+ "John",
80
+ ],
81
+ "Recency": [20, 50, 100, 10, 120, 70, 30, 150, 60, 40],
82
+ "Revenue": [200, 350, 150, 400, 100, 250, 300, 80, 330, 280],
83
+ "LatestProduct": [
84
+ "All Strung Beads",
85
+ "Permanent and Removable Vinyl",
86
+ "Creatology Baskets",
87
+ "Kids Storage",
88
+ "Lap Trays",
89
+ "Lemax Spooky Town Collection",
90
+ "Frames & Shadow Boxes",
91
+ "ALL Fall Stems",
92
+ "Folding Step Stool",
93
+ "Mini Sticker Printer",
94
+ ],
95
+ "FavoriteDepartment": [
96
+ "KIDS ART & EDUCATION",
97
+ "HOBBY CRAFTS",
98
+ "BAKEWARE",
99
+ "FRAMES",
100
+ "PAPERCRAFTING",
101
+ "STORAGE",
102
+ "HOBBY CRAFTS",
103
+ "FLORAL ACCESSORIES",
104
+ "HOBBY CRAFTS",
105
+ "KIDS ART & EDUCATION",
106
+ ],
107
+ "Segment": [
108
+ "Artist",
109
+ "Creator",
110
+ "Curator",
111
+ "Artist",
112
+ "Seeker",
113
+ "Curator",
114
+ "Artist",
115
+ "Seeker",
116
+ "Creator",
117
+ "Curator",
118
+ ],
119
+ }
120
+
121
+ return pd.DataFrame(data)