Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import os | |
| from langchain_openai import ChatOpenAI | |
| from crewai import Agent, Task, Crew | |
| import PyPDF2 | |
| from docx import Document | |
| # Load environment variables | |
| api_key = os.getenv("OPENAI_API_KEY") | |
| os.environ["OPENAI_API_KEY"] = api_key | |
| # Initialize LLM | |
| llm = ChatOpenAI( | |
| model_name="gpt-4o-mini", # Not "gpt-4o-mini", valid model names are "gpt-4o", "gpt-4-turbo", "gpt-3.5-turbo" | |
| temperature=0, | |
| openai_api_key=os.getenv("OPENAI_API_KEY") | |
| ) | |
| # Function to extract text from resume files | |
| def extract_text_from_file(file): | |
| text = "" | |
| if file.type == "application/pdf": | |
| pdf_reader = PyPDF2.PdfReader(file) | |
| for page in pdf_reader.pages: | |
| text += page.extract_text() + "\n" | |
| elif file.type in ["application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/msword"]: | |
| doc = Document(file) | |
| for para in doc.paragraphs: | |
| text += para.text + "\n" | |
| return text | |
| # Define Agents | |
| resume_agent = Agent( | |
| role="Resume Keyword Extractor", | |
| goal="Extract important skills and keywords from resumes", | |
| backstory="An advanced ATS system that extracts relevant technical skills, tools, programming languages, and certifications from resumes for recruiters.", | |
| verbose=True, | |
| llm=llm # Make sure llm is initialized before this | |
| ) | |
| jd_agent = Agent( | |
| role="Job Description Analyzer", | |
| goal="Extract key skills and responsibilities from job descriptions", | |
| backstory="An AI hiring assistant that understands job requirements", | |
| verbose=True, | |
| llm=llm | |
| ) | |
| match_agent = Agent( | |
| role="Resume & JD Matcher", | |
| goal="Compare resume with job description and provide a match score", | |
| backstory="An AI that evaluates job fit based on ATS criteria", | |
| verbose=True, | |
| llm=llm | |
| ) | |
| st.title("π AI-Powered ATS Scanner") | |
| st.subheader("βοΈ Resume & JD Match Analysis") | |
| resume_files = st.file_uploader("Upload Resumes (PDF/DOC)", type=["pdf", "docx"], accept_multiple_files=True, key="match_resume") | |
| job_description = st.text_area("Paste Job Description", key="match_jd") | |
| if st.button("Analyze Match"): | |
| if resume_files and job_description: | |
| results = [] | |
| for resume_file in resume_files: | |
| resume_text = extract_text_from_file(resume_file) | |
| task_match = Task( | |
| description=f"""Given the following resume text and job description:\n\nResume:\n{resume_text}\n\n | |
| Job Description:\n{job_description}\n\n | |
| Analyze and compare the skills, tools, technologies, and certifications mentioned in both. | |
| Calculate a match score (in percentage) based on the overlap of technical and domain-specific skills. | |
| Additionally, list the important technical skills or certifications mentioned in the Job Description but missing in the Resume. | |
| Do NOT consider soft skills, personality traits, or general statements in the comparison. | |
| Provide the output in this format: | |
| - Match Score: XX% | |
| - Missing Keywords: [List of missing keywords] | |
| """, | |
| agent=match_agent, | |
| expected_output="Match score and missing keywords" | |
| ) | |
| crew = Crew( | |
| agents=[match_agent], | |
| tasks=[task_match], | |
| verbose=False | |
| ) | |
| result = crew.kickoff(inputs={"resume_text": resume_text, "job_description": job_description}) | |
| extracted_keywords = result.tasks_output[0].raw | |
| # Parse result | |
| match_score_line = next((line for line in extracted_keywords.split('\n') if "Match Score" in line), "") | |
| missing_keywords_line = next((line for line in extracted_keywords.split('\n') if "Missing Keywords" in line), "") | |
| try: | |
| score = int(match_score_line.split(":")[1].strip().replace("%", "")) | |
| except: | |
| score = 0 | |
| results.append({ | |
| "Resume": resume_file.name, | |
| "Match Score (%)": score, | |
| "Missing Keywords": missing_keywords_line.split(":", 1)[-1].strip() | |
| }) | |
| # Sort by Match Score descending | |
| results_sorted = sorted(results, key=lambda x: x["Match Score (%)"], reverse=True) | |
| st.success("β ATS Match Results Table") | |
| st.dataframe(results_sorted) | |
| else: | |
| st.warning("Please upload at least one resume and paste the job description.") | |