ak0601 commited on
Commit
ef94105
·
verified ·
1 Parent(s): 2ab7b79

Update app_hug.py

Browse files
Files changed (1) hide show
  1. app_hug.py +0 -492
app_hug.py CHANGED
@@ -1,495 +1,3 @@
1
- # from fastapi import FastAPI, HTTPException, BackgroundTasks
2
- # from pydantic import BaseModel, EmailStr, Field
3
- # from typing import Optional, Tuple
4
- # from enum import Enum
5
- # import os
6
- # import base64
7
- # import pickle
8
- # import pandas as pd
9
- # from dotenv import load_dotenv
10
- # from langchain_openai import ChatOpenAI
11
- # from langchain.schema import HumanMessage, SystemMessage
12
- # from email.mime.text import MIMEText
13
- # from google.auth.transport.requests import Request
14
- # from google.oauth2.credentials import Credentials
15
- # from google_auth_oauthlib.flow import InstalledAppFlow
16
- # from googleapiclient.discovery import build
17
- # from googleapiclient.errors import HttpError
18
- # from datetime import datetime
19
- # import json
20
-
21
- # # Load environment variables (not needed on Hugging Face, but harmless)
22
- # load_dotenv()
23
-
24
- # # ------------------------------------------
25
- # # Helper: Write GOOGLE_CREDENTIALS_JSON to file if needed
26
- # # ------------------------------------------
27
- # def ensure_credentials_file():
28
- # credentials_env = os.getenv("GOOGLE_CREDENTIALS_JSON")
29
- # credentials_path = "credentials_SYNAPSE.json"
30
- # if not os.path.exists(credentials_path):
31
- # if not credentials_env:
32
- # raise Exception("GOOGLE_CREDENTIALS_JSON not found in environment variables.")
33
- # try:
34
- # parsed_json = json.loads(credentials_env)
35
- # except json.JSONDecodeError:
36
- # raise Exception("Invalid JSON in GOOGLE_CREDENTIALS_JSON")
37
- # with open(credentials_path, "w") as f:
38
- # json.dump(parsed_json, f, indent=2)
39
- # return credentials_path
40
-
41
- # # ------------------------------------------
42
- # # FastAPI app
43
- # # ------------------------------------------
44
- # app = FastAPI(title="Recruitment Message Generator API", version="1.0.0")
45
-
46
- # SCOPES = ["https://www.googleapis.com/auth/gmail.send"]
47
- # openai_api_key = os.getenv("OPENAI_API_KEY")
48
-
49
- # # ------------------------------------------
50
- # # Enums and Models
51
- # # ------------------------------------------
52
- # class MessageType(str, Enum):
53
- # OUTREACH = "outreach"
54
- # INTRODUCTORY = "introductory"
55
- # FOLLOWUP = "followup"
56
-
57
- # class GenerateMessageRequest(BaseModel):
58
- # job_evaluation: str
59
- # sender_email: EmailStr
60
- # reply_to_email: Optional[EmailStr] = Field(None, description="Recruiter's email for reply-to header")
61
- # recipient_email: EmailStr
62
- # candidate_name: str
63
- # current_role: str
64
- # current_company: str
65
- # company_name: str
66
- # role: str
67
- # recruiter_name: str
68
- # organisation: str
69
- # message_type: MessageType
70
- # send_email: bool = False
71
-
72
- # class FeedbackRequest(BaseModel):
73
- # message: str
74
- # feedback: str
75
-
76
- # class AuthenticateRequest(BaseModel):
77
- # email: EmailStr
78
-
79
- # class AuthenticateResponse(BaseModel):
80
- # success: bool
81
- # message: str
82
- # error: Optional[str] = None
83
-
84
- # class MessageResponse(BaseModel):
85
- # success: bool
86
- # message: str
87
- # email_sent: bool = False
88
- # email_subject: Optional[str] = None
89
- # error: Optional[str] = None
90
-
91
- # # ------------------------------------------
92
- # # Gmail Helper Functions
93
- # # ------------------------------------------
94
- # def get_token_file_path(email: str) -> str:
95
- # tokens_dir = "gmail_tokens"
96
- # if not os.path.exists(tokens_dir):
97
- # os.makedirs(tokens_dir)
98
- # safe_email = email.replace("@", "_at_").replace(".", "_dot_")
99
- # return os.path.join(tokens_dir, f"token_{safe_email}.pickle")
100
-
101
- # def check_user_token_exists(email: str) -> bool:
102
- # token_file = get_token_file_path(email)
103
- # return os.path.exists(token_file)
104
-
105
- # def load_user_credentials(email: str):
106
- # token_file = get_token_file_path(email)
107
- # if os.path.exists(token_file):
108
- # try:
109
- # with open(token_file, 'rb') as token:
110
- # creds = pickle.load(token)
111
- # return creds
112
- # except Exception:
113
- # if os.path.exists(token_file):
114
- # os.remove(token_file)
115
- # return None
116
-
117
- # def save_user_credentials(email: str, creds):
118
- # token_file = get_token_file_path(email)
119
- # with open(token_file, 'wb') as token:
120
- # pickle.dump(creds, token)
121
-
122
- # def create_new_credentials(email: str):
123
- # credentials_path = ensure_credentials_file()
124
- # flow = InstalledAppFlow.from_client_secrets_file(
125
- # credentials_path, SCOPES
126
- # )
127
- # creds = flow.run_local_server(port=0)
128
- # save_user_credentials(email, creds)
129
- # return creds
130
-
131
- # def authenticate_gmail(email: str, create_if_missing: bool = False):
132
- # creds = load_user_credentials(email)
133
- # if creds:
134
- # if creds.expired and creds.refresh_token:
135
- # try:
136
- # creds.refresh(Request())
137
- # save_user_credentials(email, creds)
138
- # except Exception:
139
- # if create_if_missing:
140
- # try:
141
- # creds = create_new_credentials(email)
142
- # except:
143
- # return None
144
- # else:
145
- # return None
146
- # elif not creds.valid:
147
- # creds = None
148
- # if not creds:
149
- # if create_if_missing:
150
- # try:
151
- # creds = create_new_credentials(email)
152
- # except:
153
- # return None
154
- # else:
155
- # return None
156
- # try:
157
- # service = build("gmail", "v1", credentials=creds)
158
- # return service
159
- # except Exception:
160
- # return None
161
-
162
- # def create_email_message(sender: str, to: str, subject: str, message_text: str, reply_to: Optional[str] = None):
163
- # message = MIMEText(message_text)
164
- # message["to"] = to
165
- # message["from"] = sender
166
- # message["subject"] = subject
167
- # if reply_to:
168
- # message["reply-to"] = reply_to
169
- # message["Cc"] = reply_to
170
- # raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
171
- # return {"raw": raw_message}
172
-
173
- # def send_gmail_message(service, user_id: str, message: dict):
174
- # try:
175
- # result = service.users().messages().send(userId=user_id, body=message).execute()
176
- # return result is not None
177
- # except HttpError:
178
- # return False
179
-
180
- # # ------------------------------------------
181
- # # LLM (OpenAI) Message Generation Helpers
182
- # # ------------------------------------------
183
- # def refine_message_with_feedback(
184
- # original_message: str,
185
- # feedback: str,
186
- # ) -> Tuple[str, str]:
187
- # api_key = os.getenv("OPENAI_API_KEY")
188
- # llm = ChatOpenAI(
189
- # model="gpt-4o-mini",
190
- # temperature=0.7,
191
- # max_tokens=600,
192
- # openai_api_key=api_key
193
- # )
194
- # prompt = f"""
195
- # Please refine the following recruitment message based on the provided feedback:
196
-
197
- # ORIGINAL MESSAGE:
198
- # {original_message}
199
-
200
- # FEEDBACK:
201
- # {feedback}
202
-
203
- # Please provide your response in the following format:
204
- # SUBJECT: [Your subject line here]
205
-
206
- # BODY:
207
- # [Your refined email body content here]
208
- # Keep the same tone and intent as the original message, but incorporate the feedback to improve it.
209
- # """
210
- # try:
211
- # messages = [
212
- # SystemMessage(content="You are a professional recruitment message writer. Refine the given message based on feedback while maintaining professionalism and the original intent."),
213
- # HumanMessage(content=prompt)
214
- # ]
215
- # response = llm.invoke(messages)
216
- # content = response.content.strip()
217
- # subject_line = ""
218
- # body_content = ""
219
- # lines = content.split('\n')
220
- # body_found = False
221
- # body_lines = []
222
- # for line in lines:
223
- # if line.strip().startswith('SUBJECT:'):
224
- # subject_line = line.replace('SUBJECT:', '').strip()
225
- # elif line.strip().startswith('BODY:'):
226
- # body_found = True
227
- # elif body_found and line.strip():
228
- # body_lines.append(line)
229
- # body_content = '\n'.join(body_lines).strip()
230
- # if not subject_line:
231
- # subject_line = "Recruitment Opportunity - Updated"
232
- # if not body_content:
233
- # body_content = content
234
- # return subject_line, body_content
235
- # except Exception as e:
236
- # raise HTTPException(status_code=500, detail=f"Error refining message: {str(e)}")
237
-
238
- # def generate_recruitment_message_with_subject(
239
- # msg_type: str,
240
- # company: str,
241
- # role_title: str,
242
- # recruiter: str,
243
- # org: str,
244
- # candidate: str,
245
- # current_pos: str,
246
- # evaluation: str,
247
- # feedback: Optional[str] = None
248
- # ) -> Tuple[str, str]:
249
- # api_key = os.getenv("OPENAI_API_KEY")
250
- # llm = ChatOpenAI(
251
- # model="gpt-4o-mini",
252
- # temperature=0.7,
253
- # max_tokens=600,
254
- # openai_api_key=api_key
255
- # )
256
- # base_prompt = f"""
257
- # Generate a professional recruitment {msg_type} with the following details:
258
- # - Company hiring: {company}
259
- # - Role: {role_title}
260
- # - Recruiter: {recruiter} from {org}
261
- # - Candidate: {candidate}
262
- # - Candidate's current position: {current_pos}
263
- # - Evaluation: {evaluation}
264
- # """
265
- # if msg_type == "outreach":
266
- # prompt = base_prompt + """
267
- # Create an initial outreach message that:
268
- # - Introduces the recruiter and organization
269
- # - Mentions the specific role and company
270
- # - Expresses interest in discussing the opportunity
271
- # - Keeps it short and to the point.
272
- # - Do not include any placeholders like [Candidate Name] or [Role Title] in the email.
273
- # """
274
- # elif msg_type == "introductory":
275
- # prompt = base_prompt + """
276
- # Create an introductory message that:
277
- # - Thanks the candidate for their initial response
278
- # - Provides more details about the role and company
279
- # - Explains why this opportunity aligns with their background
280
- # - Suggests next steps (like a call or meeting)
281
- # - Maintains a warm, professional tone
282
- # """
283
- # else: # followup
284
- # prompt = base_prompt + """
285
- # Create a follow-up message that:
286
- # - References previous communication
287
- # - Reiterates interest in the candidate
288
- # - Addresses any potential concerns
289
- # - Provides additional compelling reasons to consider the role
290
- # - Includes a clear call to action
291
- # """
292
- # if feedback:
293
- # prompt += f"\n\nPlease modify the message based on this feedback: {feedback}"
294
- # prompt += """
295
-
296
- # Please provide your response in the following format:
297
- # SUBJECT: [Your subject line here]
298
-
299
- # BODY:
300
- # [Your email body content here]
301
- # """
302
- # try:
303
- # messages = [
304
- # SystemMessage(content="You are a professional recruitment message writer. Generate both an email subject line and body content. Follow the exact format requested."),
305
- # HumanMessage(content=prompt)
306
- # ]
307
- # response = llm.invoke(messages)
308
- # content = response.content.strip()
309
- # subject_line = ""
310
- # body_content = ""
311
- # lines = content.split('\n')
312
- # body_found = False
313
- # body_lines = []
314
- # for line in lines:
315
- # if line.strip().startswith('SUBJECT:'):
316
- # subject_line = line.replace('SUBJECT:', '').strip()
317
- # elif line.strip().startswith('BODY:'):
318
- # body_found = True
319
- # elif body_found and line.strip():
320
- # body_lines.append(line)
321
- # body_content = '\n'.join(body_lines).strip()
322
- # if not subject_line:
323
- # subject_line = f"Opportunity at {company} - {role_title}"
324
- # if not body_content:
325
- # body_content = content
326
- # return subject_line, body_content
327
- # except Exception as e:
328
- # raise HTTPException(status_code=500, detail=f"Error generating message: {str(e)}")
329
-
330
- # # ------------------------------------------
331
- # # FastAPI Endpoints
332
- # # ------------------------------------------
333
- # @app.get("/")
334
- # async def root():
335
- # return {
336
- # "message": "Recruitment Message Generator API",
337
- # "version": "1.0.0",
338
- # "endpoints": [
339
- # "/generate-message",
340
- # "/refine-message",
341
- # "/authenticate",
342
- # "/docs"
343
- # ]
344
- # }
345
-
346
- # @app.post("/generate-message", response_model=MessageResponse)
347
- # async def generate_message(request: GenerateMessageRequest, background_tasks: BackgroundTasks):
348
- # try:
349
- # current_position = f"{request.current_role} at {request.current_company}"
350
- # email_subject, generated_message = generate_recruitment_message_with_subject(
351
- # msg_type=request.message_type.value.replace('followup', 'follow-up'),
352
- # company=request.company_name,
353
- # role_title=request.role,
354
- # recruiter=request.recruiter_name,
355
- # org=request.organisation,
356
- # candidate=request.candidate_name,
357
- # current_pos=current_position,
358
- # evaluation=request.job_evaluation
359
- # )
360
- # email_sent = False
361
- # if request.send_email:
362
- # registered_users = []
363
- # if os.path.exists("registered_users.csv"):
364
- # df = pd.read_csv("registered_users.csv")
365
- # registered_users = df['email'].tolist() if 'email' in df.columns else []
366
- # if request.sender_email.lower() not in [user.lower() for user in registered_users]:
367
- # return MessageResponse(
368
- # success=True,
369
- # message=generated_message,
370
- # email_sent=False,
371
- # email_subject=email_subject,
372
- # error="Email not sent: Sender email is not registered"
373
- # )
374
- # service = authenticate_gmail(request.sender_email)
375
- # if service:
376
- # email_message = create_email_message(
377
- # sender=request.sender_email,
378
- # to=request.recipient_email,
379
- # subject=email_subject,
380
- # message_text=generated_message,
381
- # reply_to=request.reply_to_email
382
- # )
383
- # email_sent = send_gmail_message(service, "me", email_message)
384
- # if not email_sent:
385
- # return MessageResponse(
386
- # success=True,
387
- # message=generated_message,
388
- # email_sent=False,
389
- # email_subject=email_subject,
390
- # error="Email not sent: Failed to send via Gmail API"
391
- # )
392
- # else:
393
- # return MessageResponse(
394
- # success=True,
395
- # message=generated_message,
396
- # email_sent=False,
397
- # email_subject=email_subject,
398
- # error="Email not sent: Gmail authentication failed"
399
- # )
400
- # return MessageResponse(
401
- # success=True,
402
- # message=generated_message,
403
- # email_sent=email_sent,
404
- # email_subject=email_subject
405
- # )
406
- # except Exception as e:
407
- # return MessageResponse(
408
- # success=False,
409
- # message="",
410
- # error=str(e)
411
- # )
412
-
413
- # @app.post("/refine-message", response_model=MessageResponse)
414
- # async def refine_message(request: FeedbackRequest):
415
- # try:
416
- # email_subject, refined_message = refine_message_with_feedback(
417
- # original_message=request.message,
418
- # feedback=request.feedback
419
- # )
420
- # return MessageResponse(
421
- # success=True,
422
- # message=refined_message,
423
- # email_sent=False,
424
- # email_subject=email_subject
425
- # )
426
- # except Exception as e:
427
- # return MessageResponse(
428
- # success=False,
429
- # message="",
430
- # error=str(e)
431
- # )
432
-
433
- # @app.post("/authenticate", response_model=AuthenticateResponse)
434
- # async def authenticate_user(request: AuthenticateRequest):
435
- # try:
436
- # if check_user_token_exists(request.email):
437
- # service = authenticate_gmail(request.email, create_if_missing=False)
438
- # if service:
439
- # return AuthenticateResponse(
440
- # success=True,
441
- # message="User already authenticated and token is valid"
442
- # )
443
- # else:
444
- # service = authenticate_gmail(request.email, create_if_missing=True)
445
- # if service:
446
- # return AuthenticateResponse(
447
- # success=True,
448
- # message="Token refreshed successfully"
449
- # )
450
- # else:
451
- # return AuthenticateResponse(
452
- # success=False,
453
- # message="Failed to refresh token",
454
- # error="Could not refresh existing token. Please check credentials.json"
455
- # )
456
- # else:
457
- # try:
458
- # creds = create_new_credentials(request.email)
459
- # if creds:
460
- # return AuthenticateResponse(
461
- # success=True,
462
- # message="Authentication successful. Token created and saved."
463
- # )
464
- # else:
465
- # return AuthenticateResponse(
466
- # success=False,
467
- # message="Authentication failed",
468
- # error="Failed to create credentials"
469
- # )
470
- # except Exception as e:
471
- # return AuthenticateResponse(
472
- # success=False,
473
- # message="Authentication failed",
474
- # error=str(e)
475
- # )
476
- # except Exception as e:
477
- # return AuthenticateResponse(
478
- # success=False,
479
- # message="Authentication error",
480
- # error=str(e)
481
- # )
482
-
483
- # @app.get("/health")
484
- # async def health_check():
485
- # return {"status": "healthy", "timestamp": datetime.utcnow().isoformat()}
486
-
487
- # if __name__ == "__main__":
488
- # import uvicorn
489
- # uvicorn.run(app, host="0.0.0.0", port=8000)
490
-
491
-
492
-
493
  from fastapi import FastAPI, HTTPException, BackgroundTasks
494
  from pydantic import BaseModel, EmailStr, Field
495
  from typing import Optional, Tuple
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from fastapi import FastAPI, HTTPException, BackgroundTasks
2
  from pydantic import BaseModel, EmailStr, Field
3
  from typing import Optional, Tuple