File size: 18,098 Bytes
0d7e6dc
 
 
 
 
 
 
 
f7ade35
0d7e6dc
 
ce145ec
0d7e6dc
19ca30f
f7ade35
7b0da99
f7ade35
0d7e6dc
 
 
 
19ca30f
0d7e6dc
7b0da99
0d7e6dc
f7ade35
3a918ff
f7ade35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29ad2ca
f7ade35
29ad2ca
f7ade35
 
 
 
e776574
f7ade35
2fb4479
e776574
2fb4479
f7ade35
 
 
e776574
f7ade35
 
 
 
2fb4479
f7ade35
e776574
f7ade35
 
2fb4479
3a918ff
f7ade35
 
 
 
e776574
f7ade35
e776574
 
 
 
f7ade35
 
 
 
 
 
 
 
 
 
 
e776574
f7ade35
 
29ad2ca
 
f7ade35
 
 
 
e776574
f7ade35
2fb4479
e776574
 
2fb4479
e776574
 
2fb4479
f7ade35
 
 
 
e776574
f7ade35
 
 
 
e776574
f7ade35
 
29ad2ca
 
f7ade35
 
 
 
e776574
f7ade35
e776574
 
 
 
 
 
 
f7ade35
 
 
 
e776574
f7ade35
2fb4479
f7ade35
 
e776574
f7ade35
 
29ad2ca
 
f7ade35
 
 
 
e776574
f7ade35
2fb4479
e776574
 
2fb4479
e776574
 
2fb4479
f7ade35
 
2fb4479
f7ade35
 
 
 
 
 
 
3a918ff
f7ade35
e776574
f7ade35
 
29ad2ca
 
f7ade35
 
 
 
e776574
f7ade35
e776574
 
 
 
 
 
 
 
 
 
f7ade35
 
 
 
 
 
e776574
f7ade35
e776574
f7ade35
 
e776574
2fb4479
f7ade35
3a918ff
0d7e6dc
e776574
 
0d7e6dc
f7ade35
 
 
 
 
 
 
 
3a918ff
0d7e6dc
f7ade35
0d7e6dc
29ad2ca
 
0d7e6dc
f7ade35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d7e6dc
29ad2ca
f7ade35
 
 
 
 
 
 
 
 
29ad2ca
 
f7ade35
29ad2ca
 
 
 
019546f
29ad2ca
f7ade35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29ad2ca
f7ade35
 
 
 
 
 
 
 
 
 
 
29ad2ca
f7ade35
29ad2ca
f7ade35
 
 
 
 
 
 
 
 
29ad2ca
f7ade35
 
29ad2ca
f7ade35
 
 
 
 
 
 
 
 
 
 
 
 
 
29ad2ca
f7ade35
 
019546f
f7ade35
 
 
29ad2ca
f7ade35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29ad2ca
f7ade35
 
 
 
29ad2ca
f7ade35
 
 
 
 
 
29ad2ca
019546f
29ad2ca
019546f
f7ade35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8404e8a
29ad2ca
 
 
 
f7ade35
ce145ec
f7ade35
 
 
 
 
 
 
 
 
0d7e6dc
f7ade35
 
 
29ad2ca
 
f7ade35
 
 
 
 
 
 
 
 
ce145ec
29ad2ca
 
f7ade35
 
 
 
29ad2ca
 
 
f7ade35
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
"""
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()