ak0601 commited on
Commit
b0167d8
·
verified ·
1 Parent(s): 22b512c

Upload 11 files

Browse files
app_hug.py ADDED
@@ -0,0 +1,487 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ recruiter_email: Optional[EmailStr] = None
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
+ raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
170
+ return {"raw": raw_message}
171
+
172
+ def send_gmail_message(service, user_id: str, message: dict):
173
+ try:
174
+ result = service.users().messages().send(userId=user_id, body=message).execute()
175
+ return result is not None
176
+ except HttpError:
177
+ return False
178
+
179
+ # ------------------------------------------
180
+ # LLM (OpenAI) Message Generation Helpers
181
+ # ------------------------------------------
182
+ def refine_message_with_feedback(
183
+ original_message: str,
184
+ feedback: str,
185
+ ) -> Tuple[str, str]:
186
+ api_key = os.getenv("OPENAI_API_KEY")
187
+ llm = ChatOpenAI(
188
+ model="gpt-4o-mini",
189
+ temperature=0.7,
190
+ max_tokens=600,
191
+ openai_api_key=api_key
192
+ )
193
+ prompt = f"""
194
+ Please refine the following recruitment message based on the provided feedback:
195
+
196
+ ORIGINAL MESSAGE:
197
+ {original_message}
198
+
199
+ FEEDBACK:
200
+ {feedback}
201
+
202
+ Please provide your response in the following format:
203
+ SUBJECT: [Your subject line here]
204
+
205
+ BODY:
206
+ [Your refined email body content here]
207
+ Keep the same tone and intent as the original message, but incorporate the feedback to improve it.
208
+ """
209
+ try:
210
+ messages = [
211
+ SystemMessage(content="You are a professional recruitment message writer. Refine the given message based on feedback while maintaining professionalism and the original intent."),
212
+ HumanMessage(content=prompt)
213
+ ]
214
+ response = llm.invoke(messages)
215
+ content = response.content.strip()
216
+ subject_line = ""
217
+ body_content = ""
218
+ lines = content.split('\n')
219
+ body_found = False
220
+ body_lines = []
221
+ for line in lines:
222
+ if line.strip().startswith('SUBJECT:'):
223
+ subject_line = line.replace('SUBJECT:', '').strip()
224
+ elif line.strip().startswith('BODY:'):
225
+ body_found = True
226
+ elif body_found and line.strip():
227
+ body_lines.append(line)
228
+ body_content = '\n'.join(body_lines).strip()
229
+ if not subject_line:
230
+ subject_line = "Recruitment Opportunity - Updated"
231
+ if not body_content:
232
+ body_content = content
233
+ return subject_line, body_content
234
+ except Exception as e:
235
+ raise HTTPException(status_code=500, detail=f"Error refining message: {str(e)}")
236
+
237
+ def generate_recruitment_message_with_subject(
238
+ msg_type: str,
239
+ company: str,
240
+ role_title: str,
241
+ recruiter: str,
242
+ org: str,
243
+ candidate: str,
244
+ current_pos: str,
245
+ evaluation: str,
246
+ feedback: Optional[str] = None
247
+ ) -> Tuple[str, str]:
248
+ api_key = os.getenv("OPENAI_API_KEY")
249
+ llm = ChatOpenAI(
250
+ model="gpt-4o-mini",
251
+ temperature=0.7,
252
+ max_tokens=600,
253
+ openai_api_key=api_key
254
+ )
255
+ base_prompt = f"""
256
+ Generate a professional recruitment {msg_type} with the following details:
257
+ - Company hiring: {company}
258
+ - Role: {role_title}
259
+ - Recruiter: {recruiter} from {org}
260
+ - Candidate: {candidate}
261
+ - Candidate's current position: {current_pos}
262
+ - Evaluation: {evaluation}
263
+ """
264
+ if msg_type == "outreach":
265
+ prompt = base_prompt + """
266
+ Create an initial outreach message that:
267
+ - Introduces the recruiter and organization
268
+ - Mentions the specific role and company
269
+ - Expresses interest in discussing the opportunity
270
+ - Keeps it short and to the point.
271
+ """
272
+ elif msg_type == "introductory":
273
+ prompt = base_prompt + """
274
+ Create an introductory message that:
275
+ - Thanks the candidate for their initial response
276
+ - Provides more details about the role and company
277
+ - Explains why this opportunity aligns with their background
278
+ - Suggests next steps (like a call or meeting)
279
+ - Maintains a warm, professional tone
280
+ """
281
+ else: # followup
282
+ prompt = base_prompt + """
283
+ Create a follow-up message that:
284
+ - References previous communication
285
+ - Reiterates interest in the candidate
286
+ - Addresses any potential concerns
287
+ - Provides additional compelling reasons to consider the role
288
+ - Includes a clear call to action
289
+ """
290
+ if feedback:
291
+ prompt += f"\n\nPlease modify the message based on this feedback: {feedback}"
292
+ prompt += """
293
+
294
+ Please provide your response in the following format:
295
+ SUBJECT: [Your subject line here]
296
+
297
+ BODY:
298
+ [Your email body content here]
299
+ """
300
+ try:
301
+ messages = [
302
+ SystemMessage(content="You are a professional recruitment message writer. Generate both an email subject line and body content. Follow the exact format requested."),
303
+ HumanMessage(content=prompt)
304
+ ]
305
+ response = llm.invoke(messages)
306
+ content = response.content.strip()
307
+ subject_line = ""
308
+ body_content = ""
309
+ lines = content.split('\n')
310
+ body_found = False
311
+ body_lines = []
312
+ for line in lines:
313
+ if line.strip().startswith('SUBJECT:'):
314
+ subject_line = line.replace('SUBJECT:', '').strip()
315
+ elif line.strip().startswith('BODY:'):
316
+ body_found = True
317
+ elif body_found and line.strip():
318
+ body_lines.append(line)
319
+ body_content = '\n'.join(body_lines).strip()
320
+ if not subject_line:
321
+ subject_line = f"Opportunity at {company} - {role_title}"
322
+ if not body_content:
323
+ body_content = content
324
+ return subject_line, body_content
325
+ except Exception as e:
326
+ raise HTTPException(status_code=500, detail=f"Error generating message: {str(e)}")
327
+
328
+ # ------------------------------------------
329
+ # FastAPI Endpoints
330
+ # ------------------------------------------
331
+ @app.get("/")
332
+ async def root():
333
+ return {
334
+ "message": "Recruitment Message Generator API",
335
+ "version": "1.0.0",
336
+ "endpoints": [
337
+ "/generate-message",
338
+ "/refine-message",
339
+ "/authenticate",
340
+ "/docs"
341
+ ]
342
+ }
343
+
344
+ @app.post("/generate-message", response_model=MessageResponse)
345
+ async def generate_message(request: GenerateMessageRequest, background_tasks: BackgroundTasks):
346
+ try:
347
+ current_position = f"{request.current_role} at {request.current_company}"
348
+ email_subject, generated_message = generate_recruitment_message_with_subject(
349
+ msg_type=request.message_type.value.replace('followup', 'follow-up'),
350
+ company=request.company_name,
351
+ role_title=request.role,
352
+ recruiter=request.recruiter_name,
353
+ org=request.organisation,
354
+ candidate=request.candidate_name,
355
+ current_pos=current_position,
356
+ evaluation=request.job_evaluation
357
+ )
358
+ email_sent = False
359
+ if request.send_email:
360
+ registered_users = []
361
+ if os.path.exists("registered_users.csv"):
362
+ df = pd.read_csv("registered_users.csv")
363
+ registered_users = df['email'].tolist() if 'email' in df.columns else []
364
+ if request.sender_email.lower() not in [user.lower() for user in registered_users]:
365
+ return MessageResponse(
366
+ success=True,
367
+ message=generated_message,
368
+ email_sent=False,
369
+ email_subject=email_subject,
370
+ error="Email not sent: Sender email is not registered"
371
+ )
372
+ service = authenticate_gmail(request.sender_email)
373
+ if service:
374
+ email_message = create_email_message(
375
+ sender=request.sender_email,
376
+ to=request.recipient_email,
377
+ subject=email_subject,
378
+ message_text=generated_message,
379
+ reply_to=request.recruiter_email
380
+ )
381
+ email_sent = send_gmail_message(service, "me", email_message)
382
+ if not email_sent:
383
+ return MessageResponse(
384
+ success=True,
385
+ message=generated_message,
386
+ email_sent=False,
387
+ email_subject=email_subject,
388
+ error="Email not sent: Failed to send via Gmail API"
389
+ )
390
+ else:
391
+ return MessageResponse(
392
+ success=True,
393
+ message=generated_message,
394
+ email_sent=False,
395
+ email_subject=email_subject,
396
+ error="Email not sent: Gmail authentication failed"
397
+ )
398
+ return MessageResponse(
399
+ success=True,
400
+ message=generated_message,
401
+ email_sent=email_sent,
402
+ email_subject=email_subject
403
+ )
404
+ except Exception as e:
405
+ return MessageResponse(
406
+ success=False,
407
+ message="",
408
+ error=str(e)
409
+ )
410
+
411
+ @app.post("/refine-message", response_model=MessageResponse)
412
+ async def refine_message(request: FeedbackRequest):
413
+ try:
414
+ email_subject, refined_message = refine_message_with_feedback(
415
+ original_message=request.message,
416
+ feedback=request.feedback
417
+ )
418
+ return MessageResponse(
419
+ success=True,
420
+ message=refined_message,
421
+ email_sent=False,
422
+ email_subject=email_subject
423
+ )
424
+ except Exception as e:
425
+ return MessageResponse(
426
+ success=False,
427
+ message="",
428
+ error=str(e)
429
+ )
430
+
431
+ @app.post("/authenticate", response_model=AuthenticateResponse)
432
+ async def authenticate_user(request: AuthenticateRequest):
433
+ try:
434
+ if check_user_token_exists(request.email):
435
+ service = authenticate_gmail(request.email, create_if_missing=False)
436
+ if service:
437
+ return AuthenticateResponse(
438
+ success=True,
439
+ message="User already authenticated and token is valid"
440
+ )
441
+ else:
442
+ service = authenticate_gmail(request.email, create_if_missing=True)
443
+ if service:
444
+ return AuthenticateResponse(
445
+ success=True,
446
+ message="Token refreshed successfully"
447
+ )
448
+ else:
449
+ return AuthenticateResponse(
450
+ success=False,
451
+ message="Failed to refresh token",
452
+ error="Could not refresh existing token. Please check credentials.json"
453
+ )
454
+ else:
455
+ try:
456
+ creds = create_new_credentials(request.email)
457
+ if creds:
458
+ return AuthenticateResponse(
459
+ success=True,
460
+ message="Authentication successful. Token created and saved."
461
+ )
462
+ else:
463
+ return AuthenticateResponse(
464
+ success=False,
465
+ message="Authentication failed",
466
+ error="Failed to create credentials"
467
+ )
468
+ except Exception as e:
469
+ return AuthenticateResponse(
470
+ success=False,
471
+ message="Authentication failed",
472
+ error=str(e)
473
+ )
474
+ except Exception as e:
475
+ return AuthenticateResponse(
476
+ success=False,
477
+ message="Authentication error",
478
+ error=str(e)
479
+ )
480
+
481
+ @app.get("/health")
482
+ async def health_check():
483
+ return {"status": "healthy", "timestamp": datetime.utcnow().isoformat()}
484
+
485
+ if __name__ == "__main__":
486
+ import uvicorn
487
+ uvicorn.run(app, host="0.0.0.0", port=8000)
gmail_tokens.csv ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ email,access_token,refresh_token,token_uri,client_id,client_secret,scopes,expiry,token
2
+ [email protected],ya29.a0AS3H6NwggjTEMH3RZ09JZnA_34k918mSE1hemVWoc3VtmiZf3h2AcrHJGmYNov6VNO7HSnouMe2XOVNY5jn3xmH0dCytDnRJV9fcu1WfiLHwBjLND2B8xK7KPPQ65WrwIRqG7uCmnt-4eQgNS20-5NMKoUy62qruYbR5xg5vaCgYKARISARYSFQHGX2MifkdYHkS26F8ymU9Plo40kA0175,1//0gdA8tU6VFZQgCgYIARAAGBASNwF-L9IrHULnmrqCQ0cm8T9b_823Tm0cvoOE5u-6_kIOSKR3vArNsPhOqoDWcwjhNEAMVCZf_a4,https://oauth2.googleapis.com/token,134246740312-hq134ss12i47b5tdqa6v9dvmpb34el7u.apps.googleusercontent.com,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,https://www.googleapis.com/auth/gmail.send,2025-06-30T06:48:02.130965,gmail_tokens\token_ali_at_getjobsbysynapse_dot_com.pickle
3
+ [email protected],ya29.a0AS3H6NyUUZzfX6k3YLaze3_oCfYlYO1NWBQoS5tL-lZMyPMGw-Bda36wtGuecucSgv3YV8nP-zJjnkr-CTtVz2advTmFGkWqoiKRwMbP3ds8Rc__sLhXXJyGocgodeG8_ZELZ7sbMu1yxE86wahIkUakPxDXTgKerIHsDUtIaCgYKAQ8SARASFQHGX2MiwN7pFdWL_KPNLT9ifc7GCw0175,1//0gvpymvUiojGZCgYIARAAGBASNwF-L9Ird8_yKPv3HWCxT9dhpWLR_KwYlBPOMIpiCcQnwhDqi6ac8-4oLhDPA6T9xNPdPy9URq4,https://oauth2.googleapis.com/token,134246740312-hq134ss12i47b5tdqa6v9dvmpb34el7u.apps.googleusercontent.com,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,https://www.googleapis.com/auth/gmail.send,2025-06-30T06:50:47.931799,gmail_tokens\token_ali_at_matchwithsynapse_dot_com.pickle
4
+ [email protected],ya29.a0AS3H6NyPysZGsyDxwn9jo5zHkwh1I2wycyfD8gjw655YGqslNR37j5WhFXewjT1JU5NFh1NbZCh-SeWuCOZp-_ZvGu7elsswsLg7_YMYx38XdNwnu-cVwdGhKT6TakikmCQMF7ATM8w_ykAbT75VX3Wz38Ho9pxrdsZWQVSkaCgYKAS4SARMSFQHGX2MigGQZccNrOEfc4Hr_8IPaJQ0175,1//0gyVDLQU8kisCCgYIARAAGBASNwF-L9IrNQZg0yHD_VnM3bU14X4ZlWEyY6fUqa5ltbnWW_j08egtAfNDw4AGkYvSwByoa_sv7Xw,https://oauth2.googleapis.com/token,134246740312-hq134ss12i47b5tdqa6v9dvmpb34el7u.apps.googleusercontent.com,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,https://www.googleapis.com/auth/gmail.send,2025-06-30T06:51:40.576934,gmail_tokens\token_ali_dot_tag_at_elitesrn_dot_com.pickle
5
+ [email protected],ya29.a0AS3H6NzBJGynA2pYXHOkfSU5S6_FnOLn6lu2jLg7gneTlwbxHGWcaXPtp6JFdATR2CSZmC8qHzyzTyRhDwqI1BUvXQqDdpgKTV7Px2l4bWXPCZzimWk-DbSIxBXolvTnrlDXWq5KsBV3sPkry6SB3v2nNaU-34MnFB1VdvGrwQaCgYKAdASARcSFQHGX2MiRaUEVWxUgmV_Pdcasc74-A0177,1//0gcLQ1zVYdP7yCgYIARAAGBASNwF-L9Ir9fu9m_IljS2LAxdVEnjEAxBzM4CCC7voPLqpUKlT9zHnzustS7fbx9cDq2QGuPFCbjI,https://oauth2.googleapis.com/token,667261841954-q5gdoc76bvcn3l72q993t2b62tfk8pvq.apps.googleusercontent.com,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,https://www.googleapis.com/auth/gmail.send,2025-06-30T06:58:01.533285,gmail_tokens\token_kapooraman2468_at_gmail_dot_com.pickle
gmail_tokens/token_ali_at_getjobsbysynapse_dot_com.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:09059e2904e3d5beed937b5fb1edfe78a77d15ce04905d50cb78b7f2cc52efbf
3
+ size 999
gmail_tokens/token_ali_at_matchwithsynapse_dot_com.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4b3d012ca1145c9a4f1400f3187f4b7c82b3d5f2cb5e4d392937865635fbd535
3
+ size 999
gmail_tokens/token_ali_dot_tag_at_elitesrn_dot_com.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bd0a5f5fd7484649823ef686bd91f0863f356d363b46a23dd736428033ff8f9e
3
+ size 999
gmail_tokens/token_ali_dot_taghikhani_at_getjobsbysynapse_dot_com.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:25082999b045e7be6d0a797766fef72b72e6a4df668d5087ad4ef95644b8d5da
3
+ size 999
gmail_tokens/token_aman_at_synapseint_dot_com.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cb3dd4b977b6ba88a47b8791490404dee73e80abeffe48108a7cc1a754261f6c
3
+ size 999
gmail_tokens/token_aman_dot_21ug3019_at_iiitranchi_dot_ac_dot_in.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:04b2555649ba9cb3282cc86c061691229a7bb37ad53b60df0992133757dd1aea
3
+ size 999
gmail_tokens/token_kapooraman2468_at_gmail_dot_com.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ebbba500ecaf05629d824c02dfdfec628f4e16d93cd6e50891a4eeb931eee991
3
+ size 1001
registered_users.csv ADDED
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ google_api_python_client
3
+ google_auth_oauthlib
4
+ langchain
5
+ langchain_openai
6
+ pandas
7
+ protobuf
8
+ psycopg2
9
+ psycopg2_binary
10
+ pydantic
11
+ python-dotenv
12
+ SQLAlchemy
13
+ streamlit
14
+ uvicorn