CareerAgent / app.py
TouradAi's picture
Update application file
f7ade35
raw
history blame
18.1 kB
"""
Career Agent - Intelligent CV and Cover Letter Generator
========================================================
An AI agent that autonomously analyzes job postings and candidate profiles
to create tailored application documents using multi-step reasoning.
Author: Career Agent Team
Version: 1.1 - SambaNova Edition
"""
import os
import logging
import gradio as gr
from typing import Optional, Dict, Any
from dotenv import load_dotenv
from openai import OpenAI
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Load environment variables
load_dotenv()
# === SambaNova API Integration ===
class SambaNovaClient:
"""SambaNova client using OpenAI SDK."""
def __init__(self, api_key: str, model_name: str = "Meta-Llama-3.3-70B-Instruct"):
self.client = OpenAI(
api_key=api_key,
base_url="https://api.sambanova.ai/v1"
)
self.model_name = model_name
def generate(self, prompt: str, system_prompt: str = "You are a helpful assistant.") -> str:
"""Generate response using SambaNova API."""
try:
response = self.client.chat.completions.create(
model=self.model_name,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
],
temperature=0.1,
top_p=0.1,
max_tokens=3000
)
return response.choices[0].message.content or ""
except Exception as e:
logger.error(f"SambaNova API call failed: {e}")
return f"❌ API Error: {str(e)}"
# === Analysis Functions ===
def analyze_candidate_profile(client: SambaNovaClient, user_info: str) -> str:
"""Analyzes the candidate's profile to extract insights and positioning."""
system_prompt = "You are a senior career strategist with expertise in talent assessment and professional positioning."
prompt = f"""
Analyze this candidate profile in detail:
{user_info}
Provide a comprehensive analysis including:
- Experience level and career stage assessment
- Core competencies and unique value propositions
- Industry expertise and domain knowledge
- Leadership capabilities and soft skills evidence
- Career trajectory and growth potential
- Strategic positioning opportunities
- Areas of competitive advantage
Format your response as a structured professional assessment with clear sections.
"""
return client.generate(prompt, system_prompt)
def research_job_posting(client: SambaNovaClient, job_description: str) -> str:
"""Analyzes the job posting for strategic application guidance."""
system_prompt = "You are an expert recruiter and talent acquisition specialist with deep knowledge of job market trends."
prompt = f"""
Conduct a comprehensive analysis of this job posting:
{job_description}
Extract and analyze:
- Must-have vs nice-to-have qualifications
- Technical skills and experience requirements breakdown
- Company culture indicators and values alignment
- Key responsibilities and success metrics
- Career growth and advancement signals
- Compensation and benefits analysis
- Critical ATS keywords and industry terminology
- Hiring urgency and competition level indicators
- Decision-maker priorities and pain points
Provide strategic intelligence for optimal application positioning.
"""
return client.generate(prompt, system_prompt)
def assess_fit_and_strategy(client: SambaNovaClient, profile_analysis: str, job_research: str) -> str:
"""Evaluates fit between candidate and job, develops application strategy."""
system_prompt = "You are a strategic career consultant specializing in job application optimization and candidate positioning."
prompt = f"""
Based on the candidate analysis and job research below, develop a comprehensive application strategy:
CANDIDATE ANALYSIS:
{profile_analysis}
JOB INTELLIGENCE:
{job_research}
Provide detailed strategic assessment:
- Overall fit percentage with detailed justification
- Top 5 strongest selling points to emphasize
- Potential concerns and mitigation strategies
- Unique value proposition development
- Competitive differentiation approach
- Key messaging themes and positioning
- Recommended application tone and style
- Interview preparation insights
"""
return client.generate(prompt, system_prompt)
def generate_strategic_resume(client: SambaNovaClient, candidate_info: str, strategy: str) -> str:
"""Generates a tailored, ATS-optimized resume."""
system_prompt = "You are a professional resume writer and ATS optimization expert with extensive experience in creating winning resumes."
prompt = f"""
Create a professional, ATS-optimized resume based on:
CANDIDATE INFORMATION:
{candidate_info}
STRATEGIC GUIDANCE:
{strategy}
Generate a complete resume with:
- Compelling professional summary (3-4 lines)
- Core competencies/skills section optimized for ATS
- Professional experience with quantified achievements
- Education and certifications
- Additional relevant sections (projects, awards, etc.)
Format professionally with clear sections and bullet points.
Focus on impact, metrics, and value delivery.
"""
return client.generate(prompt, system_prompt)
def create_cover_letter(client: SambaNovaClient, candidate_info: str, strategy: str, job_description: str) -> str:
"""Generates a persuasive, personalized cover letter."""
system_prompt = "You are an expert cover letter writer specializing in compelling, personalized application letters that get results."
prompt = f"""
Write a persuasive cover letter based on:
CANDIDATE INFORMATION:
{candidate_info}
STRATEGIC POSITIONING:
{strategy}
JOB DESCRIPTION:
{job_description}
Create an engaging cover letter that:
- Opens with a compelling hook that grabs attention
- Demonstrates specific research about the company/role
- Connects candidate experience to concrete value delivery
- Shows cultural fit and genuine enthusiasm
- Addresses potential concerns proactively
- Closes with a confident, action-oriented call-to-action
Keep it concise (3-4 paragraphs) but impactful.
"""
return client.generate(prompt, system_prompt)
def quality_assurance_check(client: SambaNovaClient, resume: str, cover_letter: str, job_posting: str) -> str:
"""Performs quality review of generated documents."""
system_prompt = "You are a senior HR professional and application reviewer with expertise in document quality assessment."
prompt = f"""
Perform a comprehensive quality review of these application materials:
RESUME:
{resume}
COVER LETTER:
{cover_letter}
ORIGINAL JOB POSTING:
{job_posting}
Evaluate and provide feedback on:
- ATS optimization and keyword alignment (score /10)
- Document consistency and professional presentation (score /10)
- Value proposition clarity and impact (score /10)
- Competitive differentiation strength (score /10)
- Overall application effectiveness (score /10)
Provide specific improvement recommendations and an overall quality assessment.
"""
return client.generate(prompt, system_prompt)
# === Main Career Agent Class ===
class CareerAgent:
"""Main Career Agent class handling AI-powered document generation."""
def __init__(self):
self.client = self._initialize_client()
def _initialize_client(self) -> SambaNovaClient:
"""Initialize SambaNova client."""
api_key = os.getenv("SAMBANOVA_API_KEY")
if not api_key:
raise ValueError("SAMBANOVA_API_KEY environment variable is required.")
return SambaNovaClient(api_key=api_key)
def process_application(self, user_info: str, job_description: str) -> str:
"""Process the complete application with step-by-step analysis."""
if not user_info.strip() or not job_description.strip():
return "❌ Please provide both your profile and the job description."
try:
logger.info("πŸ” Step 1: Analyzing candidate profile...")
profile_analysis = analyze_candidate_profile(self.client, user_info)
logger.info("πŸ” Step 2: Researching job requirements...")
job_research = research_job_posting(self.client, job_description)
logger.info("🎯 Step 3: Assessing fit and developing strategy...")
strategy = assess_fit_and_strategy(self.client, profile_analysis, job_research)
logger.info("πŸ“„ Step 4: Generating tailored resume...")
resume = generate_strategic_resume(self.client, user_info, strategy)
logger.info("βœ‰οΈ Step 5: Creating personalized cover letter...")
cover_letter = create_cover_letter(self.client, user_info, strategy, job_description)
logger.info("βœ… Step 6: Performing quality assurance...")
qa_review = quality_assurance_check(self.client, resume, cover_letter, job_description)
# Format final output
result = f"""
=== πŸ“„ TAILORED RESUME ===
{resume}
=== βœ‰οΈ PERSONALIZED COVER LETTER ===
{cover_letter}
=== 🎯 STRATEGIC ANALYSIS ===
{strategy}
=== βœ… QUALITY ASSURANCE REVIEW ===
{qa_review}
---
Generated by SambaNova Llama 3.3 70B Instruct
"""
logger.info("βœ… Application processing completed successfully!")
return result.strip()
except Exception as e:
logger.error(f"Processing error: {e}")
return f"""❌ SambaNova API Error: {str(e)}
πŸ”§ Troubleshooting:
- Verify your SAMBANOVA_API_KEY is valid
- Check your internet connection
- Ensure you have sufficient API credits
- Try again in a few moments
If the problem persists, please check your API key configuration."""
# === Enhanced Gradio Interface ===
class CareerAgentInterface:
def __init__(self, agent: CareerAgent):
self.agent = agent
def create_interface(self) -> gr.Blocks:
"""Create enhanced side-by-side interface."""
with gr.Blocks(title="🎯 Intelligent Career Agent (SambaNova)", css=self._css()) as demo:
# Header
gr.Markdown("""
# 🎯 Intelligent Career Agent
### Powered by SambaNova's Llama 3.3 70B Instruct
Generate tailored resumes and cover letters using cutting-edge AI technology.
""")
# Status indicator
status = gr.Markdown("βœ… **Ready** - Llama 3.3 70B Model Loaded", elem_classes="status-ready")
# Main layout - side by side
with gr.Row(equal_height=True):
# Left column - Inputs
with gr.Column(scale=1):
gr.Markdown("## πŸ“ Input Information")
self.user_info = gr.Textbox(
label="πŸ‘€ Your Professional Profile",
placeholder="""Example:
β€’ Software Engineer with 5+ years experience
β€’ Expert in Python, React, AWS
β€’ Led team of 8 developers at TechCorp
β€’ MBA in Technology Management
β€’ Passionate about AI and machine learning
Paste your complete background here...""",
lines=12,
max_lines=15
)
self.job_description = gr.Textbox(
label="πŸ“„ Target Job Description",
placeholder="""Paste the complete job posting here:
- Job title and company
- Requirements and qualifications
- Responsibilities
- Company culture info
- Any other relevant details...""",
lines=8,
max_lines=12
)
# Control buttons
with gr.Row():
self.generate_btn = gr.Button(
"πŸš€ Generate Application",
variant="primary",
size="lg"
)
self.clear_btn = gr.Button(
"πŸ—‘οΈ Clear All",
variant="secondary"
)
# Right column - Output
with gr.Column(scale=1):
gr.Markdown("## πŸ“„ Generated Documents")
self.output = gr.Textbox(
label="🎯 Your Tailored Application Materials",
placeholder="Click 'Generate Application' to create your personalized resume and cover letter...",
lines=25,
max_lines=30,
show_copy_button=True,
interactive=False
)
# Progress and tips
gr.Markdown("""
### πŸ’‘ Tips for Best Results:
- **Be specific** about your achievements with numbers/metrics
- **Include keywords** from your target industry
- **Paste the complete** job description for better matching
- **Review the output** and customize as needed
### πŸ”„ Processing Steps:
1. **Profile Analysis** - Understanding your background
2. **Job Research** - Decoding employer requirements
3. **Strategy Development** - Optimizing your positioning
4. **Resume Generation** - Creating tailored content
5. **Cover Letter Writing** - Personalizing your pitch
6. **Quality Assurance** - Ensuring excellence
""")
# Event handlers
def process_with_status(user_info, job_desc):
try:
result = self.agent.process_application(user_info, job_desc)
return result, "βœ… **Complete** - Your application materials are ready!"
except Exception as e:
return f"❌ Error: {str(e)}", "❌ **Error** - Please check your API key and try again"
self.generate_btn.click(
fn=lambda: "πŸ”„ **Generating...** SambaNova Llama 3.3 70B is processing your request",
outputs=status
).then(
fn=process_with_status,
inputs=[self.user_info, self.job_description],
outputs=[self.output, status]
)
self.clear_btn.click(
fn=lambda: ("", "", "Click 'Generate Application' to create your personalized resume and cover letter...", "βœ… **Ready** - Llama 3.3 70B Model Loaded"),
outputs=[self.user_info, self.job_description, self.output, status]
)
return demo
def _css(self) -> str:
"""Enhanced CSS for better visual design."""
return """
.gradio-container {
max-width: 1400px !important;
margin: auto;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.status-ready {
background: linear-gradient(90deg, #10b981, #059669);
color: white;
padding: 10px;
border-radius: 8px;
text-align: center;
margin: 10px 0;
}
/* Button styling */
.btn-primary {
background: linear-gradient(90deg, #3b82f6, #1d4ed8) !important;
border: none !important;
color: white !important;
font-weight: bold !important;
}
.btn-primary:hover {
background: linear-gradient(90deg, #1d4ed8, #1e40af) !important;
}
/* Enhanced textbox styling */
.textbox textarea {
border-radius: 8px !important;
border: 2px solid #e5e7eb !important;
}
.textbox textarea:focus {
border-color: #3b82f6 !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
}
/* Column gap */
.flex.gap-4 > div {
gap: 1.5rem;
}
"""
# === Entry Point ===
def main():
"""Main entry point with enhanced error handling."""
try:
print("πŸš€ Initializing Career Agent with SambaNova...")
# Check for API key
if not os.getenv("SAMBANOVA_API_KEY"):
print("❌ Error: SAMBANOVA_API_KEY environment variable not found!")
print("Please set your SambaNova API key:")
print("export SAMBANOVA_API_KEY='your-api-key-here'")
return
career_agent = CareerAgent()
print("βœ… SambaNova Llama 3.3 70B initialized successfully!")
interface = CareerAgentInterface(career_agent)
demo = interface.create_interface()
print("🌐 Launching Gradio interface...")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
except Exception as e:
logger.error(f"Startup error: {e}")
print(f"❌ Startup Error: {str(e)}")
print("\nTroubleshooting:")
print("1. Check your SAMBANOVA_API_KEY is valid")
print("2. Ensure you have internet connection")
print("3. Verify all dependencies are installed: pip install openai gradio python-dotenv")
if __name__ == "__main__":
main()