Afathman commited on
Commit
f3667ed
·
verified ·
1 Parent(s): b78ff02

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -49
app.py CHANGED
@@ -11,7 +11,6 @@ try:
11
  models = joblib.load('email_quality_models.pkl')
12
  scaler = joblib.load('feature_scaler.pkl')
13
  day_encoder = joblib.load('day_encoder.pkl')
14
- list_encoder = joblib.load('list_encoder.pkl')
15
  feature_names = joblib.load('feature_names.pkl')
16
  model_results = joblib.load('model_results.pkl')
17
  except Exception as e:
@@ -53,50 +52,115 @@ def section_score(features):
53
  score = max(0, min(100, score))
54
  return score
55
 
56
- def analyze_email_complete(subject, preview_text, campaign_name, body_text, day_of_week,
57
- email_list, send_time, total_recipients, target_metric):
58
- # Extract features for each section
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  subject_features = extract_text_features(subject)
60
  preview_features = extract_text_features(preview_text)
61
  body_features = extract_text_features(body_text)
62
-
63
- # Section scores (placeholder logic)
64
  subject_score = section_score(subject_features)
65
  preview_score = section_score(preview_features)
66
  body_score = section_score(body_features)
67
-
68
- # Overall performance score (dynamic placeholder: weighted avg of section scores)
 
 
 
69
  performance_score = int(round(0.4 * subject_score + 0.3 * preview_score + 0.3 * body_score))
70
-
 
71
  # Sentiment analysis
72
  text_for_sentiment = f"{subject}\n{preview_text}\n{body_text}"
73
  sentiment_result = sentiment(text_for_sentiment)[0]
74
-
75
  # Zero-shot classification
76
  labels = ["engaging", "promotional", "informative", "urgent", "personal"]
77
  classification_result = classifier(text_for_sentiment, labels)
78
-
79
- # Recommendations (simple, based on features)
80
- recommendations = []
81
- if subject_features['length'] > 50:
82
- recommendations.append(f"📧 Consider shortening your subject line (currently {subject_features['length']} chars)")
83
- if subject_features['emoji_count'] == 0:
84
- recommendations.append("😊 Consider adding an emoji to your subject line")
85
- if preview_features['length'] < 20:
86
- recommendations.append("👀 Add more detail to your preview text")
87
- if body_features['word_count'] < 50:
88
- recommendations.append("✍️ Consider a longer, more detailed email body")
89
- if sentiment_result['label'] == "NEGATIVE":
90
- recommendations.append("😬 Try a more positive tone in your email")
91
-
92
  # Format output
 
 
 
 
 
93
  output = f"""
94
  ## 📊 Performance Score: {performance_score}/100
95
 
96
- ### ✂️ Section Scores
97
- - **Subject Line:** {subject_score}/100
98
- - **Preview Text:** {preview_score}/100
99
- - **Body Text:** {body_score}/100
 
 
 
 
 
100
 
101
  ### 📈 Sentiment Analysis
102
  - **Sentiment:** {sentiment_result['label']} (confidence: {sentiment_result['score']:.2f})
@@ -105,30 +169,17 @@ def analyze_email_complete(subject, preview_text, campaign_name, body_text, day_
105
  """
106
  for i, (label, score) in enumerate(zip(classification_result['labels'][:3], classification_result['scores'][:3])):
107
  output += f"- **{label.title()}**: {score:.2f}\n"
108
- if recommendations:
109
- output += "\n### 💡 Recommendations\n"
110
- for rec in recommendations[:5]:
111
- output += f"{rec}\n"
112
  output += f"""
113
  ### 📋 Email Details
114
  - **Subject Length:** {subject_features['length']} characters
115
  - **Preview Length:** {preview_features['length']} characters
116
  - **Body Word Count:** {body_features['word_count']} words
117
  - **Send Time:** {send_time} on {day_of_week}
118
- - **Target Audience:** {int(total_recipients):,} recipients
119
  """
120
  return output
121
 
122
  # Available options
123
  day_options = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
124
- list_options = [
125
- 'C4 - Very Engaged',
126
- 'C4 - Less Engaged',
127
- 'C4 - Very Engaged, C4 - Less Engaged',
128
- 'C4 - Re-Engage',
129
- 'New Users added in last 30 days (all entry points)',
130
- 'FMP: 2024 Premium Users Opted In to Weekly'
131
- ]
132
 
133
  demo = gr.Interface(
134
  fn=analyze_email_complete,
@@ -138,20 +189,18 @@ demo = gr.Interface(
138
  gr.Textbox(label="📋 Campaign Name", placeholder="Enter campaign name"),
139
  gr.Textbox(label="📝 Email Body", placeholder="Paste your email body here"),
140
  gr.Dropdown(choices=day_options, label="📅 Day of Week", value="Thursday"),
141
- gr.Dropdown(choices=list_options, label="📮 Email List", value="C4 - Very Engaged"),
142
  gr.Textbox(label="⏰ Send Time", placeholder="9:00 AM", value="9:00 AM"),
143
- gr.Number(label="👥 Total Recipients", value=500000),
144
- gr.Radio(choices=['open_rate', 'click_rate', 'unsubscribe_rate'],
145
  label="🎯 Target Metric", value='click_rate')
146
  ],
147
  outputs=gr.Markdown(),
148
  title="🚀 Email Performance Predictor - Forks Over Knives",
149
- description="Predict email performance and get actionable recommendations based on your campaign data",
150
  examples=[
151
- ["Wrap Up Your Monday with Flavor 🌯🥑", "Ready in minutes—perfect for lunch, dinner, or...",
152
- "Meatless Monday | Black Bean Avo Wraps", "Try our new wraps! They're delicious and easy to make.", "Monday", "C4 - Very Engaged", "9:00 AM", 545464, "click_rate"],
153
- ["NEW Special Issue: Plant-Based Bowls", "Get your first look inside the latest issue...",
154
- "Plant-Based Bowls Special Issue", "Discover 50+ new recipes in this special issue.", "Saturday", "C4 - Very Engaged, C4 - Less Engaged", "1:30 AM", 650681, "open_rate"]
155
  ]
156
  )
157
 
 
11
  models = joblib.load('email_quality_models.pkl')
12
  scaler = joblib.load('feature_scaler.pkl')
13
  day_encoder = joblib.load('day_encoder.pkl')
 
14
  feature_names = joblib.load('feature_names.pkl')
15
  model_results = joblib.load('model_results.pkl')
16
  except Exception as e:
 
52
  score = max(0, min(100, score))
53
  return score
54
 
55
+ def section_suggestion(section, features):
56
+ # Simple, section-specific suggestions
57
+ if section == "subject":
58
+ if features['length'] > 50:
59
+ return "Try shortening your subject line for better impact."
60
+ if features['emoji_count'] == 0:
61
+ return "Add an emoji to make your subject line stand out."
62
+ if features['exclamation_count'] == 0:
63
+ return "Consider adding an exclamation mark for urgency."
64
+ return "Your subject line looks good!"
65
+ elif section == "preview":
66
+ if features['length'] < 20:
67
+ return "Add more detail to your preview text."
68
+ if features['emoji_count'] == 0:
69
+ return "Try adding an emoji to your preview text."
70
+ return "Your preview text is engaging!"
71
+ elif section == "body":
72
+ if features['word_count'] < 50:
73
+ return "Consider a longer, more detailed email body."
74
+ if features['exclamation_count'] == 0:
75
+ return "Try using an exclamation mark to highlight key points."
76
+ return "Your email body is well-structured!"
77
+ return ""
78
+
79
+ def predict_email_performance(subject, preview_text, campaign_name, body_text, day_of_week, send_time, target_metric):
80
+ # Extract text features
81
+ subject_features = extract_text_features(subject)
82
+ campaign_features = extract_text_features(campaign_name)
83
+ preview_features = extract_text_features(preview_text)
84
+ body_features = extract_text_features(body_text)
85
+ # Parse send time
86
+ try:
87
+ send_hour = datetime.strptime(send_time, '%I:%M %p').hour
88
+ except:
89
+ send_hour = 9 # Default to 9 AM
90
+ # Encode categorical variables
91
+ try:
92
+ day_encoded = day_encoder.transform([day_of_week])[0]
93
+ except:
94
+ day_encoded = 0 # Default encoding
95
+ # Create feature vector (no list or audience size)
96
+ features = [
97
+ 500000, # Placeholder for audience size (kept for model compatibility)
98
+ send_hour,
99
+ day_encoded,
100
+ 0 # Placeholder for list (kept for model compatibility)
101
+ ]
102
+ # Add text features in correct order
103
+ for prefix, feats in zip(['subject_', 'campaign_', 'preview_'], [subject_features, campaign_features, preview_features]):
104
+ for suffix in ['length', 'word_count', 'exclamation_count', 'question_count', 'emoji_count', 'number_count', 'caps_ratio']:
105
+ features.append(feats[suffix])
106
+ # For body, just append features (if you want to use them in the model, retrain with these features)
107
+ for suffix in ['length', 'word_count', 'exclamation_count', 'question_count', 'emoji_count', 'number_count', 'caps_ratio']:
108
+ features.append(body_features[suffix])
109
+ # Scale features (truncate or pad to match model input)
110
+ features = features[:len(feature_names)]
111
+ features_scaled = scaler.transform([features])
112
+ # Make prediction
113
+ model = models[target_metric]
114
+ prediction = model.predict(features_scaled)[0]
115
+ # Convert to percentage and ensure reasonable bounds
116
+ if target_metric == 'open_rate':
117
+ prediction = max(0, min(1, prediction)) * 100
118
+ elif target_metric == 'click_rate':
119
+ prediction = max(0, min(0.5, prediction)) * 100
120
+ else: # unsubscribe_rate
121
+ prediction = max(0, min(0.1, prediction)) * 100
122
+ return prediction
123
+
124
+ def analyze_email_complete(subject, preview_text, campaign_name, body_text, day_of_week, send_time, target_metric):
125
+ # Section features and scores
126
  subject_features = extract_text_features(subject)
127
  preview_features = extract_text_features(preview_text)
128
  body_features = extract_text_features(body_text)
 
 
129
  subject_score = section_score(subject_features)
130
  preview_score = section_score(preview_features)
131
  body_score = section_score(body_features)
132
+ # Section suggestions
133
+ subject_sugg = section_suggestion("subject", subject_features)
134
+ preview_sugg = section_suggestion("preview", preview_features)
135
+ body_sugg = section_suggestion("body", body_features)
136
+ # Overall performance score (weighted avg)
137
  performance_score = int(round(0.4 * subject_score + 0.3 * preview_score + 0.3 * body_score))
138
+ # Predicted metric
139
+ predicted_value = predict_email_performance(subject, preview_text, campaign_name, body_text, day_of_week, send_time, target_metric)
140
  # Sentiment analysis
141
  text_for_sentiment = f"{subject}\n{preview_text}\n{body_text}"
142
  sentiment_result = sentiment(text_for_sentiment)[0]
 
143
  # Zero-shot classification
144
  labels = ["engaging", "promotional", "informative", "urgent", "personal"]
145
  classification_result = classifier(text_for_sentiment, labels)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  # Format output
147
+ metric_label = {
148
+ "open_rate": "Open Rate",
149
+ "click_rate": "Click Rate",
150
+ "unsubscribe_rate": "Unsubscribe Rate"
151
+ }[target_metric]
152
  output = f"""
153
  ## 📊 Performance Score: {performance_score}/100
154
 
155
+ ### 🎯 Predicted {metric_label}: {predicted_value:.2f}%
156
+
157
+ ### ✂️ Section Scores & Suggestions
158
+ - **Subject Line:** {subject_score}/100
159
+ _Suggestion: {subject_sugg}_
160
+ - **Preview Text:** {preview_score}/100
161
+ _Suggestion: {preview_sugg}_
162
+ - **Body Text:** {body_score}/100
163
+ _Suggestion: {body_sugg}_
164
 
165
  ### 📈 Sentiment Analysis
166
  - **Sentiment:** {sentiment_result['label']} (confidence: {sentiment_result['score']:.2f})
 
169
  """
170
  for i, (label, score) in enumerate(zip(classification_result['labels'][:3], classification_result['scores'][:3])):
171
  output += f"- **{label.title()}**: {score:.2f}\n"
 
 
 
 
172
  output += f"""
173
  ### 📋 Email Details
174
  - **Subject Length:** {subject_features['length']} characters
175
  - **Preview Length:** {preview_features['length']} characters
176
  - **Body Word Count:** {body_features['word_count']} words
177
  - **Send Time:** {send_time} on {day_of_week}
 
178
  """
179
  return output
180
 
181
  # Available options
182
  day_options = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
 
 
 
 
 
 
 
 
183
 
184
  demo = gr.Interface(
185
  fn=analyze_email_complete,
 
189
  gr.Textbox(label="📋 Campaign Name", placeholder="Enter campaign name"),
190
  gr.Textbox(label="📝 Email Body", placeholder="Paste your email body here"),
191
  gr.Dropdown(choices=day_options, label="📅 Day of Week", value="Thursday"),
 
192
  gr.Textbox(label="⏰ Send Time", placeholder="9:00 AM", value="9:00 AM"),
193
+ gr.Radio(choices=['open_rate', 'click_rate', 'unsubscribe_rate'],
 
194
  label="🎯 Target Metric", value='click_rate')
195
  ],
196
  outputs=gr.Markdown(),
197
  title="🚀 Email Performance Predictor - Forks Over Knives",
198
+ description="Predict email performance and get actionable, section-specific recommendations based on your campaign data",
199
  examples=[
200
+ ["Wrap Up Your Monday with Flavor 🌯🥑", "Ready in minutes—perfect for lunch, dinner, or...",
201
+ "Meatless Monday | Black Bean Avo Wraps", "Try our new wraps! They're delicious and easy to make.", "Monday", "9:00 AM", "click_rate"],
202
+ ["NEW Special Issue: Plant-Based Bowls", "Get your first look inside the latest issue...",
203
+ "Plant-Based Bowls Special Issue", "Discover 50+ new recipes in this special issue.", "Saturday", "1:30 AM", "open_rate"]
204
  ]
205
  )
206