import streamlit as st import os import openai from dotenv import load_dotenv import os from openai import AzureOpenAI from azure.core.credentials import AzureKeyCredential # Load environment variables from .env file load_dotenv() # Set environment variables for Azure OpenAI ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT") API_KEY = os.getenv("AZURE_OPENAI_API_KEY") DEPLOYMENT_NAME = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME") API_VERSION = os.getenv("AZURE_OPENAI_API_VERION") # Check if the necessary environment variables are loaded if not API_KEY or not ENDPOINT or not DEPLOYMENT_NAME: st.error("Azure OpenAI credentials are missing. Please check your .env file.") st.stop() client = AzureOpenAI( api_version=API_VERSION, azure_endpoint=ENDPOINT, api_key=API_KEY, ) # Function to extract information from PD using Azure OpenAI GPT-4 model def extract_PD_info_from_azure(text): prompt = f""" Act as an HR recruiter. Carefully evaluate the provided job description (PD) document and extract the following information into the specified structured format. Ensure that all fields are populated. If a field is not explicitly mentioned in the text, use ""N/A"" as the default value. - Requirements Categories to Extract: - Location - Country - City - Department - Required Years of Experience - Responsibilities - Skills - Experience - Education - Other Factors - Languages PD Text: {text} """ response = client.chat.completions.create( messages=[ { "role": "system", "content": "You are a helpful assistant.", }, { "role": "user", "content": prompt, } ], max_tokens=4096, temperature=1.0, top_p=1.0, model=DEPLOYMENT_NAME ) try: result = response.choices[0].message.content return result except Exception as e: st.error(f"Error occurred while contacting Azure OpenAI: {e}") return None # Function to extract information from PD using Azure OpenAI GPT-4 model def extract_criterions_from_azure(text): prompt = f""" Act as an HR recruiter. Based on the main criteria categories defined below, extract bullet items from the provided PD text. For each bullet item, create a Criterion Object with the following fields: Instructions: - Criterions should represent each item listed under each PD section (Skills,Education, Experience, Other Factors): 1- For each item under PD sections mentioned above, ensure to have related criteria item created to measure it. only skip those items may not relevant or negate a state such as ""There are no extra requirements specified for this position"" . - PD sections with NA value, dont create Crtierion for it at all. - Ensure to add Criterions for Languages Proficiency based on its identified level - Ensure to add Criterions that has clue within the PD to measure it, if no clue in PD, do not consider it. **Important:** - Output all Criterion items together under each other as follows, make sure category part formated in bold: 1- Item 1 (Category: Skills) 2- Item 2 (Category: Experience) PD Text: {text} """ response = client.chat.completions.create( messages=[ { "role": "system", "content": "You are a helpful assistant.", }, { "role": "user", "content": prompt, } ], max_tokens=4096, temperature=1.0, top_p=1.0, model=DEPLOYMENT_NAME ) try: result = response.choices[0].message.content return result except Exception as e: st.error(f"Error occurred while contacting Azure OpenAI: {e}") return None def extract_weights_from_azure(text): prompt = f""" Act as an HR recruiter. Based on the extracted criteria records from the previous step, evaluate the importance of each requirement category type based on provided criteria and assign a weight to it. The weight should reflect how critical the category is for the job, with a score from 1 to 100, ensuring that the sum of all weights does not exceed 100. Requirements Categories to Evaluate and Assign Weights: Location (keyword: Location) Required Years of Experience (keyword: Required_Years_of_Experience) Responsibilities (keyword: Responsibilities) Skills (keyword: Skills) Experience (keyword: Experience) Education (keyword: Education) Other Factors (keyword: Other_Factors) Languages (keyword: Language_Proficiency) Instructions: Dynamic Handling of Categories: **Include categories that have explicit criteria mentioned in the Criterions JSON Content. **Exclude categories that are not present in the content. **Adjust the weights dynamically so the sum of all assigned weights does not exceed 100. Weight Assignment: **Assign a weight (1–100) to each category based on its importance to the job. **Distribute weights logically, ensuring critical categories like Skills, Experience, Education, and Language Proficiency are well represented. **Ensure the sum of all weights, including Extra_Requirement_Three if present, totals exactly 100. **If the total exceeds or is less than 100, proportionally adjust the weights of the other categories. Category Justification: **For each category, provide a detailed justification of its importance, tied to the specific requirements in the job description. **Explain how the requirements support the assigned weight and their direct relevance to job performance or success. Final Adjustment Rule: After assigning initial weights: ** Check if the total weight equals 100. ** If the total is less than 100, proportionally increase the weights of all present categories. ** If the total is more than 100, proportionally decrease the weights of all present categories. ** Preserve explicit weight floors (e.g., Experience greater than or equal to 15%) when adjusting. ** The final output must sum to exactly 100. Output Format: **The response must strictly follow below, including the Category_Description for each category. **Ensure that all categories in the PD criteria are represented in the weights, and no category is missing. **If Language_Proficiency is found in the criteria, it should have a weight assigned and be included in the output. **If Extra_Requirement_One is found in the criteria, it should have a weight assigned and be included in the output. **If Extra_Requirement_Two is found in the criteria, it should have a weight assigned and be included in the output. **If Extra_Requirement_Three is found in the criteria, it should have a weight assigned and be included in the output. Example Output: 1- Skills (Weight: 35%): 2- Experience (Weight: 25%): 3- Education (Weight: 25%): 4- Language Proficincy (Weight: 15%): Criterions list: {text} """ response = client.chat.completions.create( messages=[ { "role": "system", "content": "You are a helpful assistant.", }, { "role": "user", "content": prompt, } ], max_tokens=4096, temperature=1.0, top_p=1.0, model=DEPLOYMENT_NAME ) try: result = response.choices[0].message.content return result except Exception as e: st.error(f"Error occurred while contacting Azure OpenAI: {e}") return None # Streamlit App UI st.title("AI Screening - Post Description Information Extraction") st.write("Enter the PD text below, and the agent will extract relevant information such as job title, location, skills, experience, and education, Criterions, Criterion Weights.") # Text area for entering PD content manually pd_text = st.text_area("Enter PD Text", height=300) if pd_text: # Display the entered PD text # st.subheader("Entered Text from PD") # st.text_area("PD Text", pd_text, height=300) # Extract relevant information using Azure OpenAI GPT-4 extracted_info = extract_PD_info_from_azure(pd_text) # Display the extracted information if extracted_info: st.subheader("Extracted Information") with st.chat_message("assistant", avatar="🤖"): st.markdown( f"
{extracted_info}
", unsafe_allow_html=True, ) # st.write(extracted_info) else: st.write("Could not extract information. Please try again.") # Extract Criterions extracted_criterions = extract_criterions_from_azure(extracted_info) # Display the extracted information if extracted_criterions: st.subheader("Extracted Criterion List") # Immediately display the assistant's response with st.chat_message("assistant", avatar="🤖"): st.markdown( f"
{extracted_criterions}
", unsafe_allow_html=True, ) # st.write(extracted_criterions) else: st.write("Could not extract criterion information. Please try again.") # Extract Criterions extracted_weights = extract_weights_from_azure(extracted_criterions) # Display the extracted information if extracted_weights: st.subheader("Extracted Weights List") with st.chat_message("assistant", avatar="🤖"): st.markdown( f"
{extracted_weights}
", unsafe_allow_html=True, ) # st.write(extracted_weights) else: st.write("Could not extract weights information. Please try again.") #