Spaces:
No application file
No application file
import streamlit as st | |
import os | |
import sys | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import datetime | |
import pandas as pd | |
# Adjust the system path to find project modules | |
current_dir = os.path.dirname(os.path.abspath(__file__)) | |
project_root = os.path.dirname(os.path.dirname(os.path.dirname(current_dir))) | |
sys.path.append(project_root) | |
from src.modules.module2_relevancy.relevance_analyzer import EnhancedRelevanceAnalyzer | |
from groq_client import GroqClient | |
from file_processing import extract_text_from_file | |
from src.modules.module3_compare.model import QuestionSimilarityModel | |
from src.modules.module4_bias.bias import screen_questions | |
from src.modules.module1_question_generation.project_controller import Project | |
from src.modules.module1_question_generation.tool_controller import * | |
DATASET_DIR = "dataset" | |
project_control = Project() | |
if 'page' not in st.session_state: | |
st.session_state.page = 'main' | |
if ('accuracy_history' not in st.session_state): | |
st.session_state['accuracy_history'] = { | |
"DSA" : [], | |
"Technical" : [], | |
"Behaviour": [] | |
} | |
def main(): | |
if st.session_state.page == 'main': | |
sidebar() | |
if ('current_project' in st.session_state): | |
if (st.session_state['current_project']['project_name'] == 'default'): | |
st.title("Interview Question Generator & Analyzer") | |
main_page() | |
else: | |
st.subheader('No project selected') | |
elif st.session_state.page == 'configure': | |
configure_page() | |
def sidebar(): | |
st.sidebar.title("Project Options") | |
project_action = st.sidebar.selectbox("Select Action", ["Open Existing Project", "Create New Project"]) | |
if project_action == "Create New Project": | |
new_project_name = st.sidebar.text_input("Enter Project Name") | |
print('Title: ', new_project_name) | |
if st.sidebar.button("Create Project") and new_project_name: | |
if new_project_name in project_control.list_projects(): | |
st.sidebar.error("Project with this name already exists.") | |
else: | |
project_data = project_control.initialize_project(new_project_name) | |
st.session_state["current_project"] = project_data | |
st.success(f"Project '{new_project_name}' created successfully!") | |
elif project_action == "Open Existing Project": | |
existing_projects = project_control.list_projects() | |
selected_project = st.sidebar.selectbox("Select Project", existing_projects) | |
if st.sidebar.button("Open Project") and selected_project: | |
project_data = project_control.load_project(selected_project) | |
if project_data: | |
st.session_state["current_project"] = project_data | |
else: | |
st.sidebar.error("Failed to load project_control.") | |
if ('current_project' in st.session_state and st.sidebar.button('Configure Project')): | |
st.session_state.page = 'configure' | |
def main_page(): | |
client = GroqClient() | |
analyzer = EnhancedRelevanceAnalyzer() | |
similarity_model = QuestionSimilarityModel('dataset/leetcode_dataset.csv') | |
project = st.session_state["current_project"] | |
st.subheader('Project: ', project['project_name']) | |
job_role = st.text_input("Enter Job Role") | |
question_type = st.selectbox("Type of questions", ["DSA", "Technical", "Behaviour"]) | |
jd_file = st.file_uploader("Upload Job Description (PDF/DOCX)", type=["pdf", "docx"]) | |
if jd_file and job_role and question_type and st.button('Get questions') : | |
with st.spinner("Analyzing Job Description..."): | |
jd_text = extract_text_from_file(jd_file) | |
if not analyzer.check_title_jd_match(job_role, jd_text): | |
st.error("⚠️ Job description doesn't match the job title! Upload a relevant JD.") | |
st.stop() | |
questions = client.generate_questions(job_role, jd_text, question_type) | |
# Deterministic | |
d_results = verify_deterministic_assertions(questions, project["assertions"]) | |
df_results = pd.DataFrame(list(d_results.items()), columns=["Assertion Type", "Result"]) | |
st.table(df_results) | |
question_lines = [q.strip() for q in questions.split('\n') if q.strip()] | |
if question_lines and not question_lines[0][0].isdigit(): | |
question_lines = question_lines[1:] | |
# first_five_questions = question_lines[:10] | |
# remaining_questions = question_lines[5:15] | |
scores = [] | |
if (question_type == "DSA"): | |
similarity_results = similarity_model.check_similarity(question_lines) | |
scores = similarity_results | |
st.subheader("DSA questions with similarity analysis") | |
score = 0 | |
for i, (question, result) in enumerate(zip(question_lines, similarity_results), 1): | |
st.write(f"{i}. {question}") | |
score += result["relevance_score"] | |
with st.expander(f"Similarity Analysis for Question {i}"): | |
st.write(f"Similarity Score: {result['relevance_score']:.2f}") | |
st.write(f"Best Match: {result['best_match']['title']}") | |
st.write(f"Difficulty: {result['best_match']['difficulty']}") | |
if result['matched_sources']: | |
st.write("\nSimilar Questions:") | |
for source in result['matched_sources']: | |
st.write(f"- {source['title']} (Difficulty: {source['difficulty']})") | |
overall_similarity = score / len(question_lines) | |
st.metric("Overall Relevance", f"{overall_similarity*100:.1f}%") | |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
project['accuracy_history'][question_type].append((timestamp, overall_similarity)) | |
# if (question_type == "Technical" or question_type == "Behaviour"): | |
if (question_type == "Technical"): | |
for q in question_lines: | |
st.write(f"- {q}") | |
scores = analyzer.calculate_question_scores(jd_text, question_lines) | |
avg_score = sum(scores) / len(scores) | |
half_avg = avg_score / 1.25 | |
count_above_half = sum(1 for s in scores if s > half_avg) | |
overall_relevance = (count_above_half / len(scores)) * 100 | |
st.subheader("Analysis Results") | |
st.metric("Overall Relevance", f"{overall_relevance:.1f}%") | |
# Store accuracy with timestamp | |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
project['accuracy_history'][question_type].append((timestamp, overall_relevance)) | |
if question_type == "Behaviour": | |
valid_bias_questions, invalid_bias_questions, bias_accuracy, validity = screen_questions(question_lines) | |
for i, q in enumerate(question_lines): | |
st.write(f"- {f'[Invalid {validity[i]:.2f}]' if validity[i] == 1 else f'[ Valid {validity[i]:.2f}]'} {q}") | |
st.metric("Bias Accuracy", f"{bias_accuracy * 100:.1f}%") | |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
project['accuracy_history'][question_type].append((timestamp, bias_accuracy)) | |
# Plot accuracy history | |
if project['accuracy_history']: | |
st.subheader("Accuracy History") | |
timestamps, accuracies = zip(*project['accuracy_history'][question_type]) | |
fig, ax = plt.subplots() | |
ax.plot(timestamps, accuracies, marker='o') | |
ax.set_xlabel("Timestamp") | |
ax.set_ylabel("Overall Relevance (%)") | |
ax.set_title("Relevance Over Time") | |
plt.xticks(rotation=45) | |
st.pyplot(fig) | |
export_data = [] | |
for i, (question, score) in enumerate(zip(question_lines, scores), 1): | |
export_data.append(f"Q{i}. {question}") | |
if (question_type == "DSA"): | |
export_data.append(f"Overall Score: {score['relevance_score']}") | |
export_data.append(f"Best Match: {score['best_match']['title']}") | |
else: | |
export_data.append(f"Overall Score: {score}") | |
export_data.append("") | |
# for i, (question, score) in enumerate(zip(remaining_questions, scores[5:15]), 5): | |
# export_data.append(f"Q{i}. {question}") | |
# export_data.append("") | |
project_control.save_project(project["project_name"], project) | |
st.download_button( | |
"Download Questions with Analysis", | |
f"Job Role: {job_role}\n\n\n" + "\n".join(export_data), | |
file_name=f"{job_role.replace(' ', '_')}_questions_analysis.txt", | |
mime="text/plain" | |
) | |
def configure_page(): | |
st.title("Project Configuration") | |
project = st.session_state['current_project'] | |
assertion_type = st.selectbox("Select Assertion Type", ["deterministic", "factual", "misc"]) | |
if assertion_type == "deterministic": | |
check_type = st.selectbox("Select Deterministic Check Type", ["regex", "json_format", "contains", "not-contains"]) | |
check_value = st.text_area("Enter pattern") | |
if st.button("Add Deterministic Assertion") and check_value: | |
assertion_data = { | |
"check_type": check_type, | |
"value": check_value, | |
} | |
project["assertions"]["deterministic"].append(assertion_data) | |
st.success("Deterministic Assertion added.") | |
elif assertion_type == "factual": | |
fact = st.file_uploader("Provide knowledgebase for factual assertion", type=["pdf", "docx"]) | |
if st.button("Add") and fact: | |
project_id = project["project_name"] | |
file_extension = os.path.splitext(fact.name)[1] | |
# current working dir | |
saved_path = os.path.join(os.getcwd(), DATASET_DIR, f"{project_id}{file_extension}") | |
with open(saved_path, "wb") as f: | |
f.write(fact.getbuffer()) | |
project["assertions"]["knowledgebase"] = saved_path | |
st.success("Factual Assertion added and file saved.") | |
elif assertion_type == "misc": | |
new_assertion = st.text_input("Add Miscellaneous Assertion") | |
if st.button("Add Miscellaneous Assertion") and new_assertion: | |
project["assertions"]["misc"].append(new_assertion) | |
if (st.checkbox('sql-only')): | |
project["assertions"]["sql-only"] = True | |
if (st.checkbox('json-only')): | |
project["assertions"]["json-only"] = True | |
if st.button("Save Assertion"): | |
project_control.save_project(project["project_name"], project) | |
st.success(f"Assertion saved") | |
if st.button("Go Back"): | |
st.session_state.page = 'main' | |
if __name__ == "__main__": | |
main() | |