import os import requests import openai import gradio as gr from openai_swarm import Agent, Swarm # Fetch API keys from environment variables OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") PROXYCURL_API_KEY = os.getenv("PROXYCURL_API_KEY") FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY") # Function to fetch LinkedIn data using Proxycurl API def fetch_linkedin_data(linkedin_url): headers = {'Authorization': f'Bearer {PROXYCURL_API_KEY}'} response = requests.get(f"https://api.proxycurl.com/v1/linkedin/{linkedin_url}", headers=headers) if response.status_code == 200: return response.json() else: return {"error": "Unable to fetch LinkedIn data"} # Function to fetch company information using Firecrawl API def fetch_company_info(company_url): headers = {'Authorization': f'Bearer {FIRECRAWL_API_KEY}'} response = requests.get(f"https://api.firecrawl.com/v1/scrape?url={company_url}", headers=headers) if response.status_code == 200: return response.json() else: return {"error": "Unable to fetch company information"} # Function to structure the email using the "Start with Why" model def structure_email(user_data, linkedin_info, company_info): why = f"I am passionate about {company_info.get('mission', 'your mission')} because it aligns with my experience as {linkedin_info.get('current_role', 'a professional')}." how = f"My skills in {user_data['role']} match the requirements and goals of your organization." what = f"I can bring my experience in {linkedin_info.get('skills', 'relevant skills')} to help achieve {company_info.get('goal', 'your company goals')}." structured_input = f"{why}\n\n{how}\n\n{what}" return structured_input # Function to generate email content using Nvidia Nemotron LLM def generate_email_content(api_key, prompt): openai.api_key = api_key response = openai.Completion.create( model="nemotron-70b", prompt=prompt, max_tokens=500 ) return response.choices[0].text # Function to validate the generated email for professional tone and completeness def validate_email(email_content): # Basic validation: check if the email contains key sections (can be expanded) return "Why" in email_content and "How" in email_content and "What" in email_content # Define the ReAct Agent using Swarm framework class EmailAgent(Agent): def __init__(self, user_data): super().__init__() self.user_data = user_data self.iterations = 0 def act(self): linkedin_info = fetch_linkedin_data(self.user_data['linkedin_url']) company_info = fetch_company_info(self.user_data['company_url']) if "error" in linkedin_info or "error" in company_info: return "Error fetching data. Please check the LinkedIn and company URLs." prompt = structure_email(self.user_data, linkedin_info, company_info) email_content = generate_email_content(OPENAI_API_KEY, prompt) return email_content def react(self, output): # React based on the generated email's validity if validate_email(output): return output else: # If invalid, refine prompt or retry (up to 3 iterations) self.iterations += 1 if self.iterations < 3: refined_prompt = f"Refined: {output}" return generate_email_content(OPENAI_API_KEY, refined_prompt) else: return "Unable to generate a valid email after 3 attempts." # Define the main function to run the agent within the Swarm def run_agent(name, email, phone, linkedin_url, company_url, role): user_data = { "name": name, "email": email, "phone": phone, "linkedin_url": linkedin_url, "company_url": company_url, "role": role } # Initialize the swarm and add the EmailAgent email_swarm = Swarm() agent = EmailAgent(user_data) email_swarm.add_agent(agent) # Run the swarm to get the final email content result = email_swarm.run() return result # Set up the Gradio interface final_interface = gr.Interface( fn=run_agent, inputs=[ gr.Textbox(label="Name"), gr.Textbox(label="Email"), gr.Textbox(label="Phone Number"), gr.Textbox(label="LinkedIn Profile URL"), gr.Textbox(label="Company URL or Name"), gr.Textbox(label="Role Being Applied For") ], outputs="text", title="Email Writing AI Agent", description="Autonomously generate a professional email tailored to the job application." ) if __name__ == "__main__": final_interface.launch()