Spaces:
Sleeping
Sleeping
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%): <short description about required skills for this job> | |
2- Experience (Weight: 25%): <short description about required experiences for this job> | |
3- Education (Weight: 25%): <short description about required education for this job> | |
4- Language Proficincy (Weight: 15%): <short description about required languages for this job> | |
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"<div class='chat-message assistant'>{extracted_info}</div>", | |
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"<div class='chat-message assistant'>{extracted_criterions}</div>", | |
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"<div class='chat-message assistant'>{extracted_weights}</div>", | |
unsafe_allow_html=True, | |
) | |
# st.write(extracted_weights) | |
else: | |
st.write("Could not extract weights information. Please try again.") # | |