Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -25,10 +25,10 @@ from pydantic import BaseModel, Field, confloat
|
|
25 |
# )
|
26 |
from langchain_community.llms import HuggingFaceHub
|
27 |
#HuggingFaceH4/zephyr-7b-beta"
|
28 |
-
llm = HuggingFaceHub(
|
29 |
-
|
30 |
-
|
31 |
-
)
|
32 |
|
33 |
class SkillScore(BaseModel):
|
34 |
skill_name: str = Field(description="Name of the skill being scored")
|
@@ -255,7 +255,7 @@ resume_analyzer = Agent(
|
|
255 |
providing actionable suggestions for improvement. Your recommendations always
|
256 |
focus on both human readability and ATS compatibility.""",
|
257 |
verbose=True,
|
258 |
-
llm = llm,
|
259 |
# knowledge_sources=[pdf_source],
|
260 |
)
|
261 |
job_analyzer = Agent(
|
@@ -268,7 +268,7 @@ job_analyzer = Agent(
|
|
268 |
and soft skills requirements, and can evaluate experience levels accurately.""",
|
269 |
verbose=True,
|
270 |
tools=[ScrapeWebsiteTool()],
|
271 |
-
llm = llm,
|
272 |
|
273 |
# knowledge_sources=[pdf_source],
|
274 |
)
|
@@ -282,7 +282,7 @@ company_researcher = Agent(
|
|
282 |
candidates for interviews. """,
|
283 |
tools=[SerperDevTool()],
|
284 |
verbose=True,
|
285 |
-
llm = llm,
|
286 |
|
287 |
# knowledge_sources=[pdf_source],
|
288 |
|
@@ -296,7 +296,7 @@ resume_writer = Agent (
|
|
296 |
beautifully formatted, ATS-friendly documents that maintain professionalism
|
297 |
while showcasing candidate strengths effectively.""",
|
298 |
verbose=True,
|
299 |
-
llm = llm,
|
300 |
|
301 |
)
|
302 |
report_generator = Agent(
|
@@ -309,49 +309,42 @@ report_generator = Agent(
|
|
309 |
into clear, actionable insights with proper markdown formatting, emojis, and
|
310 |
visual elements that make information both appealing and easily digestible.""",
|
311 |
verbose=True,
|
312 |
-
llm = llm,
|
313 |
|
314 |
)
|
315 |
|
316 |
analyze_job_task = Task(
|
317 |
description="""Analyze the {job_url} description and score the candidate's fit based on their resume.
|
318 |
Output will be saved as structured JSON data.
|
319 |
-
|
320 |
1. Extract Requirements:
|
321 |
- Technical skills (required vs nice-to-have)
|
322 |
- Soft skills
|
323 |
- Experience levels
|
324 |
- Education requirements
|
325 |
- Industry knowledge
|
326 |
-
|
327 |
2. Score Technical Skills (35% of total):
|
328 |
- For each required skill:
|
329 |
* Match Level (0-1): How well does candidate's experience match?
|
330 |
* Years Experience: Compare to required years
|
331 |
* Context Score: How relevant is their usage of the skill?
|
332 |
- Calculate weighted average based on skill importance
|
333 |
-
|
334 |
3. Score Soft Skills (20% of total):
|
335 |
- Identify soft skills from resume
|
336 |
- Compare against job requirements
|
337 |
- Consider context and demonstration of skills
|
338 |
-
|
339 |
4. Score Experience (25% of total):
|
340 |
- Years of relevant experience
|
341 |
- Role similarity
|
342 |
- Industry relevance
|
343 |
- Project scope and complexity
|
344 |
-
|
345 |
5. Score Education (10% of total):
|
346 |
- Degree level match
|
347 |
- Field of study relevance
|
348 |
- Additional certifications
|
349 |
-
|
350 |
6. Score Industry Knowledge (10% of total):
|
351 |
- Years in similar industry
|
352 |
- Domain expertise
|
353 |
- Industry-specific achievements
|
354 |
-
|
355 |
7. Calculate Overall Score:
|
356 |
- Weighted average of all components
|
357 |
- Identify key strengths and gaps
|
@@ -367,19 +360,16 @@ optimize_resume_task = Task(
|
|
367 |
description= """
|
368 |
Review the provided resume against the job analysis and create structured optimization suggestions.
|
369 |
Output will be saved as structured JSON data.
|
370 |
-
|
371 |
1. Content Analysis:
|
372 |
- Compare resume content with job requirements
|
373 |
- Identify missing keywords and skills
|
374 |
- Analyze achievement descriptions
|
375 |
- Check for ATS compatibility
|
376 |
-
|
377 |
2. Structure Review:
|
378 |
- Evaluate section organization
|
379 |
- Check formatting consistency
|
380 |
- Assess information hierarchy
|
381 |
- Verify contact details
|
382 |
-
|
383 |
3. Generate Suggestions:
|
384 |
- Content improvements with before/after examples
|
385 |
- Skills to highlight based on job match
|
@@ -403,7 +393,6 @@ research_company_task = Task(
|
|
403 |
- Culture and values
|
404 |
- Market position
|
405 |
- Growth trajectory
|
406 |
-
|
407 |
2. Interview Preparation:
|
408 |
- Common interview questions
|
409 |
- Company-specific topics
|
@@ -422,19 +411,16 @@ generate_resume_task = Task(
|
|
422 |
Using the optimization suggestions and job analysis from previous steps,
|
423 |
create a polished resume in markdown format.
|
424 |
Do not add markdown code blocks like '```'.
|
425 |
-
|
426 |
1. Content Integration:
|
427 |
- Incorporate optimization suggestions
|
428 |
- Add missing keywords and skills
|
429 |
- Enhance achievement descriptions
|
430 |
- Ensure ATS compatibility
|
431 |
-
|
432 |
2. Formatting:
|
433 |
- Use proper markdown headers (#, ##, ###)
|
434 |
- Apply consistent styling
|
435 |
- Create clear section hierarchy
|
436 |
- Use bullet points effectively
|
437 |
-
|
438 |
3. Documentation:
|
439 |
- Track changes made
|
440 |
- Note preserved elements
|
@@ -453,39 +439,32 @@ generate_report_task = Task(
|
|
453 |
description="""
|
454 |
Create an executive summary report using data from previous steps.
|
455 |
Format in markdown without code blocks '```'.
|
456 |
-
|
457 |
1. Data Integration:
|
458 |
- Job analysis and scores
|
459 |
- Resume optimization details
|
460 |
- Company research insights
|
461 |
- Final resume changes
|
462 |
-
|
463 |
2. Report Sections:
|
464 |
## Executive Summary
|
465 |
- Overall match score and quick wins
|
466 |
- Key strengths and improvement areas
|
467 |
- Action items priority list
|
468 |
-
|
469 |
## Job Fit Analysis
|
470 |
- Detailed score breakdown
|
471 |
- Skills match assessment
|
472 |
- Experience alignment
|
473 |
-
|
474 |
## Optimization Overview
|
475 |
- Key resume improvements
|
476 |
- ATS optimization results
|
477 |
- Impact metrics
|
478 |
-
|
479 |
## Company Insights
|
480 |
- Culture fit analysis
|
481 |
- Interview preparation tips
|
482 |
- Key talking points
|
483 |
-
|
484 |
## Next Steps
|
485 |
- Prioritized action items
|
486 |
- Skill development plan
|
487 |
- Application strategy
|
488 |
-
|
489 |
3. Formatting:
|
490 |
- Use proper markdown headers
|
491 |
- Include relevant emojis
|
@@ -504,7 +483,7 @@ from crewai import Crew
|
|
504 |
# Function to run CrewAI with dynamic inputs
|
505 |
def run_crew(api_key: str, job_url: str, company_name: str, resume_pdf_path: str):
|
506 |
if not api_key:
|
507 |
-
return "β οΈ Please provide a valid
|
508 |
|
509 |
os.environ["HUGGINGFACEHUB_API_TOKEN"] = f"{api_key}" # Set API key securely
|
510 |
# os.environ["HUGGINGFACEHUB_API_TOKEN"] = userdata.get('HF_TOKEN')
|
@@ -515,6 +494,19 @@ def run_crew(api_key: str, job_url: str, company_name: str, resume_pdf_path: str
|
|
515 |
file_paths=[resume_pdf_path])
|
516 |
# Initialize CrewAI with resume knowledge
|
517 |
print(resume_pdf_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
crew = Crew(
|
519 |
agents=[resume_analyzer, job_analyzer, company_researcher, resume_writer, report_generator],
|
520 |
tasks=[analyze_job_task, optimize_resume_task, research_company_task, generate_resume_task, generate_report_task ],
|
@@ -529,21 +521,6 @@ def run_crew(api_key: str, job_url: str, company_name: str, resume_pdf_path: str
|
|
529 |
|
530 |
# Run AI pipeline
|
531 |
result_extractor = crew.kickoff(inputs=inputs)
|
532 |
-
# Ensure output exists before writing files
|
533 |
-
# optimized_resume_text = result_extractor.get('optimized_resume') if isinstance(result_extractor, dict) and 'optimized_resume' in result_extractor else "No resume data generated."
|
534 |
-
# final_report_text = result_extractor.get('final_report') if isinstance(result_extractor, dict) and 'final_report' in result_extractor else "No report generated."
|
535 |
-
|
536 |
-
# # Save outputs as markdown files
|
537 |
-
# optimized_resume_path = os.path.join(OUTPUT_DIR, "optimized_resume.md")
|
538 |
-
# final_report_path = os.path.join(OUTPUT_DIR, "final_report.md")
|
539 |
-
|
540 |
-
# with open(optimized_resume_path, "w", encoding="utf-8") as resume_file:
|
541 |
-
# resume_file.write(f"# Optimized Resume\n\n{optimized_resume_text}\n")
|
542 |
-
|
543 |
-
# with open(final_report_path, "w", encoding="utf-8") as report_file:
|
544 |
-
# report_file.write(f"# AI Resume Optimization Report\n\n{final_report_text}\n")
|
545 |
-
|
546 |
-
# return "β
Resume processed successfully! Download the files below.", optimized_resume_path, final_report_path
|
547 |
|
548 |
return result_extractor
|
549 |
|
@@ -590,7 +567,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
590 |
gr.Markdown("# π€ AI Resume Optimizer π")
|
591 |
gr.Markdown("Get Complete analysis of your resume")
|
592 |
|
593 |
-
api_key = gr.Textbox(label="π
|
594 |
job_url = gr.Textbox(label="π Job URL", placeholder="Paste job listing URL here")
|
595 |
company_name = gr.Textbox(label="π’ Company Name", placeholder="Enter company name")
|
596 |
resume_pdf = gr.File(label="π Upload Resume (PDF Only)")
|
@@ -605,4 +582,4 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
605 |
|
606 |
# Launch the UI
|
607 |
if __name__ == "__main__":
|
608 |
-
demo.launch()
|
|
|
25 |
# )
|
26 |
from langchain_community.llms import HuggingFaceHub
|
27 |
#HuggingFaceH4/zephyr-7b-beta"
|
28 |
+
# llm = HuggingFaceHub(
|
29 |
+
# repo_id="mistralai/Mistral-7B-Instruct-v0.2",
|
30 |
+
# task="text-generation",
|
31 |
+
# )
|
32 |
|
33 |
class SkillScore(BaseModel):
|
34 |
skill_name: str = Field(description="Name of the skill being scored")
|
|
|
255 |
providing actionable suggestions for improvement. Your recommendations always
|
256 |
focus on both human readability and ATS compatibility.""",
|
257 |
verbose=True,
|
258 |
+
#llm = llm, # Commenting out llm here
|
259 |
# knowledge_sources=[pdf_source],
|
260 |
)
|
261 |
job_analyzer = Agent(
|
|
|
268 |
and soft skills requirements, and can evaluate experience levels accurately.""",
|
269 |
verbose=True,
|
270 |
tools=[ScrapeWebsiteTool()],
|
271 |
+
#llm = llm, # Commenting out llm here
|
272 |
|
273 |
# knowledge_sources=[pdf_source],
|
274 |
)
|
|
|
282 |
candidates for interviews. """,
|
283 |
tools=[SerperDevTool()],
|
284 |
verbose=True,
|
285 |
+
#llm = llm, # Commenting out llm here
|
286 |
|
287 |
# knowledge_sources=[pdf_source],
|
288 |
|
|
|
296 |
beautifully formatted, ATS-friendly documents that maintain professionalism
|
297 |
while showcasing candidate strengths effectively.""",
|
298 |
verbose=True,
|
299 |
+
#llm = llm, # Commenting out llm here
|
300 |
|
301 |
)
|
302 |
report_generator = Agent(
|
|
|
309 |
into clear, actionable insights with proper markdown formatting, emojis, and
|
310 |
visual elements that make information both appealing and easily digestible.""",
|
311 |
verbose=True,
|
312 |
+
#llm = llm, # Commenting out llm here
|
313 |
|
314 |
)
|
315 |
|
316 |
analyze_job_task = Task(
|
317 |
description="""Analyze the {job_url} description and score the candidate's fit based on their resume.
|
318 |
Output will be saved as structured JSON data.
|
|
|
319 |
1. Extract Requirements:
|
320 |
- Technical skills (required vs nice-to-have)
|
321 |
- Soft skills
|
322 |
- Experience levels
|
323 |
- Education requirements
|
324 |
- Industry knowledge
|
|
|
325 |
2. Score Technical Skills (35% of total):
|
326 |
- For each required skill:
|
327 |
* Match Level (0-1): How well does candidate's experience match?
|
328 |
* Years Experience: Compare to required years
|
329 |
* Context Score: How relevant is their usage of the skill?
|
330 |
- Calculate weighted average based on skill importance
|
|
|
331 |
3. Score Soft Skills (20% of total):
|
332 |
- Identify soft skills from resume
|
333 |
- Compare against job requirements
|
334 |
- Consider context and demonstration of skills
|
|
|
335 |
4. Score Experience (25% of total):
|
336 |
- Years of relevant experience
|
337 |
- Role similarity
|
338 |
- Industry relevance
|
339 |
- Project scope and complexity
|
|
|
340 |
5. Score Education (10% of total):
|
341 |
- Degree level match
|
342 |
- Field of study relevance
|
343 |
- Additional certifications
|
|
|
344 |
6. Score Industry Knowledge (10% of total):
|
345 |
- Years in similar industry
|
346 |
- Domain expertise
|
347 |
- Industry-specific achievements
|
|
|
348 |
7. Calculate Overall Score:
|
349 |
- Weighted average of all components
|
350 |
- Identify key strengths and gaps
|
|
|
360 |
description= """
|
361 |
Review the provided resume against the job analysis and create structured optimization suggestions.
|
362 |
Output will be saved as structured JSON data.
|
|
|
363 |
1. Content Analysis:
|
364 |
- Compare resume content with job requirements
|
365 |
- Identify missing keywords and skills
|
366 |
- Analyze achievement descriptions
|
367 |
- Check for ATS compatibility
|
|
|
368 |
2. Structure Review:
|
369 |
- Evaluate section organization
|
370 |
- Check formatting consistency
|
371 |
- Assess information hierarchy
|
372 |
- Verify contact details
|
|
|
373 |
3. Generate Suggestions:
|
374 |
- Content improvements with before/after examples
|
375 |
- Skills to highlight based on job match
|
|
|
393 |
- Culture and values
|
394 |
- Market position
|
395 |
- Growth trajectory
|
|
|
396 |
2. Interview Preparation:
|
397 |
- Common interview questions
|
398 |
- Company-specific topics
|
|
|
411 |
Using the optimization suggestions and job analysis from previous steps,
|
412 |
create a polished resume in markdown format.
|
413 |
Do not add markdown code blocks like '```'.
|
|
|
414 |
1. Content Integration:
|
415 |
- Incorporate optimization suggestions
|
416 |
- Add missing keywords and skills
|
417 |
- Enhance achievement descriptions
|
418 |
- Ensure ATS compatibility
|
|
|
419 |
2. Formatting:
|
420 |
- Use proper markdown headers (#, ##, ###)
|
421 |
- Apply consistent styling
|
422 |
- Create clear section hierarchy
|
423 |
- Use bullet points effectively
|
|
|
424 |
3. Documentation:
|
425 |
- Track changes made
|
426 |
- Note preserved elements
|
|
|
439 |
description="""
|
440 |
Create an executive summary report using data from previous steps.
|
441 |
Format in markdown without code blocks '```'.
|
|
|
442 |
1. Data Integration:
|
443 |
- Job analysis and scores
|
444 |
- Resume optimization details
|
445 |
- Company research insights
|
446 |
- Final resume changes
|
|
|
447 |
2. Report Sections:
|
448 |
## Executive Summary
|
449 |
- Overall match score and quick wins
|
450 |
- Key strengths and improvement areas
|
451 |
- Action items priority list
|
|
|
452 |
## Job Fit Analysis
|
453 |
- Detailed score breakdown
|
454 |
- Skills match assessment
|
455 |
- Experience alignment
|
|
|
456 |
## Optimization Overview
|
457 |
- Key resume improvements
|
458 |
- ATS optimization results
|
459 |
- Impact metrics
|
|
|
460 |
## Company Insights
|
461 |
- Culture fit analysis
|
462 |
- Interview preparation tips
|
463 |
- Key talking points
|
|
|
464 |
## Next Steps
|
465 |
- Prioritized action items
|
466 |
- Skill development plan
|
467 |
- Application strategy
|
|
|
468 |
3. Formatting:
|
469 |
- Use proper markdown headers
|
470 |
- Include relevant emojis
|
|
|
483 |
# Function to run CrewAI with dynamic inputs
|
484 |
def run_crew(api_key: str, job_url: str, company_name: str, resume_pdf_path: str):
|
485 |
if not api_key:
|
486 |
+
return "β οΈ Please provide a valid HUGGINGFACEHUB_API_TOKEN API Key."
|
487 |
|
488 |
os.environ["HUGGINGFACEHUB_API_TOKEN"] = f"{api_key}" # Set API key securely
|
489 |
# os.environ["HUGGINGFACEHUB_API_TOKEN"] = userdata.get('HF_TOKEN')
|
|
|
494 |
file_paths=[resume_pdf_path])
|
495 |
# Initialize CrewAI with resume knowledge
|
496 |
print(resume_pdf_path)
|
497 |
+
# Initialize HuggingFaceHub with API token
|
498 |
+
llm = HuggingFaceHub(
|
499 |
+
repo_id="mistralai/Mistral-7B-Instruct-v0.2",
|
500 |
+
task="text-generation",
|
501 |
+
huggingfacehub_api_token=api_key,
|
502 |
+
)
|
503 |
+
# Create agents with the initialized llm
|
504 |
+
resume_analyzer.llm = llm
|
505 |
+
job_analyzer.llm = llm
|
506 |
+
company_researcher.llm = llm
|
507 |
+
resume_writer.llm = llm
|
508 |
+
report_generator.llm = llm
|
509 |
+
|
510 |
crew = Crew(
|
511 |
agents=[resume_analyzer, job_analyzer, company_researcher, resume_writer, report_generator],
|
512 |
tasks=[analyze_job_task, optimize_resume_task, research_company_task, generate_resume_task, generate_report_task ],
|
|
|
521 |
|
522 |
# Run AI pipeline
|
523 |
result_extractor = crew.kickoff(inputs=inputs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
524 |
|
525 |
return result_extractor
|
526 |
|
|
|
567 |
gr.Markdown("# π€ AI Resume Optimizer π")
|
568 |
gr.Markdown("Get Complete analysis of your resume")
|
569 |
|
570 |
+
api_key = gr.Textbox(label="π HUGGINGFACEHUB_API_TOKEN Key", placeholder="Enter your HUGGINGFACEHUB_API_TOKEN securely")
|
571 |
job_url = gr.Textbox(label="π Job URL", placeholder="Paste job listing URL here")
|
572 |
company_name = gr.Textbox(label="π’ Company Name", placeholder="Enter company name")
|
573 |
resume_pdf = gr.File(label="π Upload Resume (PDF Only)")
|
|
|
582 |
|
583 |
# Launch the UI
|
584 |
if __name__ == "__main__":
|
585 |
+
demo.launch()
|