File size: 7,708 Bytes
37185e0
 
 
 
cdbe688
c400028
37185e0
 
c400028
 
 
 
 
 
 
 
052a8fc
e3f43f3
c400028
77c5125
c400028
77c5125
 
 
e3f43f3
77c5125
37185e0
bc5de14
 
 
 
 
 
0724750
bc5de14
0724750
 
bc5de14
 
 
0724750
bc5de14
 
 
 
 
0724750
87ccea1
77c5125
0724750
37185e0
0724750
37185e0
 
3be9484
77c5125
87ccea1
77c5125
 
bc5de14
0724750
77c5125
 
 
0724750
bc5de14
77c5125
 
bc5de14
 
 
 
 
0724750
bc5de14
77c5125
bc5de14
 
 
77c5125
87ccea1
c0d54a6
3be9484
37185e0
3be9484
 
 
 
 
 
0724750
37185e0
 
 
 
 
3be9484
37185e0
c0d54a6
37185e0
 
2bd7b24
09696f6
c400028
 
77c5125
c400028
bc5de14
77c5125
0724750
bc5de14
 
 
2bd7b24
0724750
77c5125
2bd7b24
0724750
c400028
2bd7b24
77c5125
 
 
 
c3d82ad
12d8a5c
87ccea1
2bd7b24
 
 
 
729192c
2bd7b24
729192c
 
12d8a5c
729192c
 
 
12d8a5c
2bd7b24
 
 
 
 
 
09696f6
2bd7b24
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import gradio as gr
import requests
import os

# Load API keys securely from environment variables
proxycurl_api_key = os.getenv("PROXYCURL_API_KEY")  # Add your Proxycurl API key to your environment variables
groq_api_key = os.getenv("GROQ_CLOUD_API_KEY")

# Function to use Proxycurl API to get the LinkedIn profile data
def get_linkedin_profile_via_proxycurl(linkedin_profile_url):
    headers = {
        "Authorization": f"Bearer {proxycurl_api_key}",
    }
    url = f"https://nubela.co/proxycurl/api/v2/linkedin?url={linkedin_profile_url}"
    
    response = requests.get(url, headers=headers)
    
    if response.status_code == 200:
        data = response.json()
        # Extract relevant skills and experiences from LinkedIn profile
        bio = data.get("summary", "No bio available")
        skills = data.get("skills", [])  # List of skills from the LinkedIn profile
        experiences = data.get("experiences", [])  # List of experiences from the LinkedIn profile
        return bio, skills, experiences
    else:
        return "Error: Unable to fetch LinkedIn profile", [], []

# Function to get company information via Proxycurl Company API
def get_company_info(company_name):
    headers = {
        "Authorization": f"Bearer {proxycurl_api_key}",
    }
    url = f"https://nubela.co/proxycurl/api/v2/linkedin/company?company_name={company_name}"
    
    response = requests.get(url, headers=headers)
    
    if response.status_code == 200:
        data = response.json()
        company_info = data.get("description", "No detailed company info available.")
        return company_info
    else:
        return "Error: Unable to fetch company information."

# Placeholder for role description; could be enhanced to scrape or fetch real role data
def get_role_description(role_name, company_name):
    return f"The role of {role_name} at {company_name} involves..."

# Helper function to call Groq Cloud LLM API to generate and correct the email
def generate_and_correct_email(bio, company_name, role, company_info, role_description, skills, experiences):
    url = "https://api.groq.com/openai/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {groq_api_key}",
        "Content-Type": "application/json",
    }
    
    # New, detailed prompt with emphasis on correlating LinkedIn skills and experience to the job role
    prompt = f"""
    Write a professional email applying for the {role} position at {company_name}.
    
    The candidate’s bio is: {bio}.
    
    The candidate's LinkedIn profile highlights the following skills: {', '.join(skills)}.
    The candidate has the following experiences relevant to the job: {', '.join([exp['title'] for exp in experiences])}.
    
    The email should:
    - Be professional, engaging, and customized to the company's culture and the role’s requirements.
    - Include relevant company details: {company_info}.
    - Highlight the candidate’s skills and experiences from LinkedIn, mapping them directly to the job's requirements. The role description is: {role_description}.
    - Emphasize how the candidate’s background aligns with the company’s values and mission.
    - Attract the company's attention by focusing on how the candidate's background can bring value to the role and the company's future goals.
    - Use a tone that is persuasive but not overly promotional.
    - End with a strong call to action, encouraging the company to schedule an interview to discuss how the candidate can contribute to their success.

    Structure the email as follows:
    1. **Introduction**: Briefly introduce the candidate and state the role they are applying for.
    2. **Skills & Experience**: Map the candidate’s skills and experience from LinkedIn to the job's key requirements.
    3. **Alignment with the Company**: Emphasize how the candidate’s background fits with the company's mission, values, and goals.
    4. **Call to Action**: Encourage the company to schedule an interview to further discuss the candidate’s fit for the role.
    
    Ensure that redundant sign-offs like 'Best regards' or 'Sincerely' are not included.
    """
    
    # Construct the data payload for the API request
    data = {
        "messages": [
            {
                "role": "user",
                "content": prompt
            }
        ],
        "model": "llama3-8b-8192"
    }
    
    response = requests.post(url, headers=headers, json=data)
    
    if response.status_code == 200:
        return response.json()["choices"][0]["message"]["content"].strip()
    else:
        print(f"Error: {response.status_code}, {response.text}")
        return "Error generating email. Please check your API key or try again later."

# Main function to create the email and allow for saving, editing, or copying
def create_email(name, company_name, role, email, phone, linkedin_profile_url):
    # Step 1: Fetch LinkedIn profile using Proxycurl API if LinkedIn URL is provided
    if linkedin_profile_url:
        bio, skills, experiences = get_linkedin_profile_via_proxycurl(linkedin_profile_url)
    else:
        bio = f"{name} is a professional."  # Default bio if no LinkedIn URL is provided
        skills, experiences = [], []
    
    # Step 2: Fetch company information and role description
    company_info = get_company_info(company_name)
    role_description = get_role_description(role, company_name)
    
    # Step 3: Generate the email using Groq Cloud LLM
    generated_email = generate_and_correct_email(bio, company_name, role, company_info, role_description, skills, experiences)
    
    # Step 4: Add the user's email, phone number, and LinkedIn profile to the signature
    signature = f"\n\nBest regards,\n{name}\nEmail: {email}\nPhone: {phone}\nLinkedIn: {linkedin_profile_url if linkedin_profile_url else 'Not provided'}"

    # Ensure the body doesn't include any redundant 'Best regards' or 'Sincerely' and just append our signature
    for phrase in ["Best regards", "Sincerely"]:
        if phrase in generated_email:
            generated_email = generated_email.split(phrase)[0].strip()

    # Return the final polished email with the signature
    return generated_email + signature

# Define interface with Gradio
def gradio_ui():
    # Define inputs
    name_input = gr.Textbox(label="Your Name", placeholder="Enter your name")
    
    company_name_input = gr.Textbox(label="Company Name or URL", placeholder="Enter the company name or website URL")
    role_input = gr.Textbox(label="Role Applying For", placeholder="Enter the role you are applying for")
    
    email_input = gr.Textbox(label="Your Email Address", placeholder="Enter your email address")
    phone_input = gr.Textbox(label="Your Phone Number", placeholder="Enter your phone number")
    linkedin_input = gr.Textbox(label="Your LinkedIn URL", placeholder="Enter your LinkedIn profile URL")  # New field for LinkedIn URL
    
    # Define output for the generated email
    email_output = gr.Textbox(label="Generated Email", placeholder="Your generated email will appear here", lines=10)
    
    # Create the Gradio interface
    demo = gr.Interface(
        fn=create_email,  # Function to call when the user submits
        inputs=[name_input, company_name_input, role_input, email_input, phone_input, linkedin_input],
        outputs=[email_output],
        title="Email Writing AI Agent",
        description="Generate a professional email for a job application by providing your basic info.",
        allow_flagging="never"  # Disable flagging
    )
    
    # Launch the Gradio app
    demo.launch()

# Start the Gradio app when running the script
if __name__ == "__main__":
    gradio_ui()