Spaces:
Sleeping
Sleeping
IliaLarchenko
commited on
Commit
•
c62e737
1
Parent(s):
fb73ff7
Added support of the HuggingFace models
Browse files- config.py +21 -11
- llm.py +36 -26
- prompts.py +0 -4
config.py
CHANGED
@@ -1,18 +1,28 @@
|
|
1 |
-
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
3 |
LLM_NAME = "gpt-3.5-turbo"
|
4 |
# "gpt-3.5-turbo" - ~3 seconds delay with decent quality
|
5 |
# "gpt-4-turbo","gpt-4", etc. 10+ seconds delay but higher quality
|
|
|
|
|
|
|
6 |
|
7 |
-
STT_URL =
|
8 |
-
|
9 |
STT_NAME = "whisper-1"
|
10 |
-
# "whisper-1"
|
11 |
-
|
|
|
|
|
12 |
|
13 |
-
TTS_URL =
|
14 |
-
|
15 |
TTS_NAME = "tts-1"
|
16 |
-
#
|
17 |
-
# "tts-1" -
|
18 |
-
#
|
|
|
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
|
llm.py
CHANGED
@@ -1,19 +1,18 @@
|
|
1 |
import json
|
2 |
import os
|
3 |
|
|
|
|
|
4 |
from dotenv import load_dotenv
|
5 |
from openai import OpenAI
|
6 |
|
7 |
from audio import numpy_audio_to_bytes
|
8 |
-
from config import
|
9 |
from prompts import coding_interviewer_prompt, grading_feedback_prompt, problem_generation_prompt
|
10 |
|
11 |
load_dotenv()
|
12 |
|
13 |
-
client_LLM = OpenAI(base_url=LLM_URL, api_key=os.getenv(
|
14 |
-
print(client_LLM.base_url)
|
15 |
-
client_STT = OpenAI(base_url=STT_URL, api_key=os.getenv(STT_KEY_TYPE))
|
16 |
-
client_TTS = OpenAI(base_url=TTS_URL, api_key=os.getenv(TTS_KEY_TYPE))
|
17 |
|
18 |
|
19 |
def init_bot(problem=""):
|
@@ -73,37 +72,48 @@ def send_request(code, previous_code, message, chat_history, chat_display, clien
|
|
73 |
chat_history.append({"role": "user", "content": f"My latest code:\n{code}"})
|
74 |
chat_history.append({"role": "user", "content": message})
|
75 |
|
76 |
-
response = client.chat.completions.create(model=LLM_NAME,
|
77 |
-
|
78 |
-
json_reply = response.choices[0].message.content.strip()
|
79 |
|
80 |
-
|
81 |
-
data = json.loads(json_reply)
|
82 |
-
reply = data["reply_to_candidate"]
|
83 |
-
except json.JSONDecodeError as e:
|
84 |
-
print("Failed to decode JSON:", str(e))
|
85 |
-
reply = "There was an error processing your request."
|
86 |
|
87 |
-
chat_history.append({"role": "assistant", "content":
|
88 |
-
chat_display.append([message,
|
89 |
|
90 |
return chat_history, chat_display, "", code
|
91 |
|
92 |
|
93 |
-
def speech_to_text(audio
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
return transcription
|
98 |
|
99 |
|
100 |
-
def text_to_speech(text
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
|
105 |
def read_last_message(chat_display):
|
106 |
last_message = chat_display[-1][1]
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
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 init_bot(problem=""):
|
|
|
72 |
chat_history.append({"role": "user", "content": f"My latest code:\n{code}"})
|
73 |
chat_history.append({"role": "user", "content": message})
|
74 |
|
75 |
+
response = client.chat.completions.create(model=LLM_NAME, messages=chat_history)
|
|
|
|
|
76 |
|
77 |
+
reply = response.choices[0].message.content.strip()
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
+
chat_history.append({"role": "assistant", "content": reply})
|
80 |
+
chat_display.append([message, reply])
|
81 |
|
82 |
return chat_history, chat_display, "", code
|
83 |
|
84 |
|
85 |
+
def speech_to_text(audio):
|
86 |
+
assert STT_TYPE in ["OPENAI_API", "HF_API"]
|
87 |
+
|
88 |
+
if STT_TYPE == "OPENAI_API":
|
89 |
+
data = ("temp.wav", numpy_audio_to_bytes(audio[1]), "audio/wav")
|
90 |
+
client = OpenAI(base_url=STT_URL, api_key=os.getenv(f"{STT_TYPE}_KEY"))
|
91 |
+
transcription = client.audio.transcriptions.create(model=STT_NAME, file=data, response_format="text")
|
92 |
+
elif STT_TYPE == "HF_API":
|
93 |
+
headers = {"Authorization": "Bearer " + os.getenv(f"{STT_TYPE}_KEY")}
|
94 |
+
transcription = requests.post(STT_URL, headers=headers, data=numpy_audio_to_bytes(audio[1]))
|
95 |
+
transcription = transcription.json()["text"]
|
96 |
+
|
97 |
return transcription
|
98 |
|
99 |
|
100 |
+
def text_to_speech(text):
|
101 |
+
assert TTS_TYPE in ["OPENAI_API", "HF_API"]
|
102 |
+
|
103 |
+
if TTS_TYPE == "OPENAI_API":
|
104 |
+
client = OpenAI(base_url=TTS_URL, api_key=os.getenv(f"{TTS_TYPE}_KEY"))
|
105 |
+
response = client.audio.speech.create(model=TTS_NAME, voice="alloy", input=text)
|
106 |
+
elif TTS_TYPE == "HF_API":
|
107 |
+
headers = {"Authorization": "Bearer " + os.getenv(f"{STT_TYPE}_KEY")}
|
108 |
+
response = requests.post(TTS_URL, headers=headers)
|
109 |
+
|
110 |
+
audio = response.content
|
111 |
+
return audio
|
112 |
|
113 |
|
114 |
def read_last_message(chat_display):
|
115 |
last_message = chat_display[-1][1]
|
116 |
+
if last_message is not None:
|
117 |
+
audio = text_to_speech(last_message)
|
118 |
+
return audio
|
119 |
+
return None
|
prompts.py
CHANGED
@@ -14,10 +14,6 @@ coding_interviewer_prompt = (
|
|
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 |
-
"Responses should be structured in JSON format with two fields: "
|
18 |
-
"1. 'reply_to_candidate': contains visible feedback and guidance for the candidate, structured to facilitate learning and insight without giving away answers. "
|
19 |
-
"2. 'hidden_note': internal notes for the grading AI, including observations on the candidate’s performance across various criteria such as problem-solving skills, debugging effectiveness, and adaptability. These notes may include specific code snippets the candidate struggled with, key mistakes made, and any notable strengths or weaknesses observed. "
|
20 |
-
"The 'hidden_note' should also reflect a self-critical perspective if the interviewer's expectations do not align with a valid candidate solution, acknowledging and adjusting for any potential bias or error. "
|
21 |
)
|
22 |
|
23 |
|
|
|
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 |
|