Update app.py
Browse files
app.py
CHANGED
|
@@ -5,6 +5,7 @@ import os
|
|
| 5 |
# Load API keys securely from environment variables
|
| 6 |
proxycurl_api_key = os.getenv("PROXYCURL_API_KEY") # Add your Proxycurl API key to your environment variables
|
| 7 |
groq_api_key = os.getenv("GROQ_CLOUD_API_KEY")
|
|
|
|
| 8 |
|
| 9 |
# Function to use Proxycurl API to get the LinkedIn profile data
|
| 10 |
def get_linkedin_profile_via_proxycurl(linkedin_profile_url):
|
|
@@ -22,27 +23,52 @@ def get_linkedin_profile_via_proxycurl(linkedin_profile_url):
|
|
| 22 |
else:
|
| 23 |
return "Error: Unable to fetch LinkedIn profile"
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
# Helper function to call Groq Cloud LLM API to generate and correct the email
|
| 26 |
-
def generate_and_correct_email(bio, company_name, role):
|
| 27 |
-
url = "https://api.groq.com/openai/v1/chat/completions"
|
| 28 |
headers = {
|
| 29 |
-
"Authorization": f"Bearer {groq_api_key}",
|
| 30 |
"Content-Type": "application/json",
|
| 31 |
}
|
| 32 |
|
| 33 |
-
# Updated prompt
|
| 34 |
prompt = f"""
|
| 35 |
-
Write a professional email applying for the {role} position at {company_name}.
|
| 36 |
-
Use this bio: {bio}.
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
-
|
| 43 |
-
-
|
| 44 |
-
-
|
| 45 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
"""
|
| 47 |
|
| 48 |
# Construct the data payload for the API request
|
|
@@ -53,16 +79,14 @@ def generate_and_correct_email(bio, company_name, role):
|
|
| 53 |
"content": prompt
|
| 54 |
}
|
| 55 |
],
|
| 56 |
-
"model": "llama3-8b-8192"
|
| 57 |
}
|
| 58 |
|
| 59 |
response = requests.post(url, headers=headers, json=data)
|
| 60 |
|
| 61 |
if response.status_code == 200:
|
| 62 |
-
# Extract the generated email content from the API response
|
| 63 |
return response.json()["choices"][0]["message"]["content"].strip()
|
| 64 |
else:
|
| 65 |
-
# Print or log the error for debugging
|
| 66 |
print(f"Error: {response.status_code}, {response.text}")
|
| 67 |
return "Error generating email. Please check your API key or try again later."
|
| 68 |
|
|
@@ -72,12 +96,15 @@ def create_email(name, company_name, role, email, phone, linkedin_profile_url):
|
|
| 72 |
if linkedin_profile_url:
|
| 73 |
bio = get_linkedin_profile_via_proxycurl(linkedin_profile_url)
|
| 74 |
else:
|
| 75 |
-
bio = f"{name} is a professional."
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
-
# Step
|
| 78 |
-
generated_email = generate_and_correct_email(bio, company_name, role)
|
| 79 |
|
| 80 |
-
# Step
|
| 81 |
signature = f"\n\nBest regards,\n{name}\nEmail: {email}\nPhone: {phone}\nLinkedIn: {linkedin_profile_url if linkedin_profile_url else 'Not provided'}"
|
| 82 |
|
| 83 |
# Ensure the body doesn't include any redundant 'Best regards' and just append our signature
|
|
|
|
| 5 |
# Load API keys securely from environment variables
|
| 6 |
proxycurl_api_key = os.getenv("PROXYCURL_API_KEY") # Add your Proxycurl API key to your environment variables
|
| 7 |
groq_api_key = os.getenv("GROQ_CLOUD_API_KEY")
|
| 8 |
+
serpapi_key = os.getenv("SERPAPI_API_KEY") # Add your SerpAPI key to your environment variables
|
| 9 |
|
| 10 |
# Function to use Proxycurl API to get the LinkedIn profile data
|
| 11 |
def get_linkedin_profile_via_proxycurl(linkedin_profile_url):
|
|
|
|
| 23 |
else:
|
| 24 |
return "Error: Unable to fetch LinkedIn profile"
|
| 25 |
|
| 26 |
+
# Function to use SerpAPI to fetch company and role information
|
| 27 |
+
def get_company_and_role_info(company_name, role):
|
| 28 |
+
query = f"{company_name} {role} job description"
|
| 29 |
+
url = f"https://serpapi.com/search.json?engine=google&q={query}&api_key={serpapi_key}"
|
| 30 |
+
|
| 31 |
+
response = requests.get(url)
|
| 32 |
+
|
| 33 |
+
if response.status_code == 200:
|
| 34 |
+
results = response.json()
|
| 35 |
+
# Extract information about the company and role from the search results
|
| 36 |
+
company_info = []
|
| 37 |
+
for result in results.get("organic_results", []):
|
| 38 |
+
if "linkedin.com" not in result.get("link", ""):
|
| 39 |
+
company_info.append(result.get("snippet", ""))
|
| 40 |
+
return "\n".join(company_info[:2]) # Limit to 2 top results
|
| 41 |
+
else:
|
| 42 |
+
return "Error fetching company and role information."
|
| 43 |
+
|
| 44 |
# Helper function to call Groq Cloud LLM API to generate and correct the email
|
| 45 |
+
def generate_and_correct_email(bio, company_name, role, company_info):
|
| 46 |
+
url = "https://api.groq.com/openai/v1/chat/completions"
|
| 47 |
headers = {
|
| 48 |
+
"Authorization": f"Bearer {groq_api_key}",
|
| 49 |
"Content-Type": "application/json",
|
| 50 |
}
|
| 51 |
|
| 52 |
+
# Updated prompt with a focus on professionalism, relevance, and creativity
|
| 53 |
prompt = f"""
|
| 54 |
+
Write a professional, concise, and compelling email applying for the {role} position at {company_name}.
|
| 55 |
+
Use this bio to highlight the candidate's skills and experience: {bio}.
|
| 56 |
+
|
| 57 |
+
Additionally, here is some information about the company and the role:
|
| 58 |
+
{company_info}
|
| 59 |
+
|
| 60 |
+
The email should:
|
| 61 |
+
- Be professional, creative, and tailored to the company and role.
|
| 62 |
+
- Creatively emphasize the candidate’s key skills and experience, aligning them with the job's requirements.
|
| 63 |
+
- Attract the company's attention by focusing on how the candidate's background can bring value to the role and company.
|
| 64 |
+
- Be concise but engaging, leaving a strong impression on the recruiter.
|
| 65 |
+
- Include a clear call to action, encouraging the company to interview the candidate.
|
| 66 |
+
|
| 67 |
+
Structure the email as follows:
|
| 68 |
+
1. **Introduction**: Briefly introduce the candidate and the role they are applying for.
|
| 69 |
+
2. **Skills & Experience**: Creatively map the candidate’s skills and experience to the job's key requirements, focusing on relevance.
|
| 70 |
+
3. **Value Proposition**: Highlight how the candidate’s experience will contribute to the company's success.
|
| 71 |
+
4. **Call to Action**: Encourage the company to set up an interview to explore how the candidate can add value.
|
| 72 |
"""
|
| 73 |
|
| 74 |
# Construct the data payload for the API request
|
|
|
|
| 79 |
"content": prompt
|
| 80 |
}
|
| 81 |
],
|
| 82 |
+
"model": "llama3-8b-8192"
|
| 83 |
}
|
| 84 |
|
| 85 |
response = requests.post(url, headers=headers, json=data)
|
| 86 |
|
| 87 |
if response.status_code == 200:
|
|
|
|
| 88 |
return response.json()["choices"][0]["message"]["content"].strip()
|
| 89 |
else:
|
|
|
|
| 90 |
print(f"Error: {response.status_code}, {response.text}")
|
| 91 |
return "Error generating email. Please check your API key or try again later."
|
| 92 |
|
|
|
|
| 96 |
if linkedin_profile_url:
|
| 97 |
bio = get_linkedin_profile_via_proxycurl(linkedin_profile_url)
|
| 98 |
else:
|
| 99 |
+
bio = f"{name} is a professional."
|
| 100 |
+
|
| 101 |
+
# Step 2: Fetch company and role information using SerpAPI
|
| 102 |
+
company_info = get_company_and_role_info(company_name, role)
|
| 103 |
|
| 104 |
+
# Step 3: Generate the email using Groq Cloud LLM
|
| 105 |
+
generated_email = generate_and_correct_email(bio, company_name, role, company_info)
|
| 106 |
|
| 107 |
+
# Step 4: Add the user's email, phone number, and LinkedIn profile to the signature
|
| 108 |
signature = f"\n\nBest regards,\n{name}\nEmail: {email}\nPhone: {phone}\nLinkedIn: {linkedin_profile_url if linkedin_profile_url else 'Not provided'}"
|
| 109 |
|
| 110 |
# Ensure the body doesn't include any redundant 'Best regards' and just append our signature
|