Spaces:
Build error
Build error
| import os | |
| import gradio as gr | |
| import requests | |
| import PyPDF2 | |
| import spacy | |
| from transformers import pipeline | |
| # Load spaCy for NER tasks | |
| nlp = spacy.load("en_core_web_sm") | |
| # Summarization model | |
| summarizer = pipeline("summarization", model="facebook/bart-large-cnn") | |
| # Sentiment analysis model | |
| sentiment_analyzer = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english") | |
| # Set up your Groq API endpoint and API key | |
| GROQ_API_URL = "https://api.groq.com/v1/models/llama" # Update this if needed | |
| GROQ_API_KEY = "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" # Replace with your actual API key | |
| def extract_text_from_pdf(file): | |
| """Extract text from uploaded PDF file.""" | |
| if file is None: | |
| return "" | |
| try: | |
| pdf_reader = PyPDF2.PdfReader(file) | |
| text = "" | |
| for page in pdf_reader.pages: | |
| page_text = page.extract_text() or "" | |
| text += page_text | |
| return text | |
| except Exception as e: | |
| return f"Error extracting PDF text: {str(e)}" | |
| def extract_text_from_file(file): | |
| """Extract text from uploaded file (PDF or TXT).""" | |
| if file is None: | |
| return "" | |
| if file.name.endswith('.pdf'): | |
| return extract_text_from_pdf(file) | |
| elif file.name.endswith('.txt'): | |
| return file.read().decode('utf-8') | |
| else: | |
| return "Unsupported file format. Please upload PDF or TXT files only." | |
| def extract_skills(text): | |
| """Extract skills from text using a pre-trained NER model.""" | |
| doc = nlp(text) | |
| skills = [ent.text for ent in doc.ents if ent.label_ == "SKILL"] | |
| return list(set(skills)) | |
| def extract_education_and_experience(text): | |
| """Extract education and experience information from text using NER.""" | |
| doc = nlp(text) | |
| education = [ent.text for ent in doc.ents if ent.label_ in ["EDUCATION", "DEGREE"]] | |
| experience = [ent.text for ent in doc.ents if ent.label_ == "EXPERIENCE"] | |
| return { | |
| 'education': list(set(education)), | |
| 'experience': list(set(experience)) | |
| } | |
| def calculate_match_percentage(resume_skills, job_skills): | |
| """Calculate the match percentage between resume skills and job requirements.""" | |
| if not job_skills: | |
| return 0 | |
| matching_skills = set(resume_skills).intersection(set(job_skills)) | |
| return (len(matching_skills) / len(job_skills)) * 100 | |
| def call_groq_api(prompt): | |
| """Call the Groq API with the prompt and return the response.""" | |
| headers = { | |
| "Authorization": f"Bearer {GROQ_API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| payload = { | |
| "model": "llama3-8b-8192", # Use the specified LLaMA model | |
| "prompt": prompt, | |
| "max_tokens": 150 # Adjust as needed | |
| } | |
| try: | |
| response = requests.post(GROQ_API_URL, headers=headers, json=payload) | |
| if response.status_code == 200: | |
| return response.json().get("output", "No output received.") | |
| else: | |
| return f"API call failed with status {response.status_code}: {response.text}" | |
| except requests.exceptions.RequestException as e: | |
| return f"Request failed: {str(e)}" | |
| def summarize_text(text, max_length=100): | |
| """Summarize the input text using the summarization model.""" | |
| return summarizer(text, max_length=max_length, min_length=30, do_sample=False)[0]['summary_text'] | |
| def sentiment_analysis(text): | |
| """Perform sentiment analysis on the given text.""" | |
| return sentiment_analyzer(text)[0] | |
| def analyze_resume_and_job(resume_file, job_desc_file): | |
| """Main function to analyze resume and job description.""" | |
| try: | |
| # Extract text from files | |
| resume_text = extract_text_from_file(resume_file) | |
| job_desc_text = extract_text_from_file(job_desc_file) | |
| if not resume_text or not job_desc_text: | |
| return { | |
| "error": "Could not extract text from one or both files" | |
| } | |
| # Summarize resume and job description | |
| resume_summary = summarize_text(resume_text) | |
| job_desc_summary = summarize_text(job_desc_text) | |
| # Perform sentiment analysis on the resume summary | |
| resume_sentiment = sentiment_analysis(resume_summary) | |
| # Extract information from resume | |
| resume_skills = extract_skills(resume_text) | |
| resume_info = extract_education_and_experience(resume_text) | |
| # Extract information from job description | |
| job_skills = extract_skills(job_desc_text) | |
| job_info = extract_education_and_experience(job_desc_text) | |
| # Calculate match percentages | |
| skills_match = calculate_match_percentage(resume_skills, job_skills) | |
| # Prepare input for LLaMA via Groq API | |
| input_prompt = f"Analyze the following resume: {resume_text[:300]} and job description: {job_desc_text[:300]}." | |
| # Call Groq API to analyze using LLaMA | |
| llama_analysis = call_groq_api(input_prompt) | |
| # Prepare analysis results | |
| summary = f""" | |
| ### Summary Analysis | |
| - Overall Skills Match: {skills_match:.1f}% | |
| - Experience Found: {', '.join(resume_info['experience'])} | |
| - Education Found: {', '.join(resume_info['education'])} | |
| """ | |
| skills = f""" | |
| ### Skills Analysis | |
| Resume Skills: | |
| {', '.join(resume_skills)} | |
| Required Skills: | |
| {', '.join(job_skills)} | |
| Missing Skills: | |
| {', '.join(set(job_skills) - set(resume_skills))} | |
| """ | |
| qualifications = f""" | |
| ### Qualifications | |
| Education Found: | |
| {', '.join(resume_info['education'])} | |
| Required Education: | |
| {', '.join(job_info['education'])} | |
| """ | |
| sentiment = f""" | |
| ### Sentiment Analysis | |
| Resume Sentiment: {resume_sentiment['label']} (Confidence: {resume_sentiment['score']:.2f}) | |
| """ | |
| # Generate recommendation based on skills match | |
| recommendation = "Recommendation based on skills match and experience." | |
| if skills_match >= 70: | |
| recommendation = "Strong Match - Recommended for interview." | |
| elif skills_match >= 50: | |
| recommendation = "Moderate Match - Consider for interview with focus on missing skills." | |
| else: | |
| recommendation = "Low Match - May not meet core requirements." | |
| recommendation = f""" | |
| ### Recommendation | |
| {recommendation} | |
| """ | |
| return { | |
| "summary": summary.strip(), | |
| "skills": skills.strip(), | |
| "qualifications": qualifications.strip(), | |
| "recommendation": recommendation.strip(), | |
| "llama_analysis": llama_analysis.strip(), | |
| "sentiment": sentiment.strip(), | |
| "resume_summary": resume_summary.strip(), | |
| "job_summary": job_desc_summary.strip() | |
| } | |
| except Exception as e: | |
| return { | |
| "error": f"Analysis failed: {str(e)}" | |
| } | |
| # Create Gradio interface | |
| def create_interface(): | |
| with gr.Blocks(title="Resume Analyzer", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# Smart Resume Analyzer") | |
| gr.Markdown("Upload your resume and job description for instant analysis") | |
| with gr.Row(): | |
| resume_input = gr.File(label="Upload Resume (PDF/TXT)") | |
| job_desc_input = gr.File(label="Upload Job Description (PDF/TXT)") | |
| analyze_button = gr.Button("Analyze") | |
| with gr.Tabs(): | |
| with gr.TabItem("Summary"): | |
| summary_output = gr.Markdown() | |
| with gr.TabItem("Skills Analysis"): | |
| skills_output = gr.Markdown() | |
| with gr.TabItem("Qualifications"): | |
| qualifications_output = gr.Markdown() | |
| with gr.TabItem("Recommendation"): | |
| recommendation_output = gr.Markdown() | |
| with gr.TabItem("LLaMA Analysis"): | |
| llama_output = gr.Markdown() | |
| with gr.TabItem("Sentiment Analysis"): | |
| sentiment_output = gr.Markdown() | |
| with gr.TabItem("Resume Summary"): | |
| resume_summary_output = gr.Markdown() | |
| with gr.TabItem("Job Description Summary"): | |
| job_summary_output = gr.Markdown() | |
| def analyze(resume_file, job_desc_file): | |
| if not resume_file or not job_desc_file: | |
| return "Please upload both resume and job description." | |
| analysis_results = analyze_resume_and_job(resume_file, job_desc_file) | |
| summary_output.update(analysis_results.get("summary", "")) | |
| skills_output.update(analysis_results.get("skills", "")) | |
| qualifications_output.update(analysis_results.get("qualifications", "")) | |
| recommendation_output.update(analysis_results.get("recommendation", "")) | |
| llama_output.update(analysis_results.get("llama_analysis", "")) | |
| sentiment_output.update(analysis_results.get("sentiment", "")) | |
| resume_summary_output.update(analysis_results.get("resume_summary", "")) | |
| job_summary_output.update(analysis_results.get("job_summary", "")) | |
| analyze_button.click(analyze, inputs=[resume_input, job_desc_input]) | |
| return demo | |
| # Launch Gradio app | |
| if __name__ == "__main__": | |
| create_interface().launch() | |