nsgupta1's picture
Update app.py
5a8dfb7 verified
Raw History Blame Contribute Delete
10.9 kB
import streamlit as st
from openai import OpenAI
import os
import pandas as pd
import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import torch
import re
# Set up OpenAI client
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Check if GPU is available
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")
# Load metadata and embeddings (ensure these files are in your working directory or update paths)
metadata_path = 'question_metadata.csv' # Update this path if needed
embeddings_path = 'question_dataset_embeddings.npy' # Update this path if needed
metadata = pd.read_csv(metadata_path)
embeddings = np.load(embeddings_path)
# Load the SentenceTransformer model
model = SentenceTransformer("all-MiniLM-L6-v2").to(device)
# Load prompts from files
with open("technical_interviewer_prompt.txt", "r") as file:
technical_interviewer_prompt = file.read()
with open("question_generation_prompt.txt", "r") as file:
question_generation_prompt = file.read()
st.title("Mock Interview: Real-World Programming")
# Initialize session state variables
if "messages" not in st.session_state:
st.session_state.messages = []
if "follow_up_mode" not in st.session_state:
st.session_state.follow_up_mode = False # Tracks whether we're in follow-up mode
if "generated_question" not in st.session_state:
st.session_state.generated_question = None # Stores the generated question for persistence
if "code_template" not in st.session_state:
st.session_state.code_template = "" # Stores the code template
if "sample_test_case" not in st.session_state:
st.session_state.sample_test_case = "" # Stores the sample test case
if "expected_output" not in st.session_state:
st.session_state.expected_output = "" # Stores the expected output
if "debug_logs" not in st.session_state:
st.session_state.debug_logs = None # Stores debug logs for toggling
# Function to find the top 1 most similar question based on user input
def find_top_question(query):
# Generate embedding for the query
query_embedding = model.encode(query, convert_to_tensor=True, device=device).cpu().numpy()
# Reshape query_embedding to ensure it is a 2D array
query_embedding = query_embedding.reshape(1, -1) # Reshape to (1, n_features)
# Compute cosine similarity between query embedding and dataset embeddings
similarities = cosine_similarity(query_embedding, embeddings).flatten() # Flatten to get a 1D array of similarities
# Get the index of the most similar result (top 1)
top_index = similarities.argsort()[-1] # Index of highest similarity
# Retrieve metadata for the top result
top_result = metadata.iloc[top_index].copy()
top_result['similarity_score'] = similarities[top_index]
return top_result
# Function to generate response using OpenAI API with debugging logs
def generate_response(messages):
# For debug logs, store only the follow-up conversation history
st.session_state.debug_logs = st.session_state.messages # Update debug logs with current conversation
response = client.chat.completions.create(
model="o1-mini",
messages=messages,
)
return response.choices[0].message.content
# Function to extract code template and sample test case from the generated question
def extract_code_and_test_case(generated_question):
code_template = ""
sample_test_case = ""
expected_output = ""
# Extract code template
code_match = re.search(r'```python(.*?)```', generated_question, re.DOTALL)
if code_match:
code_template = code_match.group(1).strip()
else:
# Default code template if none is found
code_template = "# Write your code here\n"
# Extract sample test case and expected output
test_case_match = re.search(r'Sample Input:\s*(.*?)\n', generated_question, re.DOTALL)
expected_output_match = re.search(r'Expected Output:\s*(.*?)\n', generated_question, re.DOTALL)
if test_case_match and expected_output_match:
sample_test_case = test_case_match.group(1).strip()
expected_output = expected_output_match.group(1).strip()
else:
sample_test_case = ""
expected_output = ""
return code_template, sample_test_case, expected_output
# Move the input form to the sidebar to make it always visible and more compact
with st.sidebar.form(key="input_form"):
st.markdown("## Generate a New Question")
company = st.text_input("Company", value="Google") # Default value: Google
difficulty = st.selectbox("Difficulty", ["Easy", "Medium", "Hard"], index=1) # Default: Medium
topic = st.text_input("Topic", value="Binary Search") # Default: Binary Search
generate_button = st.form_submit_button(label="Generate")
if generate_button:
# Clear session state and start fresh with follow-up mode disabled
st.session_state.messages = []
st.session_state.follow_up_mode = False
# Create a query from user inputs and find the most relevant question
query = f"{company} {difficulty} {topic}"
top_question = find_top_question(query)
# Prepare a detailed prompt for GPT using the top question's details
detailed_prompt = (
f"Transform this LeetCode question into a real-world interview scenario.\n\n"
f"**Company**: {top_question['company']}\n"
f"**Question Name**: {top_question['questionName']}\n"
f"**Difficulty Level**: {top_question['difficulty level']}\n"
f"**Tags**: {top_question['Tags']}\n"
f"**Content**: {top_question['Content']}\n"
f"\nPlease create a real-world interview question based on this information. "
f"Include the following sections:\n\n"
f"- Problem Description\n"
f"- Code Template (in a Python code block)\n"
f"- Sample Input and Expected Output (clearly separated)\n"
)
# Generate response using OpenAI API with detailed prompt and debugging logs
response = generate_response([{"role": "user", "content": detailed_prompt}]) # Question generation prompt excluded here
# Store generated question in session state for persistence in sidebar and follow-up conversation state
st.session_state.generated_question = response
# Extract code template and sample test case
code_template, sample_test_case, expected_output = extract_code_and_test_case(response)
st.session_state.code_template = code_template
st.session_state.sample_test_case = sample_test_case
st.session_state.expected_output = expected_output
# Enable follow-up mode after generating the initial question
st.session_state.follow_up_mode = True
# Display chat messages from history on app rerun (for subsequent conversation)
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# Chatbox for subsequent conversations with assistant (follow-up mode)
if st.session_state.follow_up_mode:
if user_input := st.chat_input("Continue your conversation or ask follow-up questions here:"):
# Display user message in chat message container and add to session history
with st.chat_message("user"):
st.markdown(user_input)
st.session_state.messages.append({"role": "user", "content": user_input})
# Prepare messages to send to the assistant
# Include the technical interviewer prompt and generated question, but do not display them
# Add an instruction for the assistant to reply as a real-world interviewer would
assistant_instruction = (
"As a real-world interviewer, please reply to the candidate's follow-up questions "
"specific to the generated interview question, to the point, and in a natural, human-sounding way."
)
messages_to_send = [
{"role": "user", "content": technical_interviewer_prompt},
{"role": "assistant", "content": st.session_state.generated_question},
{"role": "user", "content": assistant_instruction}
] + st.session_state.messages
assistant_response = generate_response(messages_to_send)
with st.chat_message("assistant"):
st.markdown(assistant_response)
st.session_state.messages.append({"role": "assistant", "content": assistant_response})
st.sidebar.markdown("---")
st.sidebar.markdown("## Generated Question")
if st.session_state.generated_question:
st.sidebar.markdown(st.session_state.generated_question)
else:
st.sidebar.markdown("_No question generated yet._")
st.sidebar.markdown("---")
st.sidebar.markdown("## Python Code Interpreter")
# Pre-fill code interpreter with code template after question generation
if st.session_state.code_template:
code_input = st.sidebar.text_area("Write your Python code here:", value=st.session_state.code_template, height=300)
else:
code_input = st.sidebar.text_area("Write your Python code here:", height=300)
if st.sidebar.button("Run Code"):
try:
# Prepare the code for execution
exec_globals = {}
# Create a function wrapper to execute the user's code
exec(f"def user_solution():\n{code_input}", exec_globals)
user_solution = exec_globals.get('user_solution', None)
# Prepare sample test case execution
if st.session_state.sample_test_case:
# Assume the sample test case is in the format of arguments to the function
test_case = st.session_state.sample_test_case
# Evaluate the test case safely
test_args = eval(test_case)
if not isinstance(test_args, tuple):
test_args = (test_args,)
# Capture the output
returned_output = user_solution(*test_args)
else:
returned_output = user_solution()
# Display the expected output and returned output
st.sidebar.markdown("### Sample Test Case Result:")
st.sidebar.markdown(f"**Sample Input:** {st.session_state.sample_test_case}")
st.sidebar.markdown(f"**Expected Output:** {st.session_state.expected_output}")
st.sidebar.markdown(f"**Your Output:** {returned_output}")
# Compare outputs
if str(returned_output) == st.session_state.expected_output:
st.sidebar.success("Your output matches the expected output!")
else:
st.sidebar.error("Your output does not match the expected output.")
except Exception as e:
st.sidebar.error(f"Error: {e}")
# Right sidebar toggleable debug logs and code interpreter section
with st.expander("Debug Logs (Toggle On/Off)", expanded=False):
if st.session_state.debug_logs:
st.write(st.session_state.debug_logs)