TouradAi commited on
Commit
f7ade35
Β·
1 Parent(s): 019546f

Update application file

Browse files
Files changed (2) hide show
  1. app.py +360 -214
  2. requirements.txt +2 -0
app.py CHANGED
@@ -6,15 +6,15 @@ An AI agent that autonomously analyzes job postings and candidate profiles
6
  to create tailored application documents using multi-step reasoning.
7
 
8
  Author: Career Agent Team
9
- Version: 1.0
10
  """
11
 
12
  import os
13
  import logging
14
  import gradio as gr
15
- from typing import Optional
16
  from dotenv import load_dotenv
17
- from smolagents import CodeAgent, tool, HfApiModel, ChatMessage
18
 
19
  # Configure logging
20
  logging.basicConfig(level=logging.INFO)
@@ -23,82 +23,96 @@ logger = logging.getLogger(__name__)
23
  # Load environment variables
24
  load_dotenv()
25
 
26
- # === Tools ===
27
 
28
- @tool
29
- def analyze_candidate_profile(user_info: str) -> str:
30
- """
31
- Analyzes the candidate's profile to extract insights and positioning.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- Args:
34
- user_info (str): Full professional profile including experience, skills, education.
35
 
36
- Returns:
37
- str: Structured professional assessment.
38
- """
 
39
  prompt = f"""
40
- As a senior career strategist, analyze this candidate profile:
41
 
42
  {user_info}
43
 
44
- Provide detailed analysis including:
45
- - Experience level and career stage
46
- - Core competencies and unique strengths
47
  - Industry expertise and domain knowledge
48
- - Leadership and soft skills indicators
49
- - Potential career trajectory
50
- - Areas for strategic positioning
 
51
 
52
- Format as structured professional assessment.
53
  """
54
- return call_model(prompt)
 
55
 
56
 
57
- @tool
58
- def research_job_posting(job_description: str) -> str:
59
- """
60
- Analyzes the job posting for strategic application guidance.
61
-
62
- Args:
63
- job_description (str): Full job description as provided by the employer.
64
-
65
- Returns:
66
- str: Structured analysis of employer needs and expectations.
67
- """
68
  prompt = f"""
69
- Conduct comprehensive job posting analysis:
70
 
71
  {job_description}
72
 
73
  Extract and analyze:
74
- - Required vs preferred qualifications
75
- - Technical skills and experience requirements
76
- - Company culture and values indicators
77
- - Role challenges and key responsibilities
78
- - Growth and advancement opportunities
79
- - Compensation and benefits signals
80
- - ATS keywords and phrases
81
- - Hiring urgency indicators
82
-
83
- Provide strategic intelligence for application optimization.
84
- """
85
- return call_model(prompt)
86
-
87
-
88
- @tool
89
- def assess_fit_and_strategy(profile_analysis: str, job_research: str) -> str:
90
  """
91
- Evaluates fit between the candidate and job, and suggests strategy.
 
92
 
93
- Args:
94
- profile_analysis (str): Output from profile analysis.
95
- job_research (str): Output from job posting analysis.
96
 
97
- Returns:
98
- str: Application strategy with fit assessment and messaging plan.
99
- """
 
100
  prompt = f"""
101
- Strategic fit assessment and application strategy:
102
 
103
  CANDIDATE ANALYSIS:
104
  {profile_analysis}
@@ -106,31 +120,26 @@ def assess_fit_and_strategy(profile_analysis: str, job_research: str) -> str:
106
  JOB INTELLIGENCE:
107
  {job_research}
108
 
109
- Provide comprehensive assessment:
110
- - Overall fit percentage with detailed reasoning
111
- - Strongest selling points to emphasize
112
- - Potential weaknesses and mitigation strategies
113
  - Unique value proposition development
114
- - Competitive positioning recommendations
115
- - Application approach and messaging strategy
116
- """
117
- return call_model(prompt)
118
-
119
-
120
- @tool
121
- def generate_strategic_resume(candidate_info: str, strategy: str) -> str:
122
  """
123
- Generates a tailored, ATS-optimized resume.
 
124
 
125
- Args:
126
- candidate_info (str): Raw professional data.
127
- strategy (str): Strategic direction from analysis.
128
 
129
- Returns:
130
- str: Full resume text.
131
- """
 
132
  prompt = f"""
133
- Create a professional, ATS-optimized resume:
134
 
135
  CANDIDATE INFORMATION:
136
  {candidate_info}
@@ -138,30 +147,26 @@ def generate_strategic_resume(candidate_info: str, strategy: str) -> str:
138
  STRATEGIC GUIDANCE:
139
  {strategy}
140
 
141
- Generate complete resume with:
142
- - Compelling professional summary
143
- - Work experience with quantified achievements
144
- - Skills section optimized for job requirements
145
  - Education and certifications
146
- - Additional relevant sections
147
- """
148
- return call_model(prompt)
149
 
150
-
151
- @tool
152
- def create_cover_letter(candidate_info: str, strategy: str) -> str:
153
  """
154
- Generates a persuasive, personalized cover letter.
 
155
 
156
- Args:
157
- candidate_info (str): Raw professional data.
158
- strategy (str): Strategic direction from analysis.
159
 
160
- Returns:
161
- str: Cover letter content.
162
- """
 
163
  prompt = f"""
164
- Craft a persuasive cover letter:
165
 
166
  CANDIDATE INFORMATION:
167
  {candidate_info}
@@ -169,31 +174,29 @@ def create_cover_letter(candidate_info: str, strategy: str) -> str:
169
  STRATEGIC POSITIONING:
170
  {strategy}
171
 
172
- Write engaging cover letter that:
173
- - Opens with compelling hook
174
- - Demonstrates company/role research
175
- - Connects experience to value delivery
176
- - Shows cultural fit and enthusiasm
177
- - Closes with confident call-to-action
178
- """
179
- return call_model(prompt)
180
 
 
 
 
 
 
 
 
181
 
182
- @tool
183
- def quality_assurance_check(resume: str, cover_letter: str, job_posting: str) -> str:
184
  """
185
- Runs quality review of generated documents.
 
186
 
187
- Args:
188
- resume (str): The generated resume.
189
- cover_letter (str): The generated cover letter.
190
- job_posting (str): Original job description.
191
 
192
- Returns:
193
- str: Quality feedback and suggestions.
194
- """
 
195
  prompt = f"""
196
- Quality assurance review:
197
 
198
  RESUME:
199
  {resume}
@@ -204,156 +207,299 @@ def quality_assurance_check(resume: str, cover_letter: str, job_posting: str) ->
204
  ORIGINAL JOB POSTING:
205
  {job_posting}
206
 
207
- Evaluate:
208
- - Keyword alignment and ATS optimization
209
- - Document consistency and coherence
210
- - Value proposition clarity
211
- - Competitive differentiation
212
- - Overall application strength
213
 
214
- Provide a quality score and specific improvement recommendations.
215
  """
216
- return call_model(prompt)
217
-
218
 
219
- # === Core ===
220
-
221
- def call_model(prompt: str) -> str:
222
- """Helper function to call the Hugging Face model."""
223
- try:
224
- messages = [ChatMessage(role="user", content=prompt)]
225
- response = career_agent.model(messages)
226
- return str(response.content) if hasattr(response, "content") else "⚠️ Model error"
227
- except Exception as e:
228
- logger.error(f"Model call failed: {e}")
229
- return f"⚠️ Error: {str(e)}"
230
 
 
231
 
232
  class CareerAgent:
233
  """Main Career Agent class handling AI-powered document generation."""
234
 
235
  def __init__(self):
236
- self.model = self._initialize_model()
237
- self.agent = self._create_agent()
238
-
239
- def _initialize_model(self) -> HfApiModel:
240
- token = os.getenv("HF_TOKEN")
241
- if not token:
242
- raise ValueError("HF_TOKEN environment variable is required.")
243
- return HfApiModel(model_id="meta-llama/Llama-3.1-8B-Instruct", token=token)
244
-
245
- def _create_agent(self) -> CodeAgent:
246
- return CodeAgent(
247
- model=self.model,
248
- tools=[
249
- analyze_candidate_profile,
250
- research_job_posting,
251
- assess_fit_and_strategy,
252
- generate_strategic_resume,
253
- create_cover_letter,
254
- quality_assurance_check
255
- ],
256
- add_base_tools=True
257
- )
258
 
259
  def process_application(self, user_info: str, job_description: str) -> str:
 
260
  if not user_info.strip() or not job_description.strip():
261
  return "❌ Please provide both your profile and the job description."
262
 
263
- instruction = f"""
264
- You are an expert career strategist.
265
-
266
- CANDIDATE PROFILE:
267
- {user_info}
268
-
269
- JOB POSTING:
270
- {job_description}
271
-
272
- Follow this process:
273
- 1. Analyze candidate
274
- 2. Research job
275
- 3. Assess fit
276
- 4. Generate resume
277
- 5. Generate cover letter
278
- 6. Quality review
279
-
280
- Output sections:
281
- === RESUME ===
282
- ...
283
- === COVER LETTER ===
284
- ...
285
- === STRATEGY NOTES ===
286
- ...
287
- """
288
-
289
  try:
290
- logger.info("Running career agent process...")
291
- result = self.agent.run(instruction)
292
- return str(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  except Exception as e:
294
  logger.error(f"Processing error: {e}")
295
- return f"❌ Error: {str(e)}"
 
 
 
 
 
 
 
 
296
 
297
 
298
- # === Gradio Interface ===
299
 
300
  class CareerAgentInterface:
301
  def __init__(self, agent: CareerAgent):
302
  self.agent = agent
303
 
304
  def create_interface(self) -> gr.Blocks:
305
- with gr.Blocks(title="🎯 Intelligent Career Agent", css=self._css()) as demo:
306
- gr.HTML("<h1 style='text-align:center;'>🎯 Intelligent Career Agent</h1>")
307
-
308
- with gr.Row():
309
- with gr.Column():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  self.user_info = gr.Textbox(
311
- label="πŸ‘€ Your Profile",
312
- placeholder="Paste your education, experience, skills...",
313
- lines=15
 
 
 
 
 
 
 
 
314
  )
 
315
  self.job_description = gr.Textbox(
316
- label="πŸ“„ Job Description",
317
- placeholder="Paste the full job posting here...",
318
- lines=10
 
 
 
 
 
 
319
  )
 
 
320
  with gr.Row():
321
- self.generate_btn = gr.Button("πŸš€ Generate Application")
322
- self.clear_btn = gr.Button("πŸ—‘οΈ Clear")
323
-
324
- with gr.Column():
 
 
 
 
 
 
 
 
 
 
325
  self.output = gr.Textbox(
326
- label="πŸ“„ Output",
 
327
  lines=25,
328
- show_copy_button=True
 
 
329
  )
330
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  self.generate_btn.click(
332
- fn=self.agent.process_application,
 
 
 
333
  inputs=[self.user_info, self.job_description],
334
- outputs=self.output
 
 
 
 
 
335
  )
336
- self.clear_btn.click(fn=lambda: ("", "", ""), outputs=[self.user_info, self.job_description, self.output])
337
 
338
  return demo
339
 
340
- def _css(self):
341
- return ".gradio-container { max-width: 1200px !important; margin: auto; }"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
 
343
 
344
  # === Entry Point ===
345
 
346
  def main():
 
347
  try:
348
- global career_agent
 
 
 
 
 
 
 
 
349
  career_agent = CareerAgent()
 
 
 
350
  interface = CareerAgentInterface(career_agent)
351
  demo = interface.create_interface()
352
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
353
  except Exception as e:
354
  logger.error(f"Startup error: {e}")
355
  print(f"❌ Startup Error: {str(e)}")
 
 
 
 
356
 
357
 
358
  if __name__ == "__main__":
359
- main()
 
6
  to create tailored application documents using multi-step reasoning.
7
 
8
  Author: Career Agent Team
9
+ Version: 1.1 - SambaNova Edition
10
  """
11
 
12
  import os
13
  import logging
14
  import gradio as gr
15
+ from typing import Optional, Dict, Any
16
  from dotenv import load_dotenv
17
+ from openai import OpenAI
18
 
19
  # Configure logging
20
  logging.basicConfig(level=logging.INFO)
 
23
  # Load environment variables
24
  load_dotenv()
25
 
26
+ # === SambaNova API Integration ===
27
 
28
+ class SambaNovaClient:
29
+ """SambaNova client using OpenAI SDK."""
30
+
31
+ def __init__(self, api_key: str, model_name: str = "Meta-Llama-3.3-70B-Instruct"):
32
+ self.client = OpenAI(
33
+ api_key=api_key,
34
+ base_url="https://api.sambanova.ai/v1"
35
+ )
36
+ self.model_name = model_name
37
+
38
+ def generate(self, prompt: str, system_prompt: str = "You are a helpful assistant.") -> str:
39
+ """Generate response using SambaNova API."""
40
+ try:
41
+ response = self.client.chat.completions.create(
42
+ model=self.model_name,
43
+ messages=[
44
+ {"role": "system", "content": system_prompt},
45
+ {"role": "user", "content": prompt}
46
+ ],
47
+ temperature=0.1,
48
+ top_p=0.1,
49
+ max_tokens=3000
50
+ )
51
+
52
+ return response.choices[0].message.content or ""
53
+
54
+ except Exception as e:
55
+ logger.error(f"SambaNova API call failed: {e}")
56
+ return f"❌ API Error: {str(e)}"
57
 
58
+ # === Analysis Functions ===
 
59
 
60
+ def analyze_candidate_profile(client: SambaNovaClient, user_info: str) -> str:
61
+ """Analyzes the candidate's profile to extract insights and positioning."""
62
+ system_prompt = "You are a senior career strategist with expertise in talent assessment and professional positioning."
63
+
64
  prompt = f"""
65
+ Analyze this candidate profile in detail:
66
 
67
  {user_info}
68
 
69
+ Provide a comprehensive analysis including:
70
+ - Experience level and career stage assessment
71
+ - Core competencies and unique value propositions
72
  - Industry expertise and domain knowledge
73
+ - Leadership capabilities and soft skills evidence
74
+ - Career trajectory and growth potential
75
+ - Strategic positioning opportunities
76
+ - Areas of competitive advantage
77
 
78
+ Format your response as a structured professional assessment with clear sections.
79
  """
80
+
81
+ return client.generate(prompt, system_prompt)
82
 
83
 
84
+ def research_job_posting(client: SambaNovaClient, job_description: str) -> str:
85
+ """Analyzes the job posting for strategic application guidance."""
86
+ system_prompt = "You are an expert recruiter and talent acquisition specialist with deep knowledge of job market trends."
87
+
 
 
 
 
 
 
 
88
  prompt = f"""
89
+ Conduct a comprehensive analysis of this job posting:
90
 
91
  {job_description}
92
 
93
  Extract and analyze:
94
+ - Must-have vs nice-to-have qualifications
95
+ - Technical skills and experience requirements breakdown
96
+ - Company culture indicators and values alignment
97
+ - Key responsibilities and success metrics
98
+ - Career growth and advancement signals
99
+ - Compensation and benefits analysis
100
+ - Critical ATS keywords and industry terminology
101
+ - Hiring urgency and competition level indicators
102
+ - Decision-maker priorities and pain points
103
+
104
+ Provide strategic intelligence for optimal application positioning.
 
 
 
 
 
105
  """
106
+
107
+ return client.generate(prompt, system_prompt)
108
 
 
 
 
109
 
110
+ def assess_fit_and_strategy(client: SambaNovaClient, profile_analysis: str, job_research: str) -> str:
111
+ """Evaluates fit between candidate and job, develops application strategy."""
112
+ system_prompt = "You are a strategic career consultant specializing in job application optimization and candidate positioning."
113
+
114
  prompt = f"""
115
+ Based on the candidate analysis and job research below, develop a comprehensive application strategy:
116
 
117
  CANDIDATE ANALYSIS:
118
  {profile_analysis}
 
120
  JOB INTELLIGENCE:
121
  {job_research}
122
 
123
+ Provide detailed strategic assessment:
124
+ - Overall fit percentage with detailed justification
125
+ - Top 5 strongest selling points to emphasize
126
+ - Potential concerns and mitigation strategies
127
  - Unique value proposition development
128
+ - Competitive differentiation approach
129
+ - Key messaging themes and positioning
130
+ - Recommended application tone and style
131
+ - Interview preparation insights
 
 
 
 
132
  """
133
+
134
+ return client.generate(prompt, system_prompt)
135
 
 
 
 
136
 
137
+ def generate_strategic_resume(client: SambaNovaClient, candidate_info: str, strategy: str) -> str:
138
+ """Generates a tailored, ATS-optimized resume."""
139
+ system_prompt = "You are a professional resume writer and ATS optimization expert with extensive experience in creating winning resumes."
140
+
141
  prompt = f"""
142
+ Create a professional, ATS-optimized resume based on:
143
 
144
  CANDIDATE INFORMATION:
145
  {candidate_info}
 
147
  STRATEGIC GUIDANCE:
148
  {strategy}
149
 
150
+ Generate a complete resume with:
151
+ - Compelling professional summary (3-4 lines)
152
+ - Core competencies/skills section optimized for ATS
153
+ - Professional experience with quantified achievements
154
  - Education and certifications
155
+ - Additional relevant sections (projects, awards, etc.)
 
 
156
 
157
+ Format professionally with clear sections and bullet points.
158
+ Focus on impact, metrics, and value delivery.
 
159
  """
160
+
161
+ return client.generate(prompt, system_prompt)
162
 
 
 
 
163
 
164
+ def create_cover_letter(client: SambaNovaClient, candidate_info: str, strategy: str, job_description: str) -> str:
165
+ """Generates a persuasive, personalized cover letter."""
166
+ system_prompt = "You are an expert cover letter writer specializing in compelling, personalized application letters that get results."
167
+
168
  prompt = f"""
169
+ Write a persuasive cover letter based on:
170
 
171
  CANDIDATE INFORMATION:
172
  {candidate_info}
 
174
  STRATEGIC POSITIONING:
175
  {strategy}
176
 
177
+ JOB DESCRIPTION:
178
+ {job_description}
 
 
 
 
 
 
179
 
180
+ Create an engaging cover letter that:
181
+ - Opens with a compelling hook that grabs attention
182
+ - Demonstrates specific research about the company/role
183
+ - Connects candidate experience to concrete value delivery
184
+ - Shows cultural fit and genuine enthusiasm
185
+ - Addresses potential concerns proactively
186
+ - Closes with a confident, action-oriented call-to-action
187
 
188
+ Keep it concise (3-4 paragraphs) but impactful.
 
189
  """
190
+
191
+ return client.generate(prompt, system_prompt)
192
 
 
 
 
 
193
 
194
+ def quality_assurance_check(client: SambaNovaClient, resume: str, cover_letter: str, job_posting: str) -> str:
195
+ """Performs quality review of generated documents."""
196
+ system_prompt = "You are a senior HR professional and application reviewer with expertise in document quality assessment."
197
+
198
  prompt = f"""
199
+ Perform a comprehensive quality review of these application materials:
200
 
201
  RESUME:
202
  {resume}
 
207
  ORIGINAL JOB POSTING:
208
  {job_posting}
209
 
210
+ Evaluate and provide feedback on:
211
+ - ATS optimization and keyword alignment (score /10)
212
+ - Document consistency and professional presentation (score /10)
213
+ - Value proposition clarity and impact (score /10)
214
+ - Competitive differentiation strength (score /10)
215
+ - Overall application effectiveness (score /10)
216
 
217
+ Provide specific improvement recommendations and an overall quality assessment.
218
  """
219
+
220
+ return client.generate(prompt, system_prompt)
221
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
+ # === Main Career Agent Class ===
224
 
225
  class CareerAgent:
226
  """Main Career Agent class handling AI-powered document generation."""
227
 
228
  def __init__(self):
229
+ self.client = self._initialize_client()
230
+
231
+ def _initialize_client(self) -> SambaNovaClient:
232
+ """Initialize SambaNova client."""
233
+ api_key = os.getenv("SAMBANOVA_API_KEY")
234
+ if not api_key:
235
+ raise ValueError("SAMBANOVA_API_KEY environment variable is required.")
236
+ return SambaNovaClient(api_key=api_key)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
  def process_application(self, user_info: str, job_description: str) -> str:
239
+ """Process the complete application with step-by-step analysis."""
240
  if not user_info.strip() or not job_description.strip():
241
  return "❌ Please provide both your profile and the job description."
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  try:
244
+ logger.info("πŸ” Step 1: Analyzing candidate profile...")
245
+ profile_analysis = analyze_candidate_profile(self.client, user_info)
246
+
247
+ logger.info("πŸ” Step 2: Researching job requirements...")
248
+ job_research = research_job_posting(self.client, job_description)
249
+
250
+ logger.info("🎯 Step 3: Assessing fit and developing strategy...")
251
+ strategy = assess_fit_and_strategy(self.client, profile_analysis, job_research)
252
+
253
+ logger.info("πŸ“„ Step 4: Generating tailored resume...")
254
+ resume = generate_strategic_resume(self.client, user_info, strategy)
255
+
256
+ logger.info("βœ‰οΈ Step 5: Creating personalized cover letter...")
257
+ cover_letter = create_cover_letter(self.client, user_info, strategy, job_description)
258
+
259
+ logger.info("βœ… Step 6: Performing quality assurance...")
260
+ qa_review = quality_assurance_check(self.client, resume, cover_letter, job_description)
261
+
262
+ # Format final output
263
+ result = f"""
264
+ === πŸ“„ TAILORED RESUME ===
265
+
266
+ {resume}
267
+
268
+ === βœ‰οΈ PERSONALIZED COVER LETTER ===
269
+
270
+ {cover_letter}
271
+
272
+ === 🎯 STRATEGIC ANALYSIS ===
273
+
274
+ {strategy}
275
+
276
+ === βœ… QUALITY ASSURANCE REVIEW ===
277
+
278
+ {qa_review}
279
+
280
+ ---
281
+ Generated by SambaNova Llama 3.3 70B Instruct
282
+ """
283
+
284
+ logger.info("βœ… Application processing completed successfully!")
285
+ return result.strip()
286
+
287
  except Exception as e:
288
  logger.error(f"Processing error: {e}")
289
+ return f"""❌ SambaNova API Error: {str(e)}
290
+
291
+ πŸ”§ Troubleshooting:
292
+ - Verify your SAMBANOVA_API_KEY is valid
293
+ - Check your internet connection
294
+ - Ensure you have sufficient API credits
295
+ - Try again in a few moments
296
+
297
+ If the problem persists, please check your API key configuration."""
298
 
299
 
300
+ # === Enhanced Gradio Interface ===
301
 
302
  class CareerAgentInterface:
303
  def __init__(self, agent: CareerAgent):
304
  self.agent = agent
305
 
306
  def create_interface(self) -> gr.Blocks:
307
+ """Create enhanced side-by-side interface."""
308
+ with gr.Blocks(title="🎯 Intelligent Career Agent (SambaNova)", css=self._css()) as demo:
309
+ # Header
310
+ gr.Markdown("""
311
+ # 🎯 Intelligent Career Agent
312
+ ### Powered by SambaNova's Llama 3.3 70B Instruct
313
+
314
+ Generate tailored resumes and cover letters using cutting-edge AI technology.
315
+ """)
316
+
317
+ # Status indicator
318
+ status = gr.Markdown("βœ… **Ready** - Llama 3.3 70B Model Loaded", elem_classes="status-ready")
319
+
320
+ # Main layout - side by side
321
+ with gr.Row(equal_height=True):
322
+ # Left column - Inputs
323
+ with gr.Column(scale=1):
324
+ gr.Markdown("## πŸ“ Input Information")
325
+
326
  self.user_info = gr.Textbox(
327
+ label="πŸ‘€ Your Professional Profile",
328
+ placeholder="""Example:
329
+ β€’ Software Engineer with 5+ years experience
330
+ β€’ Expert in Python, React, AWS
331
+ β€’ Led team of 8 developers at TechCorp
332
+ β€’ MBA in Technology Management
333
+ β€’ Passionate about AI and machine learning
334
+
335
+ Paste your complete background here...""",
336
+ lines=12,
337
+ max_lines=15
338
  )
339
+
340
  self.job_description = gr.Textbox(
341
+ label="πŸ“„ Target Job Description",
342
+ placeholder="""Paste the complete job posting here:
343
+ - Job title and company
344
+ - Requirements and qualifications
345
+ - Responsibilities
346
+ - Company culture info
347
+ - Any other relevant details...""",
348
+ lines=8,
349
+ max_lines=12
350
  )
351
+
352
+ # Control buttons
353
  with gr.Row():
354
+ self.generate_btn = gr.Button(
355
+ "πŸš€ Generate Application",
356
+ variant="primary",
357
+ size="lg"
358
+ )
359
+ self.clear_btn = gr.Button(
360
+ "πŸ—‘οΈ Clear All",
361
+ variant="secondary"
362
+ )
363
+
364
+ # Right column - Output
365
+ with gr.Column(scale=1):
366
+ gr.Markdown("## πŸ“„ Generated Documents")
367
+
368
  self.output = gr.Textbox(
369
+ label="🎯 Your Tailored Application Materials",
370
+ placeholder="Click 'Generate Application' to create your personalized resume and cover letter...",
371
  lines=25,
372
+ max_lines=30,
373
+ show_copy_button=True,
374
+ interactive=False
375
  )
376
+
377
+ # Progress and tips
378
+ gr.Markdown("""
379
+ ### πŸ’‘ Tips for Best Results:
380
+ - **Be specific** about your achievements with numbers/metrics
381
+ - **Include keywords** from your target industry
382
+ - **Paste the complete** job description for better matching
383
+ - **Review the output** and customize as needed
384
+
385
+ ### πŸ”„ Processing Steps:
386
+ 1. **Profile Analysis** - Understanding your background
387
+ 2. **Job Research** - Decoding employer requirements
388
+ 3. **Strategy Development** - Optimizing your positioning
389
+ 4. **Resume Generation** - Creating tailored content
390
+ 5. **Cover Letter Writing** - Personalizing your pitch
391
+ 6. **Quality Assurance** - Ensuring excellence
392
+ """)
393
+
394
+ # Event handlers
395
+ def process_with_status(user_info, job_desc):
396
+ try:
397
+ result = self.agent.process_application(user_info, job_desc)
398
+ return result, "βœ… **Complete** - Your application materials are ready!"
399
+ except Exception as e:
400
+ return f"❌ Error: {str(e)}", "❌ **Error** - Please check your API key and try again"
401
+
402
  self.generate_btn.click(
403
+ fn=lambda: "πŸ”„ **Generating...** SambaNova Llama 3.3 70B is processing your request",
404
+ outputs=status
405
+ ).then(
406
+ fn=process_with_status,
407
  inputs=[self.user_info, self.job_description],
408
+ outputs=[self.output, status]
409
+ )
410
+
411
+ self.clear_btn.click(
412
+ fn=lambda: ("", "", "Click 'Generate Application' to create your personalized resume and cover letter...", "βœ… **Ready** - Llama 3.3 70B Model Loaded"),
413
+ outputs=[self.user_info, self.job_description, self.output, status]
414
  )
 
415
 
416
  return demo
417
 
418
+ def _css(self) -> str:
419
+ """Enhanced CSS for better visual design."""
420
+ return """
421
+ .gradio-container {
422
+ max-width: 1400px !important;
423
+ margin: auto;
424
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
425
+ }
426
+
427
+ .status-ready {
428
+ background: linear-gradient(90deg, #10b981, #059669);
429
+ color: white;
430
+ padding: 10px;
431
+ border-radius: 8px;
432
+ text-align: center;
433
+ margin: 10px 0;
434
+ }
435
+
436
+ /* Button styling */
437
+ .btn-primary {
438
+ background: linear-gradient(90deg, #3b82f6, #1d4ed8) !important;
439
+ border: none !important;
440
+ color: white !important;
441
+ font-weight: bold !important;
442
+ }
443
+
444
+ .btn-primary:hover {
445
+ background: linear-gradient(90deg, #1d4ed8, #1e40af) !important;
446
+ }
447
+
448
+ /* Enhanced textbox styling */
449
+ .textbox textarea {
450
+ border-radius: 8px !important;
451
+ border: 2px solid #e5e7eb !important;
452
+ }
453
+
454
+ .textbox textarea:focus {
455
+ border-color: #3b82f6 !important;
456
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
457
+ }
458
+
459
+ /* Column gap */
460
+ .flex.gap-4 > div {
461
+ gap: 1.5rem;
462
+ }
463
+ """
464
 
465
 
466
  # === Entry Point ===
467
 
468
  def main():
469
+ """Main entry point with enhanced error handling."""
470
  try:
471
+ print("πŸš€ Initializing Career Agent with SambaNova...")
472
+
473
+ # Check for API key
474
+ if not os.getenv("SAMBANOVA_API_KEY"):
475
+ print("❌ Error: SAMBANOVA_API_KEY environment variable not found!")
476
+ print("Please set your SambaNova API key:")
477
+ print("export SAMBANOVA_API_KEY='your-api-key-here'")
478
+ return
479
+
480
  career_agent = CareerAgent()
481
+
482
+ print("βœ… SambaNova Llama 3.3 70B initialized successfully!")
483
+
484
  interface = CareerAgentInterface(career_agent)
485
  demo = interface.create_interface()
486
+
487
+ print("🌐 Launching Gradio interface...")
488
+ demo.launch(
489
+ server_name="0.0.0.0",
490
+ server_port=7860,
491
+ share=False,
492
+ show_error=True
493
+ )
494
+
495
  except Exception as e:
496
  logger.error(f"Startup error: {e}")
497
  print(f"❌ Startup Error: {str(e)}")
498
+ print("\nTroubleshooting:")
499
+ print("1. Check your SAMBANOVA_API_KEY is valid")
500
+ print("2. Ensure you have internet connection")
501
+ print("3. Verify all dependencies are installed: pip install openai gradio python-dotenv")
502
 
503
 
504
  if __name__ == "__main__":
505
+ main()
requirements.txt CHANGED
@@ -1,3 +1,5 @@
1
  gradio
2
  smolagents
3
  duckduckgo-search
 
 
 
1
  gradio
2
  smolagents
3
  duckduckgo-search
4
+ openai
5
+ python-dotenv