Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -5,16 +5,17 @@ from pytube import YouTube
|
|
| 5 |
import tempfile
|
| 6 |
from fpdf import FPDF
|
| 7 |
import time
|
|
|
|
| 8 |
|
| 9 |
-
#
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
| 13 |
|
| 14 |
-
# AssemblyAI API configuration
|
| 15 |
assembly_base_url = "https://api.assemblyai.com/v2"
|
| 16 |
assembly_headers = {
|
| 17 |
-
"authorization":
|
| 18 |
}
|
| 19 |
|
| 20 |
def generate_sentiment_score(input_text, parameters):
|
|
@@ -27,53 +28,47 @@ def generate_sentiment_score(input_text, parameters):
|
|
| 27 |
1. Carefully review the provided interview transcript.
|
| 28 |
2. Consider phrases, word choices, or patterns of speech that convey positive or negative sentiment for each parameter.
|
| 29 |
3. Based on your analysis, provide a sentiment score on a scale of 1-5 for each parameter, with 1 being extremely negative and 5 being extremely positive.
|
| 30 |
-
Provide your scores in the format: Parameter: Score.
|
| 31 |
-
'''
|
| 32 |
-
|
| 33 |
-
headers = {
|
| 34 |
-
"Authorization": f"Bearer {together_api_key}",
|
| 35 |
-
"Content-Type": "application/json"
|
| 36 |
-
}
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
"temperature": 0.0,
|
| 42 |
-
"max_tokens": 1024
|
| 43 |
-
}
|
| 44 |
|
| 45 |
-
response =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
-
|
| 48 |
-
return response.json()['output']['choices'][0]['text']
|
| 49 |
-
else:
|
| 50 |
-
raise Exception(f"Error: {response.status_code} - {response.text}")
|
| 51 |
|
| 52 |
def generate_detailed_feedback(input_text, parameters):
|
| 53 |
prompt = f'''
|
| 54 |
As an experienced interview reviewer, provide a detailed analysis of the candidate's responses based on the following parameters: {', '.join(parameters)}.
|
| 55 |
|
| 56 |
-
Include specific examples, quotes, and adjectives from the transcript that support your analysis. Offer actionable insights and recommendations for the hiring team to make informed decisions. Summarize the candidate's overall sentiment and demeanor.
|
| 57 |
-
'''
|
| 58 |
-
|
| 59 |
-
headers = {
|
| 60 |
-
"Authorization": f"Bearer {together_api_key}",
|
| 61 |
-
"Content-Type": "application/json"
|
| 62 |
-
}
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
"temperature": 0.0,
|
| 68 |
-
"max_tokens": 2048
|
| 69 |
-
}
|
| 70 |
|
| 71 |
-
response =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
-
|
| 74 |
-
return response.json()['output']['choices'][0]['text']
|
| 75 |
-
else:
|
| 76 |
-
raise Exception(f"Error: {response.status_code} - {response.text}")
|
| 77 |
|
| 78 |
def upload_to_assemblyai(file_path):
|
| 79 |
with open(file_path, "rb") as f:
|
|
@@ -100,9 +95,10 @@ def transcript(video_link):
|
|
| 100 |
try:
|
| 101 |
yt = YouTube(video_link)
|
| 102 |
stream = yt.streams.filter(only_audio=True).first()
|
| 103 |
-
temp_file_path =
|
|
|
|
| 104 |
|
| 105 |
-
print(f"Video '{yt.title}
|
| 106 |
|
| 107 |
upload_url = upload_to_assemblyai(temp_file_path)
|
| 108 |
transcription_text = transcribe_with_assemblyai(upload_url)
|
|
@@ -166,71 +162,60 @@ def main():
|
|
| 166 |
if input_text and parameters:
|
| 167 |
with st.spinner("Generating sentiment scores..."):
|
| 168 |
sentiment_scores = generate_sentiment_score(input_text, parameters)
|
| 169 |
-
sentiment_scores = sentiment_scores.strip().split("\n")
|
| 170 |
-
|
| 171 |
st.subheader("Sentiment Scores")
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
st.download_button(
|
| 205 |
-
label="Download Detailed Feedback as .
|
| 206 |
-
data=
|
| 207 |
-
file_name="detailed_feedback.
|
| 208 |
-
mime="
|
| 209 |
)
|
| 210 |
-
|
| 211 |
-
pdf = FPDF()
|
| 212 |
-
pdf.add_page()
|
| 213 |
-
pdf.set_font("Arial", size=12)
|
| 214 |
-
pdf.multi_cell(0, 10, detailed_feedback)
|
| 215 |
-
|
| 216 |
-
temp_pdf_path = tempfile.mktemp(suffix=".pdf")
|
| 217 |
-
pdf.output(temp_pdf_path)
|
| 218 |
-
|
| 219 |
-
with open(temp_pdf_path, "rb") as f:
|
| 220 |
-
st.download_button(
|
| 221 |
-
label="Download Detailed Feedback as .pdf",
|
| 222 |
-
data=f.read(),
|
| 223 |
-
file_name="detailed_feedback.pdf",
|
| 224 |
-
mime="application/pdf"
|
| 225 |
-
)
|
| 226 |
else:
|
| 227 |
st.warning("Please provide input and parameters for sentiment analysis.")
|
| 228 |
|
| 229 |
if __name__ == "__main__":
|
| 230 |
-
main()
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
|
|
|
| 5 |
import tempfile
|
| 6 |
from fpdf import FPDF
|
| 7 |
import time
|
| 8 |
+
from together import Together
|
| 9 |
|
| 10 |
+
# API configurations
|
| 11 |
+
together_api_key = os.environ.get('TOGETHER_API_KEY')
|
| 12 |
+
assembly_api_key = os.environ.get('ASSEMBLYAI_API_KEY')
|
| 13 |
+
|
| 14 |
+
client = Together(api_key=together_api_key)
|
| 15 |
|
|
|
|
| 16 |
assembly_base_url = "https://api.assemblyai.com/v2"
|
| 17 |
assembly_headers = {
|
| 18 |
+
"authorization": assembly_api_key
|
| 19 |
}
|
| 20 |
|
| 21 |
def generate_sentiment_score(input_text, parameters):
|
|
|
|
| 28 |
1. Carefully review the provided interview transcript.
|
| 29 |
2. Consider phrases, word choices, or patterns of speech that convey positive or negative sentiment for each parameter.
|
| 30 |
3. Based on your analysis, provide a sentiment score on a scale of 1-5 for each parameter, with 1 being extremely negative and 5 being extremely positive.
|
| 31 |
+
Provide your scores in the format: Parameter: (Score).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
+
Here's the transcript:
|
| 34 |
+
{input_text}
|
| 35 |
+
'''
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
+
response = client.chat.completions.create(
|
| 38 |
+
model="meta-llama/Llama-3-70b-chat-hf",
|
| 39 |
+
messages=[
|
| 40 |
+
{"role": "system", "content": "You are an AI assistant that analyzes interview transcripts and provides sentiment scores."},
|
| 41 |
+
{"role": "user", "content": prompt}
|
| 42 |
+
],
|
| 43 |
+
temperature=0.1,
|
| 44 |
+
max_tokens=1024,
|
| 45 |
+
top_p=0.7
|
| 46 |
+
)
|
| 47 |
|
| 48 |
+
return response.choices[0].message.content
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
def generate_detailed_feedback(input_text, parameters):
|
| 51 |
prompt = f'''
|
| 52 |
As an experienced interview reviewer, provide a detailed analysis of the candidate's responses based on the following parameters: {', '.join(parameters)}.
|
| 53 |
|
| 54 |
+
Include specific examples, quotes, and adjectives from the transcript that support your analysis.(no need to provide scores)Offer actionable insights and recommendations for the hiring team to make informed decisions. Summarize the candidate's overall sentiment and demeanor.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
+
Here's the transcript:
|
| 57 |
+
{input_text}
|
| 58 |
+
'''
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
+
response = client.chat.completions.create(
|
| 61 |
+
model="meta-llama/Llama-3-70b-chat-hf",
|
| 62 |
+
messages=[
|
| 63 |
+
{"role": "system", "content": "You are an AI assistant that provides detailed feedback on interview transcripts."},
|
| 64 |
+
{"role": "user", "content": prompt}
|
| 65 |
+
],
|
| 66 |
+
temperature=0.3,
|
| 67 |
+
max_tokens=2048,
|
| 68 |
+
top_p=0.7
|
| 69 |
+
)
|
| 70 |
|
| 71 |
+
return response.choices[0].message.content
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
def upload_to_assemblyai(file_path):
|
| 74 |
with open(file_path, "rb") as f:
|
|
|
|
| 95 |
try:
|
| 96 |
yt = YouTube(video_link)
|
| 97 |
stream = yt.streams.filter(only_audio=True).first()
|
| 98 |
+
temp_file_path = tempfile.mktemp(suffix=".mp4")
|
| 99 |
+
stream.download(output_path=os.path.dirname(temp_file_path), filename=os.path.basename(temp_file_path))
|
| 100 |
|
| 101 |
+
print(f"Video '{yt.title}' downloaded successfully!")
|
| 102 |
|
| 103 |
upload_url = upload_to_assemblyai(temp_file_path)
|
| 104 |
transcription_text = transcribe_with_assemblyai(upload_url)
|
|
|
|
| 162 |
if input_text and parameters:
|
| 163 |
with st.spinner("Generating sentiment scores..."):
|
| 164 |
sentiment_scores = generate_sentiment_score(input_text, parameters)
|
|
|
|
|
|
|
| 165 |
st.subheader("Sentiment Scores")
|
| 166 |
+
st.write(sentiment_scores)
|
| 167 |
+
|
| 168 |
+
# Parse and display scores (adjust as needed based on the model's output format)
|
| 169 |
+
scores = [line.split(":") for line in sentiment_scores.split("\n") if ":" in line]
|
| 170 |
+
for param, score in scores:
|
| 171 |
+
param = param.strip()
|
| 172 |
+
try:
|
| 173 |
+
score = float(score.strip())
|
| 174 |
+
if score >= 4:
|
| 175 |
+
color = "#2ca02c" # Green
|
| 176 |
+
elif score >= 3:
|
| 177 |
+
color = "#ff7f0e" # Orange
|
| 178 |
+
else:
|
| 179 |
+
color = "#d62728" # Red
|
| 180 |
+
st.markdown(f"**{param}**: <span style='color: {color}'>{score}/5</span>", unsafe_allow_html=True)
|
| 181 |
+
except ValueError:
|
| 182 |
+
pass
|
| 183 |
+
|
| 184 |
+
# Generate detailed feedback
|
| 185 |
+
with st.spinner("Generating detailed feedback..."):
|
| 186 |
+
detailed_feedback = generate_detailed_feedback(input_text, parameters)
|
| 187 |
+
st.subheader("Detailed Feedback")
|
| 188 |
+
st.write(detailed_feedback)
|
| 189 |
+
|
| 190 |
+
# Provide an option to download detailed feedback as a .txt or .pdf file
|
| 191 |
+
temp_txt_path = tempfile.mktemp(suffix=".txt")
|
| 192 |
+
with open(temp_txt_path, 'w') as f:
|
| 193 |
+
f.write(detailed_feedback)
|
| 194 |
+
|
| 195 |
+
st.download_button(
|
| 196 |
+
label="Download Detailed Feedback as .txt",
|
| 197 |
+
data=open(temp_txt_path, 'r').read(),
|
| 198 |
+
file_name="detailed_feedback.txt",
|
| 199 |
+
mime="text/plain"
|
| 200 |
+
)
|
| 201 |
+
|
| 202 |
+
pdf = FPDF()
|
| 203 |
+
pdf.add_page()
|
| 204 |
+
pdf.set_font("Arial", size=12)
|
| 205 |
+
pdf.multi_cell(0, 10, detailed_feedback)
|
| 206 |
+
|
| 207 |
+
temp_pdf_path = tempfile.mktemp(suffix=".pdf")
|
| 208 |
+
pdf.output(temp_pdf_path)
|
| 209 |
+
|
| 210 |
+
with open(temp_pdf_path, "rb") as f:
|
| 211 |
st.download_button(
|
| 212 |
+
label="Download Detailed Feedback as .pdf",
|
| 213 |
+
data=f.read(),
|
| 214 |
+
file_name="detailed_feedback.pdf",
|
| 215 |
+
mime="application/pdf"
|
| 216 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
else:
|
| 218 |
st.warning("Please provide input and parameters for sentiment analysis.")
|
| 219 |
|
| 220 |
if __name__ == "__main__":
|
| 221 |
+
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|