IliaLarchenko commited on
Commit
3667c7a
1 Parent(s): 4518e15

Huge refactoring

Browse files
Files changed (11) hide show
  1. api/audio.py +62 -0
  2. api/llm.py +88 -0
  3. app.py +30 -50
  4. audio.py +0 -17
  5. config.py +19 -25
  6. docs/instruction.py +29 -0
  7. llm.py +0 -135
  8. prompts.py +0 -37
  9. options.py → resources/data.py +0 -0
  10. resources/prompts.py +34 -0
  11. utils/ui.py +11 -0
api/audio.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import wave
3
+
4
+ import requests
5
+
6
+ from openai import OpenAI
7
+
8
+
9
+ def numpy_audio_to_bytes(audio_data):
10
+ sample_rate = 44100
11
+ num_channels = 1
12
+ sampwidth = 2
13
+
14
+ buffer = io.BytesIO()
15
+ with wave.open(buffer, "wb") as wf:
16
+ wf.setnchannels(num_channels)
17
+ wf.setsampwidth(sampwidth)
18
+ wf.setframerate(sample_rate)
19
+ wf.writeframes(audio_data.tobytes())
20
+ return buffer.getvalue()
21
+
22
+
23
+ class STTManager:
24
+ def __init__(self, config):
25
+ self.config = config
26
+
27
+ def speech_to_text(self, audio, convert_to_bytes=True):
28
+ if convert_to_bytes:
29
+ audio = numpy_audio_to_bytes(audio[1])
30
+
31
+ if self.config.stt.type == "OPENAI_API":
32
+ data = ("temp.wav", audio, "audio/wav")
33
+ client = OpenAI(base_url=self.config.stt.url, api_key=self.config.stt.key)
34
+ transcription = client.audio.transcriptions.create(model=self.config.stt.name, file=data, response_format="text")
35
+ elif self.config.stt.type == "HF_API":
36
+ headers = {"Authorization": "Bearer " + self.config.stt.key}
37
+ transcription = requests.post(self.config.stt.url, headers=headers, data=audio)
38
+ transcription = transcription.json()["text"]
39
+
40
+ return transcription
41
+
42
+
43
+ class TTSManager:
44
+ def __init__(self, config):
45
+ self.config = config
46
+
47
+ def text_to_speech(self, text):
48
+ if self.config.tts.type == "OPENAI_API":
49
+ client = OpenAI(base_url=self.config.tts.url, api_key=self.config.tts.key)
50
+ response = client.audio.speech.create(model=self.config.tts.name, voice="alloy", response_format="opus", input=text)
51
+ elif self.config.tts.type == "HF_API":
52
+ headers = {"Authorization": "Bearer " + self.config.tts.key}
53
+ response = requests.post(self.config.tts.url, headers=headers)
54
+
55
+ return response.content
56
+
57
+ def read_last_message(self, chat_display):
58
+ if chat_display:
59
+ last_message = chat_display[-1][1] # Assuming the message is stored at index 1 of the last tuple/list in chat_display
60
+ if last_message is not None:
61
+ return self.text_to_speech(last_message)
62
+ return None
api/llm.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openai import OpenAI
2
+
3
+
4
+ class LLMManager:
5
+ def __init__(self, config, prompts):
6
+ self.config = config
7
+ self.client = OpenAI(base_url=config.llm.url, api_key=config.llm.key)
8
+ self.prompts = prompts
9
+
10
+ def test_connection(self):
11
+ response = self.client.chat.completions.create(
12
+ model=self.config.llm.name,
13
+ messages=[
14
+ {"role": "system", "content": "You just help me test the connection."},
15
+ {"role": "user", "content": "Hi!"},
16
+ {"role": "user", "content": "Ping!"},
17
+ ],
18
+ )
19
+ return response.choices[0].message.content.strip()
20
+
21
+ def init_bot(self, problem=""):
22
+ chat_history = [
23
+ {"role": "system", "content": self.prompts["coding_interviewer_prompt"]},
24
+ {"role": "system", "content": f"The candidate is solving the following problem: {problem}"},
25
+ ]
26
+ return chat_history
27
+
28
+ def get_problem(self, requirements, difficulty, topic):
29
+ full_prompt = (
30
+ f"Create a {difficulty} {topic} coding problem. "
31
+ f"Additional requirements: {requirements}. "
32
+ "The problem should be clearly stated, well-formatted, and solvable within 30 minutes. "
33
+ "Ensure the problem varies each time to provide a wide range of challenges."
34
+ )
35
+ response = self.client.chat.completions.create(
36
+ model=self.config.llm.name,
37
+ messages=[
38
+ {"role": "system", "content": self.prompts["problem_generation_prompt"]},
39
+ {"role": "user", "content": full_prompt},
40
+ ],
41
+ temperature=1.0,
42
+ )
43
+ question = response.choices[0].message.content.strip()
44
+ chat_history = self.init_bot(question)
45
+ return question, chat_history
46
+
47
+ def send_request(self, code, previous_code, message, chat_history, chat_display):
48
+ # Update chat history if code has changed
49
+ if code != previous_code:
50
+ chat_history.append({"role": "user", "content": f"My latest code:\n{code}"})
51
+ chat_history.append({"role": "user", "content": message})
52
+
53
+ # Process the updated chat history with the language model
54
+ response = self.client.chat.completions.create(model=self.config.llm.name, messages=chat_history)
55
+ reply = response.choices[0].message.content.strip()
56
+ chat_history.append({"role": "assistant", "content": reply})
57
+
58
+ # Update chat display with the new reply
59
+ if chat_display:
60
+ chat_display[-1][1] = reply
61
+ else:
62
+ chat_display.append([message, reply])
63
+
64
+ # Return updated chat history, chat display, an empty string placeholder, and the unchanged code
65
+ return chat_history, chat_display, "", code
66
+
67
+ def end_interview(self, problem_description, chat_history):
68
+ if not chat_history or len(chat_history) <= 2:
69
+ return "No interview content available to review."
70
+
71
+ transcript = []
72
+ for message in chat_history[1:]:
73
+ role = message["role"]
74
+ content = f"{role.capitalize()}: {message['content']}"
75
+ transcript.append(content)
76
+
77
+ response = self.client.chat.completions.create(
78
+ model=self.config.llm.name,
79
+ messages=[
80
+ {"role": "system", "content": self.prompts["grading_feedback_prompt"]},
81
+ {"role": "user", "content": f"The original problem to solve: {problem_description}"},
82
+ {"role": "user", "content": "\n\n".join(transcript)},
83
+ {"role": "user", "content": "Grade the interview based on the transcript provided and give feedback."},
84
+ ],
85
+ temperature=0.5,
86
+ )
87
+ feedback = response.choices[0].message.content.strip()
88
+ return feedback
app.py CHANGED
@@ -2,9 +2,17 @@ import os
2
 
3
  import gradio as gr
4
 
5
- from config import LLM_NAME, STT_NAME, TTS_NAME
6
- from llm import end_interview, get_problem, read_last_message, send_request, speech_to_text, test_connection, text_to_speech
7
- from options import fixed_messages, topics_list
 
 
 
 
 
 
 
 
8
 
9
  default_audio_params = {
10
  "label": "Record answer",
@@ -26,19 +34,6 @@ def hide_settings():
26
  return init_acc, start_btn, solution_acc, end_btn, audio_input
27
 
28
 
29
- def add_interviewer_message(message):
30
- def f(chat):
31
- chat.append((None, message))
32
- return chat
33
-
34
- return f
35
-
36
-
37
- def add_candidate_message(message, chat):
38
- chat.append((message, None))
39
- return chat
40
-
41
-
42
  def hide_solution():
43
  solution_acc = gr.Accordion("Solution", open=False)
44
  end_btn = gr.Button("Finish the interview", interactive=False)
@@ -52,51 +47,36 @@ with gr.Blocks() as demo:
52
  with gr.Row():
53
  with gr.Column(scale=10):
54
  gr.Markdown("# Welcome to the AI Tech Interviewer Training!")
55
- gr.Markdown(
56
- """
57
- This project leverages the latest AI models to simulate a realistic tech interview experience,
58
- allowing you to practice your coding interview skills in an environment that closely mimics the real thing.
59
- While it's not designed to replace a human interviewer or the essential steps of interview preparation, such as studying algorithms and practicing coding,
60
- it serves as a valuable addition to your preparation arsenal.
61
- """
62
- )
63
 
64
  if os.getenv("IS_DEMO"):
65
- gr.Markdown(
66
- """
67
- ### Demo Version Notice
68
- **This is a demo version running on limited resources, which may respond slower than usual.**
69
- It's primarily for demonstration purposes.
70
- For optimal performance, we recommend running this application on your local machine using your own OpenAI API_KEY or local models.
71
- See the instructions below on how to set up and run this application locally for the best experience.
72
- I also recommend to read this introduction page first.
73
- If you proceed to the interview interface right now, just click on the 'Coding' tab.
74
- """
75
- )
76
 
77
  gr.Markdown("### Introduction")
78
  gr.Markdown("### Setting Up Locally")
79
  gr.Markdown("### Interview Interface Overview")
80
  gr.Markdown("### Models Configuration")
 
 
81
 
82
  with gr.Column(scale=1):
83
  try:
84
- audio_test = text_to_speech("Handshake")
85
- gr.Markdown(f"TTS status: 🟢. Model: {TTS_NAME}")
86
  except:
87
- gr.Markdown(f"TTS status: 🔴. Model: {TTS_NAME}")
88
 
89
  try:
90
- text_test = speech_to_text(audio_test, False)
91
- gr.Markdown(f"STT status: 🟢. Model: {STT_NAME}")
92
  except:
93
- gr.Markdown(f"STT status: 🔴. Model: {STT_NAME}")
94
 
95
  try:
96
- test_connection()
97
- gr.Markdown(f"LLM status: 🟢. Model: {LLM_NAME}")
98
  except:
99
- gr.Markdown(f"LLM status: 🔴. Model: {LLM_NAME}")
100
 
101
  with gr.Tab("Coding") as coding_tab:
102
  chat_history = gr.State([])
@@ -148,14 +128,14 @@ with gr.Blocks() as demo:
148
  coding_tab.select(fn=add_interviewer_message(fixed_messages["intro"]), inputs=[chat], outputs=[chat])
149
 
150
  start_btn.click(fn=add_interviewer_message(fixed_messages["start"]), inputs=[chat], outputs=[chat]).then(
151
- fn=get_problem,
152
  inputs=[requirements, difficulty_select, topic_select],
153
  outputs=[description, chat_history],
154
  scroll_to_output=True,
155
  ).then(fn=hide_settings, inputs=None, outputs=[init_acc, start_btn, solution_acc, end_btn, audio_input])
156
 
157
  message.submit(
158
- fn=send_request,
159
  inputs=[code, previous_code, message, chat_history, chat],
160
  outputs=[chat_history, chat, message, previous_code],
161
  )
@@ -165,18 +145,18 @@ with gr.Blocks() as demo:
165
  inputs=[chat],
166
  outputs=[chat],
167
  ).then(
168
- fn=end_interview, inputs=[description, chat_history], outputs=feedback
169
  ).then(fn=hide_solution, inputs=None, outputs=[solution_acc, end_btn, problem_acc, audio_input])
170
 
171
- audio_input.stop_recording(fn=speech_to_text, inputs=[audio_input], outputs=[message]).then(
172
  fn=lambda: None, inputs=None, outputs=[audio_input]
173
  ).then(fn=add_candidate_message, inputs=[message, chat], outputs=[chat]).then(
174
- fn=send_request,
175
  inputs=[code, previous_code, message, chat_history, chat],
176
  outputs=[chat_history, chat, message, previous_code],
177
  )
178
 
179
- chat.change(fn=read_last_message, inputs=[chat], outputs=[audio_output])
180
 
181
  audio_output.stop(fn=lambda: None, inputs=None, outputs=[audio_output])
182
 
 
2
 
3
  import gradio as gr
4
 
5
+ from api.audio import STTManager, TTSManager
6
+ from api.llm import LLMManager
7
+ from config import config
8
+ from docs.instruction import instruction
9
+ from resources.data import fixed_messages, topics_list
10
+ from resources.prompts import prompts
11
+ from utils.ui import add_candidate_message, add_interviewer_message
12
+
13
+ llm = LLMManager(config, prompts)
14
+ tts = TTSManager(config)
15
+ stt = STTManager(config)
16
 
17
  default_audio_params = {
18
  "label": "Record answer",
 
34
  return init_acc, start_btn, solution_acc, end_btn, audio_input
35
 
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  def hide_solution():
38
  solution_acc = gr.Accordion("Solution", open=False)
39
  end_btn = gr.Button("Finish the interview", interactive=False)
 
47
  with gr.Row():
48
  with gr.Column(scale=10):
49
  gr.Markdown("# Welcome to the AI Tech Interviewer Training!")
50
+ gr.Markdown(instruction["intro"])
 
 
 
 
 
 
 
51
 
52
  if os.getenv("IS_DEMO"):
53
+ gr.Markdown(instruction["demo"])
 
 
 
 
 
 
 
 
 
 
54
 
55
  gr.Markdown("### Introduction")
56
  gr.Markdown("### Setting Up Locally")
57
  gr.Markdown("### Interview Interface Overview")
58
  gr.Markdown("### Models Configuration")
59
+ gr.Markdown("### Acknowledgement")
60
+ gr.Markdown(instruction["acknowledgements"])
61
 
62
  with gr.Column(scale=1):
63
  try:
64
+ audio_test = tts.text_to_speech("Handshake")
65
+ gr.Markdown(f"TTS status: 🟢. Model: {config.tts.name}")
66
  except:
67
+ gr.Markdown(f"TTS status: 🔴. Model: {config.tts.name}")
68
 
69
  try:
70
+ text_test = stt.speech_to_text(audio_test, False)
71
+ gr.Markdown(f"STT status: 🟢. Model: {config.stt.name}")
72
  except:
73
+ gr.Markdown(f"STT status: 🔴. Model: {config.stt.name}")
74
 
75
  try:
76
+ llm.test_connection()
77
+ gr.Markdown(f"LLM status: 🟢. Model: {config.llm.name}")
78
  except:
79
+ gr.Markdown(f"LLM status: 🔴. Model: {config.llm.name}")
80
 
81
  with gr.Tab("Coding") as coding_tab:
82
  chat_history = gr.State([])
 
128
  coding_tab.select(fn=add_interviewer_message(fixed_messages["intro"]), inputs=[chat], outputs=[chat])
129
 
130
  start_btn.click(fn=add_interviewer_message(fixed_messages["start"]), inputs=[chat], outputs=[chat]).then(
131
+ fn=llm.get_problem,
132
  inputs=[requirements, difficulty_select, topic_select],
133
  outputs=[description, chat_history],
134
  scroll_to_output=True,
135
  ).then(fn=hide_settings, inputs=None, outputs=[init_acc, start_btn, solution_acc, end_btn, audio_input])
136
 
137
  message.submit(
138
+ fn=llm.send_request,
139
  inputs=[code, previous_code, message, chat_history, chat],
140
  outputs=[chat_history, chat, message, previous_code],
141
  )
 
145
  inputs=[chat],
146
  outputs=[chat],
147
  ).then(
148
+ fn=llm.end_interview, inputs=[description, chat_history], outputs=feedback
149
  ).then(fn=hide_solution, inputs=None, outputs=[solution_acc, end_btn, problem_acc, audio_input])
150
 
151
+ audio_input.stop_recording(fn=stt.speech_to_text, inputs=[audio_input], outputs=[message]).then(
152
  fn=lambda: None, inputs=None, outputs=[audio_input]
153
  ).then(fn=add_candidate_message, inputs=[message, chat], outputs=[chat]).then(
154
+ fn=llm.send_request,
155
  inputs=[code, previous_code, message, chat_history, chat],
156
  outputs=[chat_history, chat, message, previous_code],
157
  )
158
 
159
+ chat.change(fn=tts.read_last_message, inputs=[chat], outputs=[audio_output])
160
 
161
  audio_output.stop(fn=lambda: None, inputs=None, outputs=[audio_output])
162
 
audio.py DELETED
@@ -1,17 +0,0 @@
1
- import io
2
- import wave
3
-
4
-
5
- def numpy_audio_to_bytes(audio_data):
6
- sample_rate = 44100
7
- num_channels = 1
8
- sampwidth = 2
9
-
10
- buffer = io.BytesIO()
11
- with wave.open(buffer, "wb") as wf:
12
- wf.setnchannels(num_channels)
13
- wf.setsampwidth(sampwidth)
14
- wf.setframerate(sample_rate)
15
- wf.writeframes(audio_data.tobytes())
16
-
17
- return buffer.getvalue()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.py CHANGED
@@ -1,28 +1,22 @@
1
- # X_URL - the URL for the model endpoint, can be None if using OpenAI API
2
- # X_TYPE - the type of the model, can be "OPENAI_API" or "HF_API"
3
- # there should be an environment variable with the f"{}_KEY" name and the key as the value to authenticate the API
4
- # X_NAME - the name of the model, used only for OpenAI API
5
 
6
- LLM_URL = None
7
- LLM_TYPE = "OPENAI_API"
8
- LLM_NAME = "gpt-3.5-turbo"
9
- # "gpt-3.5-turbo" - ~3 seconds delay with decent quality
10
- # "gpt-4-turbo","gpt-4", etc. 10+ seconds delay but higher quality
11
- # For HuggingFace models, the Messages API is used, it if compatible with Open AI API
12
- # Don't forget to add "/v1" to the end of the URL for HuggingFace LLM models
13
- # https://huggingface.co/docs/text-generation-inference/en/messages_api
14
 
15
- STT_URL = "https://api-inference.huggingface.co/models/openai/whisper-tiny.en"
16
- STT_TYPE = "HF_API"
17
- STT_NAME = "whisper-1"
18
- # "whisper-1" is the only OpenAI STT model available for OpenAI API
19
- # The whisper family with more models is available on HuggingFace:
20
- # https://huggingface.co/collections/openai/whisper-release-6501bba2cf999715fd953013
21
- # you can also use any other compatible model from HuggingFace
22
 
23
- TTS_URL = None
24
- TTS_TYPE = "OPENAI_API"
25
- TTS_NAME = "tts-1"
26
- # OpenAI "tts-1" - very good quality and close to real-time response
27
- # OpenAI "tts-1-hd" - slightly better quality with slightly longer response time (no obvious benefits in this case)
28
- # I think OS models on HuggingFace have much more artificial voices, but you can try them out
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
 
 
 
2
 
3
+ from dotenv import load_dotenv
 
 
 
 
 
 
 
4
 
 
 
 
 
 
 
 
5
 
6
+ class ServiceConfig:
7
+ def __init__(self, url_var, type_var, name_var):
8
+ self.url = os.getenv(url_var)
9
+ self.type = os.getenv(type_var)
10
+ self.name = os.getenv(name_var)
11
+ self.key = os.getenv(f"{self.type}_KEY")
12
+
13
+
14
+ class Config:
15
+ def __init__(self):
16
+ load_dotenv()
17
+ self.llm = ServiceConfig("LLM_URL", "LLM_TYPE", "LLM_NAME")
18
+ self.stt = ServiceConfig("STT_URL", "STT_TYPE", "STT_NAME")
19
+ self.tts = ServiceConfig("TTS_URL", "TTS_TYPE", "TTS_NAME")
20
+
21
+
22
+ config = Config()
docs/instruction.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # I will change it into proper format later
2
+
3
+ instruction = {
4
+ "intro": """
5
+ This project leverages the latest AI models to simulate a realistic tech interview experience,
6
+ allowing you to practice your coding interview skills in an environment that closely mimics the real thing.
7
+ While it's not designed to replace a human interviewer or the essential steps of interview preparation, such as studying algorithms and practicing coding,
8
+ it serves as a valuable addition to your preparation arsenal.
9
+ """,
10
+ "demo": """
11
+ ### Demo Version Notice
12
+ **This is a demo version running on limited resources, which may respond slower than usual.**
13
+ It's primarily for demonstration purposes.
14
+ For optimal performance, we recommend running this application on your local machine using your own OpenAI API_KEY or local models.
15
+ See the instructions below on how to set up and run this application locally for the best experience.
16
+ I also recommend to read this introduction page first.
17
+ If you proceed to the interview interface right now, just click on the 'Coding' tab.
18
+ """,
19
+ "acknowledgements": """
20
+ The library can be used with a wide variety of models and APIs depending on configuration.
21
+ But I would like to acknowledge the following models in particular:
22
+ * OpenAI: GPT-3.5, GPT-4, Whisper, TTS-1, etc.
23
+ * Meta: Llama family, especially Meta-Llama-3-70B-Instruct and Meta-Llama-3-8B-Instruct.
24
+ * HuggingFace: for providing a wide range of models and APIs that can be used with this library.
25
+
26
+ Please, make sure to check the documentation of the models and APIs you are using to understand their capabilities and limitations.
27
+ Also, make sure to comply with the terms of service and acceptable use policies of the models and APIs you are using.
28
+ """,
29
+ }
llm.py DELETED
@@ -1,135 +0,0 @@
1
- import json
2
- import os
3
-
4
- import requests
5
-
6
- from dotenv import load_dotenv
7
- from openai import OpenAI
8
-
9
- from audio import numpy_audio_to_bytes
10
- from config import LLM_NAME, LLM_TYPE, LLM_URL, STT_NAME, STT_TYPE, STT_URL, TTS_NAME, TTS_TYPE, TTS_URL
11
- from prompts import coding_interviewer_prompt, grading_feedback_prompt, problem_generation_prompt
12
-
13
- load_dotenv()
14
-
15
- client_LLM = OpenAI(base_url=LLM_URL, api_key=os.getenv(f"{LLM_TYPE}_KEY"))
16
-
17
-
18
- def test_connection():
19
- response = client_LLM.chat.completions.create(
20
- model=LLM_NAME,
21
- messages=[
22
- {"role": "system", "content": "You just help me test the connection."},
23
- {"role": "user", "content": "Hi!"},
24
- {"role": "user", "content": "Ping!"},
25
- ],
26
- )
27
- return response.choices[0].message.content.strip()
28
-
29
-
30
- def init_bot(problem=""):
31
- chat_history = [
32
- {"role": "system", "content": coding_interviewer_prompt},
33
- {"role": "system", "content": f"The candidate is solving the following problem: {problem}"},
34
- ]
35
- return chat_history
36
-
37
-
38
- def get_problem(requirements, difficulty, topic, client=client_LLM):
39
- full_prompt = (
40
- f"Create a {difficulty} {topic} coding problem. "
41
- f"Additional requirements: {requirements}. "
42
- "The problem should be clearly stated, well-formatted, and solvable within 30 minutes. "
43
- "Ensure the problem varies each time to provide a wide range of challenges."
44
- )
45
- response = client.chat.completions.create(
46
- model=LLM_NAME,
47
- messages=[
48
- {"role": "system", "content": problem_generation_prompt},
49
- {"role": "user", "content": full_prompt},
50
- ],
51
- temperature=1.0,
52
- )
53
- question = response.choices[0].message.content.strip()
54
- chat_history = init_bot(question)
55
- return question, chat_history
56
-
57
-
58
- def end_interview(problem_description, chat_history, client=client_LLM):
59
- if not chat_history or len(chat_history) <= 2:
60
- return "No interview content available to review."
61
-
62
- transcript = []
63
- for message in chat_history[1:]:
64
- role = message["role"]
65
- content = f"{role.capitalize()}: {message['content']}"
66
- transcript.append(content)
67
-
68
- response = client.chat.completions.create(
69
- model=LLM_NAME,
70
- messages=[
71
- {"role": "system", "content": grading_feedback_prompt},
72
- {"role": "user", "content": f"The original problem to solve: {problem_description}"},
73
- {"role": "user", "content": "\n\n".join(transcript)},
74
- {"role": "user", "content": "Grade the interview based on the transcript provided and give feedback."},
75
- ],
76
- temperature=0.5,
77
- )
78
- feedback = response.choices[0].message.content.strip()
79
- return feedback
80
-
81
-
82
- def send_request(code, previous_code, message, chat_history, chat_display, client=client_LLM):
83
- if code != previous_code:
84
- chat_history.append({"role": "user", "content": f"My latest code:\n{code}"})
85
- chat_history.append({"role": "user", "content": message})
86
-
87
- response = client.chat.completions.create(model=LLM_NAME, messages=chat_history)
88
-
89
- reply = response.choices[0].message.content.strip()
90
-
91
- chat_history.append({"role": "assistant", "content": reply})
92
- chat_display[-1][1] = reply
93
-
94
- return chat_history, chat_display, "", code
95
-
96
-
97
- def speech_to_text(audio, convert_to_bytes=True):
98
- assert STT_TYPE in ["OPENAI_API", "HF_API"]
99
-
100
- if convert_to_bytes:
101
- audio = numpy_audio_to_bytes(audio[1])
102
-
103
- if STT_TYPE == "OPENAI_API":
104
- data = ("temp.wav", audio, "audio/wav")
105
- client = OpenAI(base_url=STT_URL, api_key=os.getenv(f"{STT_TYPE}_KEY"))
106
- transcription = client.audio.transcriptions.create(model=STT_NAME, file=data, response_format="text")
107
- elif STT_TYPE == "HF_API":
108
- headers = {"Authorization": "Bearer " + os.getenv(f"{STT_TYPE}_KEY")}
109
- transcription = requests.post(STT_URL, headers=headers, data=audio)
110
- transcription = transcription.json()["text"]
111
-
112
- return transcription
113
-
114
-
115
- def text_to_speech(text):
116
- assert TTS_TYPE in ["OPENAI_API", "HF_API"]
117
-
118
- if TTS_TYPE == "OPENAI_API":
119
- client = OpenAI(base_url=TTS_URL, api_key=os.getenv(f"{TTS_TYPE}_KEY"))
120
- response = client.audio.speech.create(model=TTS_NAME, voice="alloy", response_format="opus", input=text)
121
- elif TTS_TYPE == "HF_API":
122
- headers = {"Authorization": "Bearer " + os.getenv(f"{STT_TYPE}_KEY")}
123
- response = requests.post(TTS_URL, headers=headers)
124
-
125
- audio = response.content
126
- return audio
127
-
128
-
129
- def read_last_message(chat_display):
130
- if len(chat_display) > 0:
131
- last_message = chat_display[-1][1]
132
- if last_message is not None:
133
- audio = text_to_speech(last_message)
134
- return audio
135
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
prompts.py DELETED
@@ -1,37 +0,0 @@
1
- problem_generation_prompt = (
2
- "You are AI acting as a coding round interviewer for a big-tech company. "
3
- "Generate a problem that tests the candidate's ability to solve real-world coding challenges efficiently. "
4
- "Ensure the problem tests for problem-solving skills, technical proficiency, code quality, and handling of edge cases. "
5
- )
6
-
7
- # Coding round interviewer instructions
8
- coding_interviewer_prompt = (
9
- "As an AI acting as a coding interviewer for a major tech company, you are to maintain a professional and analytical demeanor. "
10
- "You must consistently ask about the time and space complexity of the candidate's solutions after each significant problem-solving step. "
11
- "Prompt the candidate to explain how they compute these complexities, and guide them through the process if necessary, without providing the answers directly. "
12
- "Encourage thorough exploration of solutions without revealing answers directly. Provide hints subtly only after observing the candidate struggle significantly or upon explicit request. "
13
- "Probe the candidate with questions related to problem-solving approaches, algorithm choices, handling of edge cases, and error identification to assess technical proficiency comprehensively. "
14
- "If the candidate deviates from the problem, gently guide them back to focus on the task at hand. "
15
- "After multiple unsuccessful attempts by the candidate to identify or fix an error, provide more direct hints or rephrase the problem slightly to aid understanding. "
16
- "Encourage the candidate to think about real-world applications and scalability of their solutions, asking how changes to the problem parameters might affect their approach. "
17
- )
18
-
19
-
20
- # Prompt for grading feedback
21
- grading_feedback_prompt = (
22
- "You are the AI grader for a coding interview at a major tech firm. "
23
- "The following is the interview transcript with the candidate's responses. "
24
- "Ignore minor transcription errors unless they impact comprehension. "
25
- "If there are no real solution provide just say it. "
26
- "Evaluate the candidate’s performance based on the following criteria: "
27
- "\n- **Problem-Solving Skills**: Approach to solving problems, creativity, and handling of complex issues."
28
- "\n- **Technical Proficiency**: Accuracy of the solution, usage of appropriate algorithms and data structures, consideration of edge cases, and error handling."
29
- "\n- **Code Quality**: Readability, maintainability, scalability, and overall organization."
30
- "\n- **Communication Skills**: Ability to explain their thought process clearly, interaction during the interview, and responsiveness to feedback."
31
- "\n- **Debugging Skills**: Efficiency in identifying and resolving errors."
32
- "\n- **Adaptability**: Ability to incorporate feedback and adjust solutions as needed."
33
- "\n- **Handling Ambiguity**: Approach to dealing with uncertain or incomplete requirements."
34
- "\nProvide comprehensive feedback, detailing overall performance, specific errors, areas for improvement, communication lapses, overlooked edge cases, and any other relevant observations. "
35
- "Use code examples to illustrate points where necessary. Your feedback should be critical, aiming to fail candidates who do not meet high standards while providing detailed improvement areas. "
36
- "Format all feedback in clear, structured markdown for readability."
37
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
options.py → resources/data.py RENAMED
File without changes
resources/prompts.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ prompts = {
2
+ "problem_generation_prompt": (
3
+ "You are AI acting as a coding round interviewer for a big-tech company. "
4
+ "Generate a problem that tests the candidate's ability to solve real-world coding challenges efficiently. "
5
+ "Ensure the problem tests for problem-solving skills, technical proficiency, code quality, and handling of edge cases. "
6
+ ),
7
+ "coding_interviewer_prompt": (
8
+ "As an AI acting as a coding interviewer for a major tech company, you are to maintain a professional and analytical demeanor. "
9
+ "You must consistently ask about the time and space complexity of the candidate's solutions after each significant problem-solving step. "
10
+ "Prompt the candidate to explain how they compute these complexities, and guide them through the process if necessary, without providing the answers directly. "
11
+ "Encourage thorough exploration of solutions without revealing answers directly. Provide hints subtly only after observing the candidate struggle significantly or upon explicit request. "
12
+ "Probe the candidate with questions related to problem-solving approaches, algorithm choices, handling of edge cases, and error identification to assess technical proficiency comprehensively. "
13
+ "If the candidate deviates from the problem, gently guide them back to focus on the task at hand. "
14
+ "After multiple unsuccessful attempts by the candidate to identify or fix an error, provide more direct hints or rephrase the problem slightly to aid understanding. "
15
+ "Encourage the candidate to think about real-world applications and scalability of their solutions, asking how changes to the problem parameters might affect their approach. "
16
+ ),
17
+ "grading_feedback_prompt": (
18
+ "You are the AI grader for a coding interview at a major tech firm. "
19
+ "The following is the interview transcript with the candidate's responses. "
20
+ "Ignore minor transcription errors unless they impact comprehension. "
21
+ "If there are no real solution provide just say it. "
22
+ "Evaluate the candidate’s performance based on the following criteria: "
23
+ "\n- **Problem-Solving Skills**: Approach to solving problems, creativity, and handling of complex issues."
24
+ "\n- **Technical Proficiency**: Accuracy of the solution, usage of appropriate algorithms and data structures, consideration of edge cases, and error handling."
25
+ "\n- **Code Quality**: Readability, maintainability, scalability, and overall organization."
26
+ "\n- **Communication Skills**: Ability to explain their thought process clearly, interaction during the interview, and responsiveness to feedback."
27
+ "\n- **Debugging Skills**: Efficiency in identifying and resolving errors."
28
+ "\n- **Adaptability**: Ability to incorporate feedback and adjust solutions as needed."
29
+ "\n- **Handling Ambiguity**: Approach to dealing with uncertain or incomplete requirements."
30
+ "\nProvide comprehensive feedback, detailing overall performance, specific errors, areas for improvement, communication lapses, overlooked edge cases, and any other relevant observations. "
31
+ "Use code examples to illustrate points where necessary. Your feedback should be critical, aiming to fail candidates who do not meet high standards while providing detailed improvement areas. "
32
+ "Format all feedback in clear, structured markdown for readability."
33
+ ),
34
+ }
utils/ui.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def add_interviewer_message(message):
2
+ def f(chat):
3
+ chat.append((None, message))
4
+ return chat
5
+
6
+ return f
7
+
8
+
9
+ def add_candidate_message(message, chat):
10
+ chat.append((message, None))
11
+ return chat