Spaces:
Sleeping
Sleeping
File size: 7,179 Bytes
fb03edc e12b285 fb03edc c756257 fb03edc 324d83a da72dc0 fb03edc e12b285 3d8833c e12b285 9f4cedf e12b285 9f4cedf e12b285 9f4cedf e12b285 f02aeda 5d590b7 fb03edc e12b285 fb03edc 3b598e6 fb03edc 9f4cedf 8e8067f 9f4cedf 8e8067f 9f4cedf 8e8067f 9f4cedf 8e8067f 9f4cedf 8e8067f b47e010 1d5b387 3b598e6 1d5b387 9f4cedf 8e8067f fb03edc 8e8067f fb03edc 3b598e6 9f4cedf fb03edc a5bc3b5 ff7e723 a5bc3b5 ff7e723 fb03edc 437e3cd 3b598e6 9f4cedf 3b598e6 9f4cedf fb03edc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
import json
import os
import random
import string
import time
from collections import defaultdict
from typing import Dict, Optional, Tuple
from openai import OpenAI
from api.llm import LLMManager
from utils.config import Config
from resources.data import fixed_messages, topic_lists
from resources.prompts import prompts
from tests.testing_prompts import candidate_prompt
from ui.coding import send_request
def complete_interview(
interview_type: str,
exp_name: str,
llm_config: Optional[Config] = None,
requirements: str = "",
difficulty: str = "",
topic: str = "",
model: str = "gpt-4o-mini",
pause: int = 0,
mode: str = "normal",
max_messages: Optional[int] = None,
) -> Tuple[str, Dict]:
"""
Complete an interview and record the results with additional strange use cases.
:param interview_type: Type of interview to complete.
:param exp_name: Experiment name for file saving.
:param llm_config: Optional LLM configuration.
:param requirements: Additional requirements for the interview.
:param difficulty: Difficulty level for the interview.
:param topic: Topic for the interview.
:param model: Model to use for the candidate.
:param pause: Pause duration between requests to prevent rate limits.
:param mode: Mode of operation ("normal", "empty", "gibberish", "repeat").
:param max_messages: Maximum number of messages in the conversation.
:return: Tuple containing the file path and interview data.
"""
client = OpenAI(base_url="https://api.openai.com/v1")
config = Config()
if llm_config:
config.llm = llm_config
llm = LLMManager(config, prompts)
llm_name = config.llm.name
print(f"Starting evaluation interviewer LLM: {llm_name}, candidate LLM: {model}, interview type: {interview_type}")
# Select a random topic or difficulty if not provided
topic = topic or random.choice(topic_lists[interview_type])
difficulty = difficulty or random.choice(["easy", "medium", "hard"])
# Fix: Iterate over all elements and keep the last one
problem_statement_text = None
for text in llm.get_problem(requirements, difficulty, topic, interview_type):
problem_statement_text = text
if problem_statement_text is None:
raise ValueError("Failed to get problem statement")
interview_data = defaultdict(
lambda: None,
{
"interviewer_llm": llm_name,
"candidate_llm": model,
"inputs": {
"interview_type": interview_type,
"difficulty": difficulty,
"topic": topic,
"requirements": requirements,
},
"problem_statement": problem_statement_text,
"transcript": [],
"feedback": None,
"average_response_time_seconds": 0,
},
)
# Initialize interviewer and candidate messages
messages_interviewer = llm.init_bot(problem_statement_text, interview_type)
chat_display = [[None, fixed_messages["start"]]]
messages_candidate = [
{"role": "system", "content": candidate_prompt},
{"role": "user", "content": f"Your problem: {problem_statement_text}"},
{"role": "user", "content": chat_display[-1][1]},
]
response_times = []
previous_code = ""
if max_messages is None:
max_messages = 25 if mode == "normal" else 5
for _ in range(max_messages):
code = ""
if mode == "empty":
candidate_message = ""
elif mode == "gibberish":
candidate_message = "".join(random.choices(string.ascii_letters + string.digits, k=50))
elif mode == "repeat":
candidate_message = chat_display[-1][1]
else:
try:
response = client.chat.completions.create(
model=model,
messages=messages_candidate,
temperature=1,
response_format={"type": "json_object"},
timeout=30, # Add a timeout to prevent indefinite waiting
)
try:
response_json = json.loads(response.choices[0].message.content)
candidate_message = response_json.get("message", "")
code = response_json.get("code_and_notes", "")
finished = response_json.get("finished", False)
question = response_json.get("question", False)
if finished and not question and not code:
break
except:
continue
except Exception as e:
print(f"Error in API call: {str(e)}, skipping this iteration")
continue
if not candidate_message and not code and mode != "empty":
print("No message or code in response")
continue
if candidate_message:
messages_candidate.append({"role": "assistant", "content": candidate_message})
interview_data["transcript"].append(f"CANDIDATE MESSAGE: {candidate_message}")
if code:
interview_data["transcript"].append(f"CANDIDATE CODE AND NOTES: {code}")
messages_candidate.append({"role": "assistant", "content": code})
chat_display.append([candidate_message, None])
send_time = time.time()
# Fix: Iterate over all elements and keep the last one
last_result = None
for result in send_request(code, previous_code, messages_interviewer, chat_display, llm, tts=None, silent=True):
last_result = result
if last_result is not None:
messages_interviewer, chat_display, previous_code, _ = last_result
else:
print("send_request did not return any results, skipping this iteration")
continue
response_times.append(time.time() - send_time)
messages_candidate.append({"role": "user", "content": chat_display[-1][1]})
message_split = messages_interviewer[-1]["content"].split("#NOTES#")
interview_data["transcript"].append(f"INTERVIEWER MESSAGE: {message_split[0]}")
if len(message_split) > 1:
interview_data["transcript"].append(f"INTERVIEWER HIDDEN NOTE: {message_split[1]}")
time.sleep(pause) # to prevent exceeding rate limits
# Fix: Iterate over all elements and keep the last one
feedback = None
for fb in llm.end_interview(problem_statement_text, messages_interviewer, interview_type):
feedback = fb
interview_data["feedback"] = feedback
interview_data["average_response_time_seconds"] = round(sum(response_times) / len(response_times), 2) if response_times else 0
current_time = time.strftime("%Y%m%d-%H%M%S")
random_suffix = "".join(random.choices(string.ascii_letters + string.digits, k=10))
file_path = os.path.join("records", exp_name, f"{current_time}-{random_suffix}.json")
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, "w") as file:
json.dump(interview_data, file, indent=4)
return file_path, interview_data
|