Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -9,6 +9,13 @@ import json
|
|
9 |
from pathlib import Path
|
10 |
from typing import Dict, List, Optional
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
def initialize_email_client():
|
13 |
sendgrid_key = os.environ.get("SENDGRID_API_KEY")
|
14 |
sender_email = os.environ.get("SENDER_EMAIL")
|
@@ -24,33 +31,63 @@ def initialize_email_client():
|
|
24 |
return None
|
25 |
|
26 |
class UserProfile:
|
27 |
-
def __init__(self
|
28 |
-
|
|
|
29 |
self._ensure_storage_exists()
|
30 |
|
31 |
def _ensure_storage_exists(self):
|
32 |
-
if not
|
33 |
-
|
34 |
-
|
35 |
|
36 |
def save_profile(self, profile_data: Dict) -> bool:
|
37 |
try:
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
return True
|
43 |
except Exception as e:
|
44 |
print(f"Error saving profile: {e}")
|
45 |
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
class EmailTemplate:
|
48 |
-
def __init__(self
|
49 |
-
|
|
|
50 |
self._ensure_templates_exist()
|
51 |
|
52 |
def _ensure_templates_exist(self):
|
53 |
-
if not
|
54 |
default_templates = {
|
55 |
"sales_pitch": {
|
56 |
"subject": "Innovative Solutions for {company}",
|
@@ -76,6 +113,11 @@ class EmailGenie:
|
|
76 |
self.sender_email = os.environ.get("SENDER_EMAIL")
|
77 |
self.user_profile = UserProfile()
|
78 |
self.email_template = EmailTemplate()
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
def structure_info(self, info: str) -> str:
|
81 |
prompt = f"Please structure and summarize the following information about a person or company: {info}"
|
@@ -86,13 +128,17 @@ class EmailGenie:
|
|
86 |
return chat_completion.choices[0].message.content
|
87 |
|
88 |
def generate_email(self, template_name: str, context: Dict) -> str:
|
|
|
|
|
|
|
89 |
template = self.email_template.get_template(template_name)
|
90 |
structured_info = self.structure_info(context.get('recipient_info', ''))
|
91 |
|
92 |
prompt = f"""
|
93 |
Using the following template and information, create a personalized email:
|
94 |
Template: {template}
|
95 |
-
Sender: {
|
|
|
96 |
Recipient: {context['recipient']}
|
97 |
Subject: {context['email_subject']}
|
98 |
Recipient Information: {structured_info}
|
@@ -105,9 +151,14 @@ class EmailGenie:
|
|
105 |
return chat_completion.choices[0].message.content
|
106 |
|
107 |
def preview_email(self, email_content: str) -> str:
|
108 |
-
|
|
|
|
|
109 |
|
110 |
def send_email(self, to_email: str, subject: str, content: str) -> tuple[bool, str]:
|
|
|
|
|
|
|
111 |
if not self.sendgrid_client or not self.sender_email:
|
112 |
return False, "Email sending is not configured"
|
113 |
|
@@ -135,8 +186,13 @@ def create_interface():
|
|
135 |
background_input = gr.Textbox(label="Professional Background")
|
136 |
target_input = gr.Textbox(label="Target Audience")
|
137 |
save_profile_btn = gr.Button("Save Profile")
|
|
|
138 |
|
139 |
with gr.Tab("Generate Email"):
|
|
|
|
|
|
|
|
|
140 |
template_dropdown = gr.Dropdown(
|
141 |
choices=["sales_pitch", "job_application"],
|
142 |
label="Select Template"
|
@@ -150,7 +206,7 @@ def create_interface():
|
|
150 |
with gr.Tab("Send Email"):
|
151 |
recipient_email = gr.Textbox(label="Recipient Email")
|
152 |
send_btn = gr.Button("Send Email")
|
153 |
-
status_output = gr.Textbox(label="Status")
|
154 |
|
155 |
def save_profile(name, industry, background, target):
|
156 |
profile_data = {
|
@@ -160,11 +216,19 @@ def create_interface():
|
|
160 |
"target_audience": target
|
161 |
}
|
162 |
success = emailgenie.user_profile.save_profile(profile_data)
|
|
|
|
|
163 |
return "Profile saved successfully!" if success else "Error saving profile"
|
164 |
|
|
|
|
|
|
|
|
|
165 |
def generate_email_handler(template, subject, recipient, info):
|
|
|
|
|
|
|
166 |
context = {
|
167 |
-
"sender_name": "Your Name", # Could be fetched from profile
|
168 |
"email_subject": subject,
|
169 |
"recipient": recipient,
|
170 |
"recipient_info": info
|
@@ -179,7 +243,13 @@ def create_interface():
|
|
179 |
save_profile_btn.click(
|
180 |
save_profile,
|
181 |
inputs=[name_input, industry_input, background_input, target_input],
|
182 |
-
outputs=
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
)
|
184 |
|
185 |
generate_btn.click(
|
|
|
9 |
from pathlib import Path
|
10 |
from typing import Dict, List, Optional
|
11 |
|
12 |
+
# Define the storage directory in the Hugging Face Space
|
13 |
+
STORAGE_DIR = os.environ.get('STORAGE_DIR', 'data')
|
14 |
+
|
15 |
+
def ensure_storage_dir():
|
16 |
+
"""Create storage directory if it doesn't exist"""
|
17 |
+
os.makedirs(STORAGE_DIR, exist_ok=True)
|
18 |
+
|
19 |
def initialize_email_client():
|
20 |
sendgrid_key = os.environ.get("SENDGRID_API_KEY")
|
21 |
sender_email = os.environ.get("SENDER_EMAIL")
|
|
|
31 |
return None
|
32 |
|
33 |
class UserProfile:
|
34 |
+
def __init__(self):
|
35 |
+
ensure_storage_dir()
|
36 |
+
self.storage_path = os.path.join(STORAGE_DIR, 'profiles.json')
|
37 |
self._ensure_storage_exists()
|
38 |
|
39 |
def _ensure_storage_exists(self):
|
40 |
+
if not os.path.exists(self.storage_path):
|
41 |
+
with open(self.storage_path, 'w') as f:
|
42 |
+
json.dump({"profiles": []}, f)
|
43 |
|
44 |
def save_profile(self, profile_data: Dict) -> bool:
|
45 |
try:
|
46 |
+
with open(self.storage_path, 'r') as f:
|
47 |
+
data = json.load(f)
|
48 |
+
|
49 |
+
# Update existing profile or add new one
|
50 |
+
profiles = data.get("profiles", [])
|
51 |
+
profile_exists = False
|
52 |
+
for i, profile in enumerate(profiles):
|
53 |
+
if profile.get("name") == profile_data["name"]:
|
54 |
+
profiles[i] = profile_data
|
55 |
+
profile_exists = True
|
56 |
+
break
|
57 |
+
|
58 |
+
if not profile_exists:
|
59 |
+
profiles.append(profile_data)
|
60 |
+
|
61 |
+
data["profiles"] = profiles
|
62 |
+
|
63 |
+
with open(self.storage_path, 'w') as f:
|
64 |
+
json.dump(data, f)
|
65 |
return True
|
66 |
except Exception as e:
|
67 |
print(f"Error saving profile: {e}")
|
68 |
return False
|
69 |
+
|
70 |
+
def get_profile(self, name: str) -> Optional[Dict]:
|
71 |
+
try:
|
72 |
+
with open(self.storage_path, 'r') as f:
|
73 |
+
data = json.load(f)
|
74 |
+
|
75 |
+
for profile in data.get("profiles", []):
|
76 |
+
if profile.get("name") == name:
|
77 |
+
return profile
|
78 |
+
return None
|
79 |
+
except Exception as e:
|
80 |
+
print(f"Error getting profile: {e}")
|
81 |
+
return None
|
82 |
|
83 |
class EmailTemplate:
|
84 |
+
def __init__(self):
|
85 |
+
ensure_storage_dir()
|
86 |
+
self.templates_path = os.path.join(STORAGE_DIR, 'templates.json')
|
87 |
self._ensure_templates_exist()
|
88 |
|
89 |
def _ensure_templates_exist(self):
|
90 |
+
if not os.path.exists(self.templates_path):
|
91 |
default_templates = {
|
92 |
"sales_pitch": {
|
93 |
"subject": "Innovative Solutions for {company}",
|
|
|
113 |
self.sender_email = os.environ.get("SENDER_EMAIL")
|
114 |
self.user_profile = UserProfile()
|
115 |
self.email_template = EmailTemplate()
|
116 |
+
self.current_profile = None
|
117 |
+
|
118 |
+
def set_current_profile(self, name: str):
|
119 |
+
self.current_profile = self.user_profile.get_profile(name)
|
120 |
+
return self.current_profile is not None
|
121 |
|
122 |
def structure_info(self, info: str) -> str:
|
123 |
prompt = f"Please structure and summarize the following information about a person or company: {info}"
|
|
|
128 |
return chat_completion.choices[0].message.content
|
129 |
|
130 |
def generate_email(self, template_name: str, context: Dict) -> str:
|
131 |
+
if not self.current_profile:
|
132 |
+
return "Please set up your profile first."
|
133 |
+
|
134 |
template = self.email_template.get_template(template_name)
|
135 |
structured_info = self.structure_info(context.get('recipient_info', ''))
|
136 |
|
137 |
prompt = f"""
|
138 |
Using the following template and information, create a personalized email:
|
139 |
Template: {template}
|
140 |
+
Sender: {self.current_profile['name']} ({self.current_profile['industry']})
|
141 |
+
Sender Background: {self.current_profile['background']}
|
142 |
Recipient: {context['recipient']}
|
143 |
Subject: {context['email_subject']}
|
144 |
Recipient Information: {structured_info}
|
|
|
151 |
return chat_completion.choices[0].message.content
|
152 |
|
153 |
def preview_email(self, email_content: str) -> str:
|
154 |
+
if not self.current_profile:
|
155 |
+
return "Please set up your profile first."
|
156 |
+
return f"=== Email Preview ===\nFrom: {self.current_profile['name']}\n\n{email_content}"
|
157 |
|
158 |
def send_email(self, to_email: str, subject: str, content: str) -> tuple[bool, str]:
|
159 |
+
if not self.current_profile:
|
160 |
+
return False, "Please set up your profile first."
|
161 |
+
|
162 |
if not self.sendgrid_client or not self.sender_email:
|
163 |
return False, "Email sending is not configured"
|
164 |
|
|
|
186 |
background_input = gr.Textbox(label="Professional Background")
|
187 |
target_input = gr.Textbox(label="Target Audience")
|
188 |
save_profile_btn = gr.Button("Save Profile")
|
189 |
+
profile_status = gr.Textbox(label="Status", interactive=False)
|
190 |
|
191 |
with gr.Tab("Generate Email"):
|
192 |
+
profile_name = gr.Textbox(label="Your Profile Name")
|
193 |
+
load_profile_btn = gr.Button("Load Profile")
|
194 |
+
profile_load_status = gr.Textbox(label="Profile Status", interactive=False)
|
195 |
+
|
196 |
template_dropdown = gr.Dropdown(
|
197 |
choices=["sales_pitch", "job_application"],
|
198 |
label="Select Template"
|
|
|
206 |
with gr.Tab("Send Email"):
|
207 |
recipient_email = gr.Textbox(label="Recipient Email")
|
208 |
send_btn = gr.Button("Send Email")
|
209 |
+
status_output = gr.Textbox(label="Status", interactive=False)
|
210 |
|
211 |
def save_profile(name, industry, background, target):
|
212 |
profile_data = {
|
|
|
216 |
"target_audience": target
|
217 |
}
|
218 |
success = emailgenie.user_profile.save_profile(profile_data)
|
219 |
+
if success:
|
220 |
+
emailgenie.set_current_profile(name)
|
221 |
return "Profile saved successfully!" if success else "Error saving profile"
|
222 |
|
223 |
+
def load_profile(name):
|
224 |
+
success = emailgenie.set_current_profile(name)
|
225 |
+
return "Profile loaded successfully!" if success else "Profile not found"
|
226 |
+
|
227 |
def generate_email_handler(template, subject, recipient, info):
|
228 |
+
if not emailgenie.current_profile:
|
229 |
+
return "Please load your profile first"
|
230 |
+
|
231 |
context = {
|
|
|
232 |
"email_subject": subject,
|
233 |
"recipient": recipient,
|
234 |
"recipient_info": info
|
|
|
243 |
save_profile_btn.click(
|
244 |
save_profile,
|
245 |
inputs=[name_input, industry_input, background_input, target_input],
|
246 |
+
outputs=profile_status
|
247 |
+
)
|
248 |
+
|
249 |
+
load_profile_btn.click(
|
250 |
+
load_profile,
|
251 |
+
inputs=[profile_name],
|
252 |
+
outputs=profile_load_status
|
253 |
)
|
254 |
|
255 |
generate_btn.click(
|