Spaces:
Runtime error
Runtime error
import gradio as gr | |
import requests | |
import os | |
# Load API keys securely from environment variables | |
proxycurl_api_key = os.getenv("PROXYCURL_API_KEY") # Proxycurl API key | |
groq_api_key = os.getenv("GROQ_CLOUD_API_KEY") # Groq Cloud API key | |
class EmailAgent: | |
def __init__(self, linkedin_url, company_name, role, word_limit): | |
self.linkedin_url = linkedin_url | |
self.company_name = company_name | |
self.role = role | |
self.word_limit = word_limit | |
self.bio = None | |
self.skills = [] | |
self.experiences = [] | |
self.company_info = None | |
self.role_description = None | |
# Reason: Decide what information is needed | |
def reason_about_data(self): | |
print("Reasoning: I need LinkedIn data, company info, and role description.") | |
if not self.linkedin_url: | |
print("Missing LinkedIn URL. Request from the user.") | |
if not self.company_name: | |
print("Missing company name. Request from the user.") | |
# Action: Fetch LinkedIn data via Proxycurl | |
def fetch_linkedin_data(self): | |
print("Action: Fetching LinkedIn data from Proxycurl.") | |
headers = { | |
"Authorization": f"Bearer {proxycurl_api_key}", | |
} | |
url = f"https://nubela.co/proxycurl/api/v2/linkedin?url={self.linkedin_url}" | |
response = requests.get(url, headers=headers) | |
if response.status_code == 200: | |
data = response.json() | |
self.bio = data.get("summary", "No bio available") | |
self.skills = data.get("skills", []) | |
self.experiences = data.get("experiences", []) | |
else: | |
print("Error: Unable to fetch LinkedIn profile.") | |
# Action: Fetch company information via Proxycurl | |
def fetch_company_info(self): | |
print(f"Action: Fetching company info for {self.company_name}.") | |
headers = { | |
"Authorization": f"Bearer {proxycurl_api_key}", | |
} | |
url = f"https://nubela.co/proxycurl/api/v2/linkedin/company?company_name={self.company_name}" | |
response = requests.get(url, headers=headers) | |
if response.status_code == 200: | |
data = response.json() | |
self.company_info = data.get("description", "No detailed company info available.") | |
else: | |
print(f"Error: Unable to fetch company info for {self.company_name}.") | |
# Action: Fetch role description | |
def fetch_role_description(self): | |
print(f"Action: Fetching role description for {self.role}.") | |
self.role_description = f"The role of {self.role} at {self.company_name} involves..." | |
# Reflection: Check if the data is sufficient to generate an email | |
def reflect_on_data(self): | |
print("Reflection: Do I have enough data to generate the email?") | |
if not self.bio or not self.skills or not self.company_info: | |
print("Missing some critical information. Need to gather more data.") | |
return False | |
return True | |
# Action: Generate the email using Groq Cloud LLM | |
def generate_email(self): | |
print("Action: Generating the email with the gathered information.") | |
prompt = f""" | |
Write a professional email applying for the {self.role} position at {self.company_name}. | |
The candidate’s bio is: {self.bio}. | |
The candidate's LinkedIn profile highlights the following skills: {', '.join(self.skills)}. | |
The candidate has the following experiences relevant to the job: {', '.join([exp['title'] for exp in self.experiences])}. | |
The email should be professional, concise, and tailored to the company's culture. | |
Use relevant company details: {self.company_info}. | |
Highlight the candidate’s skills and experiences from LinkedIn, and map them to the job's requirements: {self.role_description}. | |
The email should not exceed {self.word_limit} words. | |
""" | |
url = "https://api.groq.com/openai/v1/chat/completions" | |
headers = { | |
"Authorization": f"Bearer {groq_api_key}", | |
"Content-Type": "application/json", | |
} | |
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 loop following ReAct pattern | |
def run(self): | |
self.reason_about_data() # Reason | |
self.fetch_linkedin_data() # Action | |
self.fetch_company_info() # Action | |
self.fetch_role_description() # Action | |
if self.reflect_on_data(): # Reflection | |
return self.generate_email() # Final Action | |
else: | |
return "Error: Not enough data to generate the email." | |
# Define the Gradio interface and the main app logic | |
def gradio_ui(): | |
# Input fields | |
name_input = gr.Textbox(label="Your Name", placeholder="Enter your name") | |
company_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") | |
word_limit_slider = gr.Slider(minimum=50, maximum=300, step=10, label="Email Word Limit", value=150) # New slider for word limit | |
# Output field | |
email_output = gr.Textbox(label="Generated Email", placeholder="Your generated email will appear here", lines=10) | |
# Function to create and run the email agent | |
def create_email(name, company_name, role, email, phone, linkedin_profile_url, word_limit): | |
agent = EmailAgent(linkedin_profile_url, company_name, role, word_limit) | |
return agent.run() | |
# Gradio interface | |
demo = gr.Interface( | |
fn=create_email, | |
inputs=[name_input, company_input, role_input, email_input, phone_input, linkedin_input, word_limit_slider], | |
outputs=[email_output], | |
title="Email Writing AI Agent with ReAct", | |
description="Generate a professional email for a job application using LinkedIn data, company info, and role description.", | |
allow_flagging="never" | |
) | |
# Launch the Gradio app | |
demo.launch() | |
# Start the Gradio app when running the script | |
if __name__ == "__main__": | |
gradio_ui() | |