siddhartharya commited on
Commit
bff2e53
·
verified ·
1 Parent(s): 5e249c4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -51
app.py CHANGED
@@ -12,6 +12,10 @@ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
12
  PROXYCURL_API_KEY = os.getenv("PROXYCURL_API_KEY")
13
  FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY")
14
 
 
 
 
 
15
  # Function to fetch LinkedIn data using the Proxycurl API
16
  def fetch_linkedin_data(linkedin_url):
17
  api_key = os.getenv("PROXYCURL_API_KEY")
@@ -19,16 +23,20 @@ def fetch_linkedin_data(linkedin_url):
19
  api_endpoint = 'https://nubela.co/proxycurl/api/v2/linkedin'
20
 
21
  logging.info("Fetching LinkedIn data...")
22
- response = requests.get(api_endpoint,
23
- params={'url': linkedin_url},
24
- headers=headers,
25
- timeout=10)
26
- if response.status_code == 200:
27
- logging.info("LinkedIn data fetched successfully.")
28
- return response.json()
29
- else:
30
- logging.error(f"Error fetching LinkedIn data: {response.text}")
31
- return {"error": f"Error fetching LinkedIn data: {response.text}"}
 
 
 
 
32
 
33
  # Function to fetch company information using Firecrawl API
34
  def fetch_company_info(company_url):
@@ -48,53 +56,60 @@ def fetch_company_info(company_url):
48
  }
49
 
50
  logging.info("Fetching company information...")
51
- response = requests.post(api_endpoint, json=data, headers=headers, timeout=15)
52
- if response.status_code == 200:
53
- logging.info("Company information fetched successfully.")
54
- return response.json()
55
- else:
56
- logging.error(f"Error fetching company information: {response.text}")
57
- return {"error": f"Error fetching company information: {response.text}"}
 
 
 
 
58
 
59
  # Function to structure the email dynamically based on inputs and fetched data
60
  def structure_email(user_data, linkedin_info, company_info):
61
- # Fetch relevant information from the LinkedIn profile and company information
62
- linkedin_role = linkedin_info.get('current_role', 'a professional')
63
- linkedin_skills = linkedin_info.get('skills', 'various relevant skills')
64
- company_mission = company_info.get('mission', 'your mission')
65
- company_goal = company_info.get('goal', 'achieving excellence in the field')
66
-
67
- # Construct the dynamic email content based on the provided and fetched information
68
- email_content = (
69
- f"Dear Hiring Manager,\n\n"
70
- f"I am writing to express my enthusiasm for the {user_data['role']} position at {user_data['company_url']}. "
71
- f"The mission of {company_mission} resonates deeply with me, as my professional experience aligns closely with this vision.\n\n"
72
- f"Having worked as {linkedin_role}, I have developed skills in {linkedin_skills}. These skills match the needs of your organization, "
73
- f"and I am confident in my ability to contribute effectively to {company_goal}.\n\n"
74
- f"I am eager to bring my expertise in {linkedin_skills} to your team, focusing on achieving key objectives and supporting your projects. "
75
- f"My goal is to make a meaningful impact and collaborate with like-minded professionals committed to excellence.\n\n"
76
- f"I would appreciate the opportunity to discuss how my background and skills align with the needs of {user_data['company_url']}. "
77
- f"Please find my resume attached for a more detailed overview of my qualifications.\n\n"
78
- f"Thank you for your time and consideration. I look forward to the possibility of contributing to your team.\n\n"
79
- f"Best regards,\n"
80
- f"{user_data['name']}"
81
- )
82
- return email_content
 
 
 
 
 
 
 
 
 
 
83
 
84
- # Function to validate the generated email for professional tone and completeness
85
  def validate_email(email_content):
86
  logging.info("Validating email content...")
87
  logging.info(f"Email Content for Validation: {email_content}")
88
 
89
- # Check if the generated email contains essential elements
90
- if ("enthusiasm" in email_content and
91
- "skills" in email_content and
92
- "contribute" in email_content):
93
- logging.info("Email content validation passed.")
94
- return True
95
- else:
96
- logging.info("Email content validation failed.")
97
- return False
98
 
99
  # Function to generate email content using Nvidia Nemotron LLM (non-streaming for simplicity)
100
  def generate_email_content(api_key, prompt):
@@ -113,13 +128,12 @@ def generate_email_content(api_key, prompt):
113
  temperature=0.5,
114
  top_p=1,
115
  max_tokens=1024,
116
- stream=False # Disable streaming for simplicity
117
  )
118
 
119
  if hasattr(response, 'choices') and len(response.choices) > 0:
120
  email_content = response.choices[0].message.content
121
  logging.info("Email content generated successfully.")
122
- logging.info(f"Generated Email Content: {email_content}")
123
  return email_content
124
  else:
125
  logging.error("Error: No choices found in the response.")
 
12
  PROXYCURL_API_KEY = os.getenv("PROXYCURL_API_KEY")
13
  FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY")
14
 
15
+ # Function to sanitize data by ensuring it's safe and clean for use
16
+ def sanitize_data(data, default_value=""):
17
+ return data.strip() if isinstance(data, str) and data.strip() else default_value
18
+
19
  # Function to fetch LinkedIn data using the Proxycurl API
20
  def fetch_linkedin_data(linkedin_url):
21
  api_key = os.getenv("PROXYCURL_API_KEY")
 
23
  api_endpoint = 'https://nubela.co/proxycurl/api/v2/linkedin'
24
 
25
  logging.info("Fetching LinkedIn data...")
26
+ try:
27
+ response = requests.get(api_endpoint,
28
+ params={'url': linkedin_url},
29
+ headers=headers,
30
+ timeout=10)
31
+ if response.status_code == 200:
32
+ logging.info("LinkedIn data fetched successfully.")
33
+ return response.json()
34
+ else:
35
+ logging.error(f"Error fetching LinkedIn data: {response.text}")
36
+ return {"error": f"Error fetching LinkedIn data: {response.text}"}
37
+ except Exception as e:
38
+ logging.error(f"Exception during LinkedIn data fetch: {e}")
39
+ return {"error": f"Exception during LinkedIn data fetch: {e}"}
40
 
41
  # Function to fetch company information using Firecrawl API
42
  def fetch_company_info(company_url):
 
56
  }
57
 
58
  logging.info("Fetching company information...")
59
+ try:
60
+ response = requests.post(api_endpoint, json=data, headers=headers, timeout=15)
61
+ if response.status_code == 200:
62
+ logging.info("Company information fetched successfully.")
63
+ return response.json()
64
+ else:
65
+ logging.error(f"Error fetching company information: {response.text}")
66
+ return {"error": f"Error fetching company information: {response.text}"}
67
+ except Exception as e:
68
+ logging.error(f"Exception during company info fetch: {e}")
69
+ return {"error": f"Exception during company info fetch: {e}"}
70
 
71
  # Function to structure the email dynamically based on inputs and fetched data
72
  def structure_email(user_data, linkedin_info, company_info):
73
+ # Sanitize and extract the required information
74
+ linkedin_role = sanitize_data(linkedin_info.get('current_role', user_data['role']))
75
+ linkedin_skills = sanitize_data(linkedin_info.get('skills', 'relevant skills'))
76
+ linkedin_industry = sanitize_data(linkedin_info.get('industry', 'the industry'))
77
+ company_name = sanitize_data(user_data['company_url'] or company_info.get('company_name', 'the company'))
78
+ company_mission = sanitize_data(company_info.get('mission', f"{company_name}'s mission"))
79
+ company_goal = sanitize_data(company_info.get('goal', 'achieving excellence'))
80
+
81
+ # Construct the email dynamically based on the sanitized and available data
82
+ email_body = f"Dear Hiring Manager,\n\n"
83
+
84
+ # Introduction and relevance
85
+ email_body += f"I am writing to express my interest in the {sanitize_data(user_data['role'])} position at {company_name}. "
86
+ if company_mission:
87
+ email_body += f"{company_mission} strongly aligns with my passion and experience in {linkedin_industry}. "
88
+
89
+ # Skills and experience section
90
+ if linkedin_role:
91
+ email_body += f"As a {linkedin_role}, I have honed my skills in {linkedin_skills}. These experiences make me confident that I can contribute effectively to your team. "
92
+ else:
93
+ email_body += f"My experience in {linkedin_skills} equips me with the skills necessary to excel in this role. "
94
+
95
+ # Contribution and impact section
96
+ if company_goal:
97
+ email_body += f"I am excited about the opportunity to bring my expertise to {company_name} and support your team in achieving {company_goal}. "
98
+
99
+ # Call to action
100
+ email_body += f"I would welcome the chance to discuss how my background and skills align with the needs of your organization. "
101
+ email_body += "Thank you for your time and consideration. I look forward to the possibility of contributing to your team.\n\n"
102
+ email_body += f"Best regards,\n{sanitize_data(user_data['name'])}"
103
+
104
+ return email_body
105
 
106
+ # Function to validate the generated email for completeness and professionalism
107
  def validate_email(email_content):
108
  logging.info("Validating email content...")
109
  logging.info(f"Email Content for Validation: {email_content}")
110
 
111
+ # Check if essential elements exist in the email content
112
+ return all(keyword in email_content for keyword in ["interest", "skills", "experience", "contribute", "Best regards"])
 
 
 
 
 
 
 
113
 
114
  # Function to generate email content using Nvidia Nemotron LLM (non-streaming for simplicity)
115
  def generate_email_content(api_key, prompt):
 
128
  temperature=0.5,
129
  top_p=1,
130
  max_tokens=1024,
131
+ stream=False
132
  )
133
 
134
  if hasattr(response, 'choices') and len(response.choices) > 0:
135
  email_content = response.choices[0].message.content
136
  logging.info("Email content generated successfully.")
 
137
  return email_content
138
  else:
139
  logging.error("Error: No choices found in the response.")