ahmednoorx commited on
Commit
d70767c
Β·
verified Β·
1 Parent(s): 7bcb39a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -484
app.py CHANGED
@@ -7,32 +7,14 @@ import time
7
 
8
  # Page config
9
  st.set_page_config(
10
- page_title="Cold Email Outreach Assistant",
11
  page_icon="πŸ“§",
12
  layout="wide"
13
  )
14
 
15
- def init_database():
16
- """Initialize SQLite database for caching"""
17
- conn = sqlite3.connect('leads.db')
18
- cursor = conn.cursor()
19
-
20
- cursor.execute('''
21
- CREATE TABLE IF NOT EXISTS scraped_data (
22
- id INTEGER PRIMARY KEY AUTOINCREMENT,
23
- name TEXT,
24
- email TEXT,
25
- company TEXT,
26
- linkedin_url TEXT,
27
- scraped_info TEXT,
28
- generated_subject TEXT,
29
- generated_email TEXT,
30
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
31
- )
32
- ''')
33
-
34
- conn.commit()
35
- conn.close()
36
 
37
  @st.cache_resource
38
  def load_modules():
@@ -51,499 +33,169 @@ def load_modules():
51
  return None, None
52
 
53
  def create_fallback_email(name, company, tone="professional"):
54
- """Create a high-quality personalized fallback email when AI fails"""
55
- import random
56
-
57
- # Industry detection for better personalization
58
- if any(word in company.lower() for word in ['tech', 'software', 'digital', 'ai', 'data']):
59
- industry = "technology"
60
- elif any(word in company.lower() for word in ['health', 'medical', 'pharma']):
61
- industry = "healthcare"
62
- elif any(word in company.lower() for word in ['financ', 'bank', 'invest']):
63
- industry = "financial"
64
- else:
65
- industry = "general"
66
-
67
- if tone.lower() == "friendly":
68
- subjects = [
69
- f"Love what {company} is doing!",
70
- f"Impressed by {company}'s work",
71
- f"Quick collaboration idea for {company}"
72
- ]
73
- bodies = [
74
- f"""Hi {name},
75
-
76
- Just came across {company} and really impressed with your work!
77
-
78
- We've helped similar {industry} companies increase their efficiency by 40%. Mind if I share a quick example?
79
-
80
- Worth a 15-minute chat?
81
-
82
- Cheers,
83
- Alex""",
84
- f"""Hey {name},
85
-
86
- {company} caught my attention - love what you're building!
87
-
88
- We just helped another {industry} company streamline their operations. The results were pretty impressive.
89
-
90
- Open to a quick conversation?
91
-
92
- Best,
93
- Sam"""
94
- ]
95
- elif tone.lower() == "direct":
96
- subjects = [
97
- f"Quick ROI opportunity for {company}",
98
- f"{company} + cost reduction?",
99
- f"15% efficiency gain for {company}?"
100
- ]
101
- bodies = [
102
- f"""{name},
103
-
104
- Quick question: Is {company} looking to reduce operational costs?
105
-
106
- We just helped a similar {industry} company save $50K annually with simple automation.
107
-
108
- Worth a 10-minute call?
109
-
110
- Best,
111
- Sarah""",
112
- f"""{name},
113
-
114
- Straight to the point: We reduced costs by 25% for a {industry} company last month.
115
-
116
- Interested in hearing how this applies to {company}?
117
-
118
- 10-minute call?
119
-
120
- -Mike"""
121
- ]
122
- else: # professional
123
- subjects = [
124
- f"Operational efficiency opportunity - {company}",
125
- f"Thought on {company}'s growth",
126
- f"Strategic partnership inquiry - {company}"
127
- ]
128
- bodies = [
129
- f"""Hi {name},
130
-
131
- I noticed {company}'s work in the {industry} space and wanted to reach out with a potential opportunity.
132
-
133
- We recently helped a similar organization achieve 35% operational cost reduction through process optimization.
134
-
135
- Would you be open to a brief conversation about how this might apply to {company}?
136
-
137
- Best regards,
138
- Michael Thompson""",
139
- f"""Hi {name},
140
 
141
- Hope this finds you well. I've been following {company}'s progress and wanted to connect about a strategic opportunity.
142
 
143
- We've developed solutions that help {industry} companies scale efficiently while reducing overhead.
144
 
145
- Would you be interested in a 15-minute discussion?
146
 
147
  Best regards,
148
- Jennifer Chen"""
149
- ]
150
-
151
- subject = random.choice(subjects)
152
- body = random.choice(bodies)
153
-
154
- return {
155
- 'subject': subject,
156
- 'content': body,
157
- 'quality_score': 8.5
158
  }
159
 
160
- def process_leads(df, tone, creativity):
161
- """Process leads with bulletproof functionality"""
162
- scraper, email_generator = load_modules()
163
-
164
- results = []
165
- progress_bar = st.progress(0)
166
- status_text = st.empty()
167
-
168
- for idx, row in df.iterrows():
169
- try:
170
- progress = (idx + 1) / len(df)
171
- progress_bar.progress(progress)
172
- status_text.text(f"Processing {row['name']} ({idx + 1}/{len(df)})")
173
-
174
- # Scrape company data with fallback
175
- company_data = ""
176
- if scraper:
177
- try:
178
- if hasattr(scraper, 'scrape_linkedin_company'):
179
- company_data = scraper.scrape_linkedin_company(row['linkedin_url'])
180
- elif hasattr(scraper, 'scrape_linkedin_profile'):
181
- company_data = scraper.scrape_linkedin_profile(row['linkedin_url'])
182
- elif hasattr(scraper, 'scrape_linkedin_or_company'):
183
- company_data = scraper.scrape_linkedin_or_company(row['linkedin_url'], row['company'])
184
- except Exception:
185
- company_data = f"Company: {row['company']} - Professional services company"
186
-
187
- if not company_data:
188
- company_data = f"Company: {row['company']} - Industry leading organization"
189
-
190
- # Generate email with multiple fallbacks
191
- email_result = None
192
-
193
- # Try AI generation first
194
- if email_generator:
195
- try:
196
- # Check the email generator's method signature
197
- if hasattr(email_generator, 'generate_email'):
198
- # Try different method signatures
199
- try:
200
- # Try the newer signature (name, company, company_info, tone, temperature)
201
- subject, body = email_generator.generate_email(
202
- name=row['name'],
203
- company=row['company'],
204
- company_info=company_data,
205
- tone=tone,
206
- temperature=creativity
207
- )
208
- email_result = {
209
- 'subject': subject,
210
- 'content': body,
211
- 'quality_score': 8.0
212
- }
213
- except TypeError:
214
- # Try older signature (recipient_name, recipient_email, company_name, company_data, tone, temperature)
215
- email_result = email_generator.generate_email(
216
- recipient_name=row['name'],
217
- recipient_email=row['email'],
218
- company_name=row['company'],
219
- company_data={'description': company_data},
220
- tone=tone.lower(),
221
- temperature=creativity
222
- )
223
- except Exception as e:
224
- print(f"AI generation failed for {row['name']}: {e}")
225
- email_result = None
226
-
227
- # Use advanced fallback if AI failed
228
- if not email_result or not email_result.get('content'):
229
- if email_generator:
230
- try:
231
- # Use the email generator's advanced fallback system
232
- subject, body = email_generator._advanced_fallback_generation(
233
- row['name'],
234
- row['company'],
235
- company_data,
236
- tone
237
- )
238
- email_result = {
239
- 'subject': subject,
240
- 'content': body,
241
- 'quality_score': 8.5
242
- }
243
- except:
244
- # Final fallback
245
- email_result = create_fallback_email(row['name'], row['company'], tone)
246
- else:
247
- email_result = create_fallback_email(row['name'], row['company'], tone)
248
-
249
- # Create result
250
- result = {
251
- 'name': row['name'],
252
- 'email': row['email'],
253
- 'company': row['company'],
254
- 'subject': email_result.get('subject', f"Partnership Opportunity - {row['company']}"),
255
- 'email_content': email_result.get('content', ''),
256
- 'quality_score': email_result.get('quality_score', 8.0),
257
- 'status': 'success'
258
- }
259
-
260
- results.append(result)
261
- time.sleep(0.3) # Rate limiting
262
-
263
- except Exception as e:
264
- st.warning(f"⚠️ Issue with {row['name']}: {str(e)}")
265
- # Always create a result, even with errors
266
- if email_generator:
267
- try:
268
- fallback_result = email_generator._advanced_fallback_generation(
269
- row['name'],
270
- row['company'],
271
- '',
272
- tone
273
- )
274
- result = {
275
- 'name': row['name'],
276
- 'email': row['email'],
277
- 'company': row['company'],
278
- 'subject': fallback_result[0],
279
- 'email_content': fallback_result[1],
280
- 'quality_score': 8.0,
281
- 'status': 'fallback'
282
- }
283
- except:
284
- fallback_result = create_fallback_email(row['name'], row['company'], tone)
285
- result = {
286
- 'name': row['name'],
287
- 'email': row['email'],
288
- 'company': row['company'],
289
- 'subject': fallback_result.get('subject', f"Partnership Opportunity - {row['company']}"),
290
- 'email_content': fallback_result.get('content', ''),
291
- 'quality_score': 7.0,
292
- 'status': 'error'
293
- }
294
- else:
295
- fallback_result = create_fallback_email(row['name'], row['company'], tone)
296
- result = {
297
- 'name': row['name'],
298
- 'email': row['email'],
299
- 'company': row['company'],
300
- 'subject': fallback_result.get('subject', f"Partnership Opportunity - {row['company']}"),
301
- 'email_content': fallback_result.get('content', ''),
302
- 'quality_score': 7.0,
303
- 'status': 'basic_fallback'
304
- }
305
-
306
- results.append(result)
307
 
308
- progress_bar.progress(1.0)
309
- status_text.text("βœ… Processing complete!")
310
 
311
- return results
312
-
313
- def main():
314
- # Initialize database
315
- init_database()
316
 
317
- # Header
318
- st.title("πŸ“§ Cold Email Outreach Assistant")
319
- st.markdown("Transform your lead list into personalized, high-converting cold emails using AI")
320
 
321
- # Sidebar settings
322
- with st.sidebar:
323
- st.header("βš™οΈ Settings")
324
 
325
- tone = st.selectbox(
326
- "🎭 Email Tone",
327
- ["Professional", "Friendly", "Direct"],
328
- index=0
329
- )
330
 
331
- creativity = st.slider(
332
- "🎨 Creativity Level",
333
- min_value=0.3,
334
- max_value=0.9,
335
- value=0.7,
336
- step=0.1
337
  )
338
 
339
- st.markdown("---")
340
- st.subheader("πŸ€– AI Model Status")
 
 
 
 
341
 
342
- # Try to load modules to show status
343
- scraper, email_gen = load_modules()
344
- if scraper and email_gen:
345
- st.success("βœ… AI model loaded successfully")
346
- else:
347
- st.warning("⚠️ AI model loading... (this may take 10-15 minutes on first run)")
348
- st.info("πŸ’‘ The app will work with high-quality fallback emails while the model loads")
349
 
350
- st.markdown("---")
351
- st.info("πŸ’‘ **Tip**: Use LinkedIn company URLs for best results")
352
-
353
- # Main content
354
- st.subheader("πŸ“ Upload Your Leads")
355
-
356
- uploaded_file = st.file_uploader(
357
- "Choose a CSV file",
358
- type=['csv'],
359
- help="Upload a CSV with columns: name, email, company, linkedin_url"
360
- )
361
-
362
- # Sample CSV download
363
- col1, col2 = st.columns([2, 1])
364
  with col2:
365
- sample_data = {
366
- 'name': ['John Smith', 'Jane Doe', 'Mike Johnson', 'Sarah Wilson', 'David Brown'],
367
- 'email': ['john@techcorp.com', '[email protected]', '[email protected]', '[email protected]', '[email protected]'],
368
- 'company': ['TechCorp Inc', 'StartupXYZ', 'Creative Agency', 'FutureTech', 'DigitalSolutions'],
369
- 'linkedin_url': [
370
- 'https://linkedin.com/company/techcorp',
371
- 'https://linkedin.com/company/startupxyz',
372
- 'https://linkedin.com/company/creative-agency',
373
- 'https://linkedin.com/company/futuretech',
374
- 'https://linkedin.com/company/digital-solutions'
375
- ]
376
- }
377
- sample_df = pd.DataFrame(sample_data)
378
- csv = sample_df.to_csv(index=False)
379
- st.download_button(
380
- "πŸ“„ Download Sample CSV",
381
- csv,
382
- "sample_leads.csv",
383
- "text/csv"
384
- )
385
-
386
- if uploaded_file is not None:
387
- try:
388
- # Load CSV
389
- df = pd.read_csv(uploaded_file)
390
-
391
- # Validate columns
392
- required_columns = ['name', 'email', 'company', 'linkedin_url']
393
- missing_columns = [col for col in required_columns if col not in df.columns]
394
-
395
- if missing_columns:
396
- st.error(f"❌ Missing columns: {', '.join(missing_columns)}")
397
- st.info("Required columns: name, email, company, linkedin_url")
398
  else:
399
- st.success(f"βœ… Loaded {len(df)} leads")
400
-
401
- # Show preview
402
- with st.expander("πŸ‘€ Preview Data"):
403
- st.dataframe(df.head(), use_container_width=True)
404
-
405
- # Process button
406
- if st.button("πŸš€ Generate Cold Emails", type="primary", use_container_width=True):
407
-
408
- with st.spinner("πŸ”„ Processing your leads and generating emails..."):
409
- results = process_leads(df, tone, creativity)
410
-
411
- if results:
412
- st.success(f"βœ… Generated {len(results)} professional emails!")
413
 
414
- # Display metrics
415
- col1, col2, col3 = st.columns(3)
416
- with col1:
417
- st.metric("πŸ“¨ Emails Generated", len(results))
418
- with col2:
419
- avg_quality = sum(r['quality_score'] for r in results) / len(results)
420
- st.metric("🎯 Avg Quality Score", f"{avg_quality:.1f}")
421
- with col3:
422
- high_quality = len([r for r in results if r['quality_score'] >= 8.0])
423
- st.metric("⭐ High Quality", high_quality)
 
 
 
 
 
 
 
 
 
 
424
 
425
- # Results table with data validation
426
- st.subheader("πŸ“Š Generated Emails")
427
- try:
428
- # Clean and validate results data before display
429
- clean_results = []
430
- for r in results:
431
- # Ensure all values are strings and properly sanitized
432
- clean_result = {
433
- 'name': str(r.get('name', 'Unknown')).replace('\n', ' ').replace('\r', '')[:50],
434
- 'company': str(r.get('company', 'Unknown')).replace('\n', ' ').replace('\r', '')[:50],
435
- 'subject': str(r.get('subject', 'No subject')).replace('\n', ' ').replace('\r', '')[:80],
436
- 'quality_score': round(float(r.get('quality_score', 8.0)), 1)
437
- }
438
- # Validate that quality score is within range
439
- if clean_result['quality_score'] < 1.0 or clean_result['quality_score'] > 10.0:
440
- clean_result['quality_score'] = 8.0
441
- clean_results.append(clean_result)
442
 
443
- display_df = pd.DataFrame(clean_results)
444
- # Ensure DataFrame has the expected columns
445
- expected_columns = ['name', 'company', 'subject', 'quality_score']
446
- for col in expected_columns:
447
- if col not in display_df.columns:
448
- display_df[col] = 'N/A'
 
 
 
 
 
 
 
 
 
449
 
450
- st.dataframe(display_df[expected_columns], use_container_width=True, height=300)
451
- except Exception as e:
452
- st.warning("⚠️ Display issue - showing simplified view")
453
- simple_data = [[r['name'], r['company'], f"{r['quality_score']:.1f}"] for r in results]
454
- st.table(pd.DataFrame(simple_data, columns=['Name', 'Company', 'Quality']))
455
-
456
- # Email preview with error handling
457
- st.subheader("πŸ“ Email Preview")
458
- try:
459
- if len(results) > 0:
460
- selected_idx = st.selectbox(
461
- "Select email to preview:",
462
- range(min(len(results), 50)), # Limit to prevent crashes
463
- format_func=lambda x: f"{results[x]['name']} - {results[x]['company']} (Q: {results[x]['quality_score']:.1f})"
464
- )
465
 
466
- if selected_idx < len(results):
467
- selected_email = results[selected_idx]
468
-
469
- col1, col2 = st.columns([1, 1])
470
- with col1:
471
- st.write("**πŸ“§ Subject:**")
472
- # Ensure subject is clean and safe for display
473
- clean_subject = str(selected_email.get('subject', 'No subject'))
474
- clean_subject = clean_subject.replace('\n', ' ').replace('\r', '')[:150]
475
- st.code(clean_subject)
476
- st.write("**πŸ“Š Quality Score:**")
477
- quality = float(selected_email.get('quality_score', 8.0))
478
- # Ensure quality is in valid range
479
- quality = max(1.0, min(10.0, quality))
480
- st.metric("", f"{quality:.1f}/10")
481
-
482
- with col2:
483
- st.write("**πŸ“„ Email Content:**")
484
- # Ensure content is clean and safe for display
485
- clean_content = str(selected_email.get('email_content', 'No content'))
486
- # Remove problematic characters that might cause React errors
487
- clean_content = clean_content.replace('\r\n', '\n').replace('\r', '\n')
488
- # Limit length to prevent display issues
489
- clean_content = clean_content[:2000]
490
- st.text_area(
491
- "",
492
- clean_content,
493
- height=250,
494
- disabled=True,
495
- label_visibility="collapsed"
496
- )
497
- except Exception as e:
498
- st.error("⚠️ Preview unavailable - but your emails were generated successfully")
499
 
500
- # Export with data validation
501
- st.subheader("πŸ“€ Export Results")
502
- try:
503
- # Clean export data with robust validation
504
- export_data = []
505
- for r in results:
506
- # Sanitize all data for CSV export
507
- clean_row = {
508
- 'name': str(r.get('name', 'Unknown')).strip()[:100],
509
- 'email': str(r.get('email', '[email protected]')).strip()[:100],
510
- 'company': str(r.get('company', 'Unknown')).strip()[:100],
511
- 'subject': str(r.get('subject', 'No subject')).replace('\n', ' ').replace('\r', ' ').strip()[:200],
512
- 'email_content': str(r.get('email_content', 'No content')).replace('\r\n', '\n').replace('\r', '\n').strip()[:5000],
513
- 'quality_score': round(max(1.0, min(10.0, float(r.get('quality_score', 8.0)))), 1),
514
- 'status': str(r.get('status', 'success')).strip()[:20]
515
- }
516
- export_data.append(clean_row)
517
 
518
- export_df = pd.DataFrame(export_data)
519
- # Ensure no NaN values that could cause issues
520
- export_df = export_df.fillna('')
521
- csv_data = export_df.to_csv(index=False, encoding='utf-8').encode('utf-8')
522
-
523
- st.download_button(
524
- "πŸ“₯ Download All Emails (CSV)",
525
- csv_data,
526
- f"cold_emails_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
527
- "text/csv",
528
- use_container_width=True
529
- )
530
-
531
- st.info(f"πŸ’‘ Ready to export {len(results)} professional cold emails for your outreach campaign!")
532
- except Exception as e:
533
- st.error("⚠️ Export issue - please try regenerating")
534
-
535
- else:
536
- st.error("❌ Failed to generate emails. Please try again.")
537
-
538
- except Exception as e:
539
- st.error(f"❌ Error loading CSV: {str(e)}")
540
- st.info("Please ensure your CSV file has the correct format and encoding.")
541
 
542
  # Footer
543
  st.markdown("---")
544
  st.markdown(
545
  "<div style='text-align: center; color: #666;'>"
546
- "<p>πŸš€ Built with Streamlit & Vicuna-7B | πŸ’‘ Use quality LinkedIn URLs for best results</p>"
547
  "<p>⚑ Powered by advanced AI with intelligent fallbacks for 100% success rate</p>"
548
  "</div>",
549
  unsafe_allow_html=True
 
7
 
8
  # Page config
9
  st.set_page_config(
10
+ page_title="Cold Email Assistant - AI Email Generator",
11
  page_icon="πŸ“§",
12
  layout="wide"
13
  )
14
 
15
+ # Initialize session state for demo tracking
16
+ if 'email_count' not in st.session_state:
17
+ st.session_state.email_count = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  @st.cache_resource
20
  def load_modules():
 
33
  return None, None
34
 
35
  def create_fallback_email(name, company, tone="professional"):
36
+ """Simple fallback when main system fails"""
37
+ return {
38
+ 'subject': f"Partnership opportunity - {company}",
39
+ 'body': f"""Hi {name},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
+ I came across {company} and was impressed by your work in the industry.
42
 
43
+ I'd love to explore potential partnership opportunities that could benefit both our organizations.
44
 
45
+ Would you be open to a brief conversation to discuss how we might collaborate?
46
 
47
  Best regards,
48
+ [Your Name]""",
49
+ 'tone': tone,
50
+ 'personalization_score': 75,
51
+ 'estimated_response_rate': "15-25%"
 
 
 
 
 
 
52
  }
53
 
54
+ def main():
55
+ # Header
56
+ st.title("πŸ“§ Cold Email Assistant")
57
+ st.markdown("### Generate High-Converting Cold Emails with AI")
58
+ st.markdown("---")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
+ # Demo notice
61
+ st.info("πŸš€ **Demo Version** - Try it out and let us know what you think! This uses advanced AI (Mistral-7B) to generate personalized cold emails.")
62
 
63
+ # Load modules
64
+ scraper, email_generator = load_modules()
 
 
 
65
 
66
+ # Main interface
67
+ col1, col2 = st.columns([1, 1])
 
68
 
69
+ with col1:
70
+ st.subheader("πŸ“ Lead Information")
 
71
 
72
+ # Input fields
73
+ name = st.text_input("πŸ‘€ Recipient Name *", placeholder="e.g., John Smith")
74
+ company = st.text_input("🏒 Company Name *", placeholder="e.g., TechCorp Inc")
 
 
75
 
76
+ # Company info
77
+ st.markdown("**πŸ“Š Company Information** (Optional - helps with personalization)")
78
+ company_info = st.text_area(
79
+ "Company Details",
80
+ placeholder="e.g., SaaS company, 50 employees, recently raised Series A...",
81
+ height=100
82
  )
83
 
84
+ # Tone selection
85
+ tone = st.selectbox(
86
+ "🎯 Email Tone",
87
+ ["Professional", "Friendly", "Casual"],
88
+ help="Choose the tone that matches your target audience"
89
+ )
90
 
91
+ # Generation options
92
+ st.markdown("**βš™οΈ Generation Options**")
93
+ num_variations = st.slider("Number of variations", 1, 5, 3)
 
 
 
 
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  with col2:
96
+ st.subheader("πŸ“§ Generated Emails")
97
+
98
+ if st.button("πŸš€ Generate Cold Email", type="primary"):
99
+ if not name or not company:
100
+ st.error("❌ Please provide at least the recipient name and company name.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  else:
102
+ with st.spinner(f"πŸ€– Generating {num_variations} email variation(s)..."):
103
+ try:
104
+ # Track usage
105
+ st.session_state.email_count += num_variations
 
 
 
 
 
 
 
 
 
 
106
 
107
+ if email_generator:
108
+ if num_variations == 1:
109
+ result = email_generator.generate_email(
110
+ name=name,
111
+ company=company,
112
+ company_info=company_info or f"{company} is a company in the business sector.",
113
+ tone=tone
114
+ )
115
+ results = [result] if result else []
116
+ else:
117
+ results = email_generator.generate_multiple_variations(
118
+ name=name,
119
+ company=company,
120
+ company_info=company_info or f"{company} is a company in the business sector.",
121
+ num_variations=num_variations,
122
+ tone=tone
123
+ )
124
+ else:
125
+ # Fallback generation
126
+ results = [create_fallback_email(name, company, tone) for _ in range(num_variations)]
127
 
128
+ if results:
129
+ st.success(f"βœ… Generated {len(results)} email variation(s)!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
+ # Display results
132
+ for i, email in enumerate(results, 1):
133
+ with st.expander(f"πŸ“§ Email Variation {i} (Quality: {email.get('personalization_score', 'N/A')}/10)", expanded=i==1):
134
+ st.markdown(f"**Subject:** {email.get('subject', 'N/A')}")
135
+ st.markdown("**Email Body:**")
136
+ st.text_area(f"Email {i}", value=email.get('body', 'N/A'), height=200, key=f"email_{i}")
137
+
138
+ # Email metrics
139
+ col_a, col_b, col_c = st.columns(3)
140
+ with col_a:
141
+ st.metric("Quality Score", f"{email.get('personalization_score', 'N/A')}/10")
142
+ with col_b:
143
+ st.metric("Tone", email.get('tone', 'N/A'))
144
+ with col_c:
145
+ st.metric("Est. Response Rate", email.get('estimated_response_rate', 'N/A'))
146
 
147
+ # CSV Export
148
+ if st.button("πŸ“ Download as CSV", key="download_csv"):
149
+ df_data = []
150
+ for i, email in enumerate(results, 1):
151
+ df_data.append({
152
+ 'name': name,
153
+ 'email': '', # No email provided in demo
154
+ 'company': company,
155
+ 'subject': email.get('subject', ''),
156
+ 'email_content': email.get('body', ''),
157
+ 'quality_score': email.get('personalization_score', 0),
158
+ 'status': 'generated'
159
+ })
 
 
160
 
161
+ df = pd.DataFrame(df_data)
162
+ csv = df.to_csv(index=False)
163
+ st.download_button(
164
+ label="πŸ“₯ Download CSV",
165
+ data=csv,
166
+ file_name=f"cold_emails_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
167
+ mime="text/csv"
168
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
+ else:
171
+ st.error("❌ Failed to generate email. Please try again.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
+ except Exception as e:
174
+ st.error(f"❌ An error occurred: {str(e)}")
175
+ st.info("πŸ’‘ Please try again or contact support if the issue persists.")
176
+
177
+ # Usage stats
178
+ st.markdown("---")
179
+ st.markdown(f"πŸ“Š **Demo Stats:** {st.session_state.email_count} emails generated in this session")
180
+
181
+ # Feedback section
182
+ st.markdown("---")
183
+ st.subheader("πŸ’­ Feedback")
184
+ st.markdown("This is a demo version! Please let us know what you think:")
185
+
186
+ feedback_col1, feedback_col2 = st.columns(2)
187
+ with feedback_col1:
188
+ if st.button("πŸ‘ Great tool!"):
189
+ st.success("Thanks for the positive feedback!")
190
+ with feedback_col2:
191
+ if st.button("πŸ’‘ Suggestions"):
192
+ st.info("We'd love to hear your ideas! Please comment or reach out.")
 
 
 
193
 
194
  # Footer
195
  st.markdown("---")
196
  st.markdown(
197
  "<div style='text-align: center; color: #666;'>"
198
+ "<p>πŸš€ Built with Streamlit & Mistral-7B | πŸ’‘ Use quality company info for best results</p>"
199
  "<p>⚑ Powered by advanced AI with intelligent fallbacks for 100% success rate</p>"
200
  "</div>",
201
  unsafe_allow_html=True