Spaces:
Build error
Build error
| import aiohttp | |
| import asyncio | |
| import nest_asyncio | |
| import streamlit as st | |
| import time | |
| from pdfminer.high_level import extract_text | |
| from docx import Document | |
| import os | |
| from pdf2image import convert_from_bytes | |
| import base64 | |
| import io | |
| import certifi | |
| import ssl | |
| # from dotenv import load_dotenv | |
| import json | |
| from prompts import ( | |
| ANALYSIS_PROMPT, | |
| ATS_PROMPT, | |
| OBJECTIVE_ANALYSIS_PROMPT, | |
| SCORING_PROMPT, | |
| DEFUALT_PREP_GUIDE, | |
| LOW_PREP_GUIDE | |
| ) | |
| # load_dotenv() | |
| api_key = os.getenv('OPENAI_API_KEY') | |
| nest_asyncio.apply() | |
| def generate_prompts(num_images): | |
| return { | |
| "SCORING": SCORING_PROMPT, | |
| "ANALYSIS": ANALYSIS_PROMPT, | |
| "OBJECTIVE_ANALYSIS": OBJECTIVE_ANALYSIS_PROMPT, | |
| "ATS": ATS_PROMPT.format(pages=num_images), | |
| } | |
| def encode_image(image): | |
| buffered = io.BytesIO() | |
| image.save(buffered, format="PNG") | |
| return base64.b64encode(buffered.getvalue()).decode('utf-8') | |
| def extract_text_from_pdf(file): | |
| try: | |
| # Reset file pointer to the start of the file | |
| file.seek(0) | |
| text = extract_text(file) | |
| return text | |
| except Exception as e: | |
| print(f"An error occurred: {e}") | |
| return None | |
| def extract_text_from_file(file): | |
| file_extension = os.path.splitext(file.name)[1] | |
| if file_extension == '.pdf': | |
| return extract_text_from_pdf(file) | |
| elif file_extension == '.docx': | |
| doc = Document(file) | |
| return "\n".join([paragraph.text for paragraph in doc.paragraphs]) | |
| elif file_extension == '.txt': | |
| return file.read().decode('utf-8') | |
| else: | |
| return "Unsupported file type" | |
| async def generate_completion(message, api_key): | |
| url = "https://api.openai.com/v1/chat/completions" | |
| headers = { | |
| "Content-Type": "application/json", | |
| "Authorization": f"Bearer {api_key}" | |
| } | |
| payload = { | |
| "model": "gpt-4o", | |
| "messages": message, | |
| "temperature": 0.1, | |
| "response_format": {"type": "json_object"} | |
| } | |
| ssl_context = ssl.create_default_context(cafile=certifi.where()) | |
| # Use certifi to specify the CA bundle for SSL certificate verification | |
| async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context)) as session: | |
| async with session.post(url, headers=headers, json=payload) as response: | |
| if response.status != 200: | |
| print(f"Error: {response.status}") | |
| return None | |
| response_json = await response.json() | |
| return response_json | |
| async def main(resume_text, job_description): | |
| analysis_types_and_prompts = { | |
| "SCORING": SCORING_PROMPT, | |
| "ANALYSIS": ANALYSIS_PROMPT, | |
| "OBJECTIVE_ANALYSIS": OBJECTIVE_ANALYSIS_PROMPT, | |
| "ATS": ATS_PROMPT.format(pages=pdf_length) | |
| } | |
| tasks = [] | |
| for analysis, prompt in analysis_types_and_prompts.items(): | |
| messages = construct_message( | |
| analysis, | |
| prompt, | |
| resume_text, | |
| job_description, | |
| base_image if analysis == "ATS" else None, | |
| ) | |
| tasks.append(generate_completion(messages,api_key)) | |
| scoring_task = asyncio.create_task(tasks[0]) | |
| other_tasks = tasks[1:] | |
| other_tasks_futures = [asyncio.create_task(task) for task in other_tasks] | |
| result_scoring = await scoring_task | |
| scoring_json = json.loads(result_scoring['choices'][0]['message']['content']) | |
| if len(scoring_json) == 1: | |
| return scoring_json, None # Error dictionary | |
| other_results = await asyncio.gather(*other_tasks_futures) | |
| responses_async = [result_scoring] + other_results | |
| if scoring_json['Overall']['Score'] <=50: | |
| guide_prompt = LOW_PREP_GUIDE | |
| else: | |
| guide_prompt = DEFUALT_PREP_GUIDE | |
| return responses_async, guide_prompt | |
| def construct_message(analysis, prompt, resume_text, job_description=None, base_image=None): | |
| if analysis == "ATS": | |
| messages = [ | |
| {"role": "system", "content": prompt}, | |
| {"role": "user", | |
| "content": f"Here is the Job Description: {job_description}"}, | |
| {"role": "user", "content": []} | |
| ] | |
| for image in base_image: | |
| messages[2]["content"].append({ | |
| "type": "image_url", | |
| "image_url": { | |
| "url": f"data:image/png;base64,{image}" | |
| }, | |
| }) | |
| return messages | |
| elif analysis == "OBJECTIVE_ANALYSIS": | |
| return ([ | |
| {"role": "system", "content": prompt}, | |
| {"role": "user", | |
| "content": f"Here is the resume text: {resume_text}"}]) | |
| else: | |
| return ([ | |
| {"role": "system", "content": prompt}, | |
| {"role": "user", | |
| "content": f"Here is the resume text: {resume_text} \n Here is the job description: {job_description}"}]) | |
| st.set_page_config(page_title="Resume Analyzer", layout="centered") | |
| st.title("Resume Analyzer") | |
| job_description_source = st.radio("Job Description Source", ("Upload File", "Paste Text")) | |
| if job_description_source == "Upload File": | |
| job_description_file = st.file_uploader("Upload Job Description", type=['pdf', 'docx', 'txt']) | |
| job_description = extract_text_from_file(job_description_file) if job_description_file else None | |
| else: | |
| job_description = st.text_area("Paste Job Description Here") | |
| resume_file = st.file_uploader("Upload Resume", type=['pdf', 'docx', 'txt']) | |
| if job_description: | |
| st.subheader("Job Description Preview") | |
| st.text_area("Job Description", job_description, height=200) | |
| if resume_file: | |
| resume_text = extract_text_from_file(resume_file) | |
| st.subheader("Resume Preview") | |
| st.text_area("Resume", resume_text, height=200) | |
| resume_file.seek(0) | |
| file_bytes = resume_file.read() | |
| images = convert_from_bytes(file_bytes) | |
| pdf_length = len(images) | |
| base_image = [] | |
| for image in images: | |
| base_image.append(encode_image(image)) | |
| if st.button("Analyze Resume"): | |
| if job_description and resume_file: | |
| start_time = time.time() | |
| responses_async, guide_prompt = asyncio.run(main(resume_text, job_description)) | |
| end_time = time.time() | |
| total_time = end_time - start_time | |
| guide_message = construct_message("GUIDE", guide_prompt, resume_text, job_description) | |
| guide_response = asyncio.run(generate_completion(guide_message, api_key)) | |
| if isinstance(responses_async, dict) and "Error" in responses_async: | |
| error_message = f"Improper file entered: {responses_async['Error']}" | |
| st.write(error_message) | |
| else: | |
| st.subheader("Analysis Result") | |
| st.text_area("Scoring Analysis", responses_async[0]['choices'][0]['message']['content'], height=400) | |
| st.text_area("Gap Analysis", responses_async[1]['choices'][0]['message']['content'], height=400) | |
| st.text_area("Objective Analysis", responses_async[2]['choices'][0]['message']['content'], height=400) | |
| st.text_area("ATS Analysis", responses_async[3]['choices'][0]['message']['content'], height=400) | |
| st.text_area("Interview Prep Guide", guide_response['choices'][0]['message']['content'], height=400) | |
| st.write(f"Image prompt input tokens: {responses_async[2]['usage']['prompt_tokens']}") | |
| # st.write(f"Time taken for OpenAI response: {response_time:.2f} seconds") | |
| st.write(f"Total time taken for execution: {total_time:.2f} seconds") | |
| #Testing JSON Respones: | |
| # testing.run_tests(responses_async, guide_response) | |
| else: | |
| st.error("Please provide both the job description and resume.") | |