Spaces:
Sleeping
Sleeping
import streamlit as st | |
from crewai import Agent, Task, Crew, Process, LLM # Import LLM from crewai | |
import os | |
import fitz # PyMuPDF for PDF handling | |
import tempfile | |
from dotenv import load_dotenv | |
import textwrap | |
# Load environment variables | |
load_dotenv() | |
# --- Helper Functions --- | |
def read_pdf(file): | |
"""Reads text from a PDF file.""" | |
try: | |
with fitz.open(stream=file.read(), filetype="pdf") as doc: | |
text = "" | |
for page in doc: | |
text += page.get_text() | |
return text | |
except Exception as e: | |
st.error(f"Error reading PDF: {e}") | |
return None | |
def wrap_text(text, width=80): | |
"""Wraps text to a specified width.""" | |
lines = text.split('\n') | |
wrapped_lines = [] | |
for line in lines: | |
wrapped_lines.extend(textwrap.wrap(line, width=width)) | |
return '\n'.join(wrapped_lines) | |
# --- CrewAI Agents and Tasks --- | |
def create_crew(job_description, resume_text): | |
"""Creates the CrewAI crew with agents and tasks.""" | |
# Configure the LLM using CrewAI's LLM class | |
llm_config = LLM( | |
model_name="gemini-1.5-flash-002", # Use direct model name | |
api_key=os.environ.get("GOOGLE_API_KEY"), # api_key needed for google gen ai | |
temperature=0.7, | |
#convert_system_message_to_human=True # No longer needed with CrewAI LLM | |
) | |
# 1. Resume Analyzer Agent | |
resume_analyzer = Agent( | |
role='Resume Analysis Expert', | |
goal='Thoroughly analyze the provided resume and identify its strengths and weaknesses.', | |
backstory="""You are a seasoned resume analyst with years of experience | |
in helping job seekers optimize their resumes. You are adept at | |
identifying key skills, experiences, and formatting issues.""", | |
verbose=True, | |
allow_delegation=False, | |
llm=llm_config # Use the CrewAI LLM configuration | |
) | |
# 2. Job Description Analyzer Agent | |
job_analyzer = Agent( | |
role='Job Description Expert', | |
goal='Analyze the job description and extract key requirements, skills, and keywords.', | |
backstory="""You are a highly skilled job description analyst. | |
You excel at identifying the core requirements, desired skills, and | |
important keywords from any job posting.""", | |
verbose=True, | |
allow_delegation=False, | |
llm=llm_config # Use the CrewAI LLM configuration | |
) | |
# 3. Resume Improvement Suggestor Agent | |
improvement_suggestor = Agent( | |
role='Resume Improvement Specialist', | |
goal='Provide specific, actionable suggestions to improve the resume based on the job description.', | |
backstory="""You are a master resume writer and career coach. You | |
are known for your ability to craft compelling resumes that highlight | |
a candidate's strengths and align them perfectly with job requirements. | |
You provide concrete, easy-to-implement suggestions.""", | |
verbose=True, | |
allow_delegation=False, | |
llm=llm_config # Use the CrewAI LLM configuration | |
) | |
# --- Tasks --- | |
# Task 1: Analyze the Resume | |
task_analyze_resume = Task( | |
description=f"""Analyze the following resume content and identify key skills, experiences, | |
and potential areas for improvement. Focus on the overall structure, clarity, | |
and impact of the resume. Output should be a structured report, not just raw thoughts. | |
Resume: | |
-------------- | |
{resume_text} | |
-------------- | |
""", | |
agent=resume_analyzer, | |
expected_output="A structured report summarizing the resume's strengths, weaknesses, key skills, and areas for improvement." | |
) | |
# Task 2: Analyze the Job Description | |
task_analyze_job_description = Task( | |
description=f"""Analyze the following job description and extract the key requirements, | |
desired skills, preferred qualifications, and any important keywords. | |
Be specific and comprehensive in your analysis. Output a structured summary. | |
Job Description: | |
-------------- | |
{job_description} | |
-------------- | |
""", | |
agent=job_analyzer, | |
expected_output="A structured summary of the job description, including key requirements, desired skills, qualifications, and important keywords." | |
) | |
# Task 3: Suggest Improvements | |
task_suggest_improvements = Task( | |
description=f"""Based on the analysis of the resume and the job description, | |
provide specific and actionable suggestions to improve the resume. Address: | |
1. **Content:** Suggest additions, deletions, or modifications to the resume content to better match the job requirements. | |
2. **Keywords:** Identify keywords from the job description that should be incorporated into the resume. | |
3. **Formatting:** Suggest any formatting changes to improve readability and impact. | |
4. **Overall Strategy:** Provide an overall strategy for tailoring the resume to the specific job. | |
The resume analysis is: {task_analyze_resume.output} | |
The job description analysis is: {task_analyze_job_description.output} | |
""", | |
agent=improvement_suggestor, | |
expected_output="A list of specific, actionable suggestions for improving the resume, covering content, keywords, formatting, and overall strategy, tailored to the job description." | |
) | |
# --- Crew --- | |
crew = Crew( | |
agents=[resume_analyzer, job_analyzer, improvement_suggestor], | |
tasks=[task_analyze_resume, task_analyze_job_description, task_suggest_improvements], | |
verbose=True, | |
process=Process.sequential | |
) | |
return crew | |
# --- Streamlit App --- | |
st.title("Resume Tailoring Assistant") | |
# Input: Job Description | |
job_description = st.text_area("Paste the Job Description Here:", height=200) | |
# Input: Resume (PDF Upload) | |
resume_file = st.file_uploader("Upload Your Resume (PDF)", type="pdf") | |
if st.button("Tailor Resume"): | |
if job_description and resume_file: | |
with st.spinner("Analyzing and generating suggestions..."): | |
resume_text = read_pdf(resume_file) | |
if resume_text: | |
# Create and run the Crew | |
crew = create_crew(job_description, resume_text) | |
result = crew.kickoff() | |
st.subheader("Suggested Improvements:") | |
st.write(wrap_text(result)) | |
else: | |
st.error("Failed to read the resume content.") | |
else: | |
st.warning("Please provide both the job description and your resume.") |