# Warning control import warnings warnings.filterwarnings('ignore') #!pip install PyMuPDF #!pip install python-docx #!pip install crewai crewai-tools import fitz # PyMuPDF for PDF processing import docx # python-docx for DOCX processing from crewai_tools import SerperDevTool import os from crewai import Agent, Task, Crew from dotenv import load_dotenv import tempfile # Load environment variables load_dotenv() # Streamlit must be imported after setting page config import streamlit as st # Set page configuration FIRST st.set_page_config(page_title="Smart Resume Analyzer", layout="wide") # Custom CSS for background color st.markdown( f""" """, unsafe_allow_html=True ) # Title and description st.markdown('

Smart Resume Analyzer & Job Matcher

', unsafe_allow_html=True) st.markdown('

Expected Runtime: 1 Min

', unsafe_allow_html=True) # Resume upload section st.markdown("### Upload Your Resume (PDF or DOCX)") uploaded_file = st.file_uploader("Drop File Here or Click to Upload", type=["pdf", "docx"], help="Upload your resume for analysis.",key="resume_upload") # Preferred location input preferred_location = st.text_input("Preferred Location", placeholder="e.g., San Francisco",max_chars=50, key="location_input") # Submit button submit_button = st.button("Submit",icon="😃") # Function to extract text from PDF def extract_text_from_pdf(file_path): """Extracts text from a PDF file using PyMuPDF.""" doc = fitz.open(file_path) text = "" for page in doc: text += page.get_text() return text # Function to extract text from DOCX def extract_text_from_docx(file_path): """Extracts text from a DOCX file using python-docx.""" doc = docx.Document(file_path) fullText = [] for para in doc.paragraphs: fullText.append(para.text) return "\n".join(fullText) # Function to extract text from resume def extract_text_from_resume(file_path): """Determines file type and extracts text.""" if file_path.endswith(".pdf"): return extract_text_from_pdf(file_path) elif file_path.endswith(".docx"): return extract_text_from_docx(file_path) else: return "Unsupported file format." # Initialize agents and tasks def initialize_crew(): search_tool = SerperDevTool() # Agent 1: Resume Advisor resume_advisor = Agent( role="Professional Resume Advisor", goal="Give feedback on the resume to make it stand out in the job market.", verbose=True, backstory="With a strategic mind and an eye for detail, you excel at providing feedback on resumes to highlight the most relevant skills and experiences." ) # Agent 2: Resume Writer resume_writer = Agent( role="Professional Resume Writer", goal="Based on the feedback received from Resume Advisor, make changes to the resume to make it stand out in the job market.", verbose=True, backstory="With a strategic mind and an eye for detail, you excel at refining resumes based on the feedback to highlight the most relevant skills and experiences." ) # Agent 3: Job Researcher job_researcher = Agent( role="Senior Recruitment Consultant", goal="Find the 5 most relevant, recently posted jobs based on the improved resume received from resume advisor and the location preference.", tools=[search_tool], verbose=True, backstory="""As a senior recruitment consultant, your prowess in finding the most relevant jobs based on the resume and location preference is unmatched. You can scan the resume efficiently, identify the most suitable job roles, and search for the best-suited recently posted open job positions at the preferred location.""" ) # Task for Resume Advisor Agent: Give Feedback resume_advisor_task = Task( description=( """Give feedback on the resume to make it stand out for recruiters. Review every section, including the summary, work experience, skills, and education. Suggest to add relevant sections if they are missing. Also, give an overall score to the resume out of 10. This is the resume: {resume}""" ), expected_output="The overall score of the resume followed by the feedback in bullet points.", agent=resume_advisor ) # Task for Resume Writer Agent: Improve Resume resume_writer_task = Task( description=( """Rewrite the resume based on the feedback to make it stand out for recruiters. You can adjust and enhance the resume but don't make up facts. Review and update every section, including the summary, work experience, skills, and education to better reflect the candidate's abilities. This is the resume: {resume}""" ), expected_output="Resume in markdown format that effectively highlights the candidate's qualifications and experiences.", context=[resume_advisor_task], agent=resume_writer ) # Task for Job Researcher Agent: Find Jobs research_task = Task( description="""Find the 5 most relevant recent job postings based on the resume received from resume advisor and location preference. This is the preferred location: {location}. Use the tools to gather relevant content and shortlist the 5 most relevant, recent, job openings.""", expected_output="A bullet point list of the 5 job openings, with the appropriate links and detailed description about each job, in markdown format.", agent=job_researcher ) # Create Crew crew = Crew( name="Resume Analysis Crew", tasks=[resume_advisor_task, resume_writer_task, research_task], agents=[resume_advisor, resume_writer, job_researcher] ) return crew,resume_advisor_task, resume_writer_task, research_task # Function to run the crew and get results def resume_agent(file_path, location): resume_text = extract_text_from_resume(file_path) crew, resume_advisor_task, resume_writer_task, research_task = initialize_crew() result = crew.kickoff(inputs={"resume": resume_text, "location": location}) # Extract outputs feedback = resume_advisor_task.output.raw.strip("```markdown").strip("```").strip() improved_resume = resume_writer_task.output.raw.strip("```markdown").strip("```").strip() job_roles = research_task.output.raw.strip("```markdown").strip("```").strip() return feedback, improved_resume, job_roles # Handle file upload and processing if submit_button: if uploaded_file is None: st.error("Please upload a resume before submitting.") else: with st.spinner("Analyzing your resume and finding job matches..."): # Save uploaded file to a temporary location with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(uploaded_file.name)[1]) as tmp_file: tmp_file.write(uploaded_file.getvalue()) tmp_file_path = tmp_file.name try: feedback, improved_resume, job_roles = resume_agent(tmp_file_path, preferred_location) st.success("Analysis complete!") st.markdown("## Resume Feedback:") st.markdown(feedback) st.markdown("## Improved Resume Suggestions:") st.markdown(improved_resume) st.markdown("## Relevant Job Roles:") st.markdown(job_roles) except Exception as e: st.error(f"An error occurred: {e}") finally: # Clean up temporary file os.unlink(tmp_file_path)