Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,34 +3,30 @@ from youtube_transcript_api import YouTubeTranscriptApi
|
|
3 |
import re
|
4 |
import tempfile
|
5 |
import os
|
6 |
-
import
|
7 |
-
import torch
|
8 |
-
from transformers import pipeline
|
9 |
-
from groq.client import Client
|
10 |
|
11 |
-
# Set up
|
12 |
-
|
13 |
|
14 |
-
#
|
15 |
-
|
16 |
-
"automatic-speech-recognition",
|
17 |
-
model="openai/whisper-medium",
|
18 |
-
chunk_length_s=30,
|
19 |
-
device=device,
|
20 |
-
)
|
21 |
|
22 |
-
#
|
23 |
-
warnings.filterwarnings("ignore", message="FP16 is not supported on CPU; using FP32 instead")
|
24 |
-
|
25 |
-
# Set up Groq client
|
26 |
-
client = Client(api_key=os.environ.get("GROQ_API_KEY"))
|
27 |
-
|
28 |
-
# Function to transcribe audio using ASR pipeline
|
29 |
def transcribe_audio(file_path):
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
# Function to get transcript from YouTube
|
36 |
def get_transcript(url):
|
@@ -45,36 +41,34 @@ def get_transcript(url):
|
|
45 |
except Exception as e:
|
46 |
return str(e)
|
47 |
|
48 |
-
# Function to summarize text using
|
49 |
def summarize_text(text):
|
50 |
try:
|
51 |
-
response =
|
|
|
52 |
messages=[
|
53 |
-
{
|
54 |
-
|
55 |
-
"content": f"Summarize the following text:\n\n{text}"
|
56 |
-
}
|
57 |
],
|
58 |
-
|
59 |
)
|
60 |
-
summary = response
|
61 |
return summary
|
62 |
except Exception as e:
|
63 |
return f"Error summarizing text: {e}"
|
64 |
|
65 |
-
# Function to generate quiz questions using
|
66 |
def generate_quiz_questions(text):
|
67 |
try:
|
68 |
-
response =
|
|
|
69 |
messages=[
|
70 |
-
{
|
71 |
-
|
72 |
-
"content": f"Generate quiz questions for the following text:\n\n{text}"
|
73 |
-
}
|
74 |
],
|
75 |
-
|
76 |
)
|
77 |
-
quiz_questions = response
|
78 |
return quiz_questions
|
79 |
except Exception as e:
|
80 |
return f"Error generating quiz questions: {e}"
|
@@ -82,50 +76,50 @@ def generate_quiz_questions(text):
|
|
82 |
# Function to parse quiz questions from generated text
|
83 |
def parse_quiz_questions(quiz_text):
|
84 |
questions = []
|
85 |
-
question_blocks = quiz_text.split("\n\n")
|
86 |
current_question = None
|
87 |
current_choices = []
|
88 |
correct_answer = None
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
|
|
105 |
|
106 |
# Add the last question if it exists
|
107 |
-
if current_question
|
108 |
questions.append({
|
109 |
"question": current_question,
|
110 |
"choices": current_choices,
|
111 |
"correct_answer": correct_answer
|
112 |
})
|
113 |
-
|
114 |
return questions
|
115 |
|
116 |
-
# Function to generate explanation for quiz answers using
|
117 |
def generate_explanation(question, correct_answer, user_answer):
|
118 |
try:
|
119 |
-
response =
|
|
|
120 |
messages=[
|
121 |
-
{
|
122 |
-
|
123 |
-
"content": f"Explain why the correct answer to the following question is '{correct_answer}' and not '{user_answer}':\n\n{question}"
|
124 |
-
}
|
125 |
],
|
126 |
-
|
127 |
)
|
128 |
-
explanation = response
|
129 |
return explanation
|
130 |
except Exception as e:
|
131 |
return f"Error generating explanation: {e}"
|
@@ -135,7 +129,7 @@ def check_answers(questions, user_answers):
|
|
135 |
feedback = []
|
136 |
correct_count = 0
|
137 |
for i, question in enumerate(questions):
|
138 |
-
correct_answer = question
|
139 |
user_answer = user_answers.get(f"question_{i+1}", "")
|
140 |
if user_answer == correct_answer:
|
141 |
feedback.append({
|
@@ -158,10 +152,10 @@ def check_answers(questions, user_answers):
|
|
158 |
|
159 |
# Function to handle uploaded files
|
160 |
def handle_uploaded_file(uploaded_file):
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
return
|
165 |
|
166 |
# Streamlit app layout and functionality
|
167 |
st.title("YouTube Transcript Quiz Generator")
|
@@ -182,18 +176,18 @@ if option == "YouTube URL":
|
|
182 |
quiz_text = generate_quiz_questions(transcript_text)
|
183 |
questions = parse_quiz_questions(quiz_text)
|
184 |
|
185 |
-
if
|
186 |
st.error("No valid quiz questions could be generated.")
|
187 |
else:
|
188 |
st.session_state.summary = summary
|
189 |
-
st.session_state.questions = questions
|
190 |
st.session_state.user_answers = {}
|
191 |
st.session_state.generated_quiz = True
|
192 |
else:
|
193 |
st.error(transcript_text)
|
194 |
|
195 |
if option == "Upload audio/video file":
|
196 |
-
uploaded_file = st.file_uploader("Choose an audio or video file", type=
|
197 |
if uploaded_file:
|
198 |
if st.button("Generate Quiz"):
|
199 |
tmp_file_path = handle_uploaded_file(uploaded_file)
|
@@ -204,11 +198,11 @@ if option == "Upload audio/video file":
|
|
204 |
quiz_text = generate_quiz_questions(transcript_text)
|
205 |
questions = parse_quiz_questions(quiz_text)
|
206 |
|
207 |
-
if
|
208 |
st.error("No valid quiz questions could be generated.")
|
209 |
else:
|
210 |
st.session_state.summary = summary
|
211 |
-
st.session_state.questions = questions
|
212 |
st.session_state.user_answers = {}
|
213 |
st.session_state.generated_quiz = True
|
214 |
else:
|
@@ -241,4 +235,4 @@ if st.session_state.generated_quiz:
|
|
241 |
if item['status'] == "Incorrect":
|
242 |
st.write(f"**Explanation:** {item['explanation']}")
|
243 |
else:
|
244 |
-
st.write("Please generate the quiz first.")
|
|
|
3 |
import re
|
4 |
import tempfile
|
5 |
import os
|
6 |
+
import openai
|
|
|
|
|
|
|
7 |
|
8 |
+
# Set up OpenAI API key
|
9 |
+
openai.api_key = os.getenv("OPENAI_API_KEY")
|
10 |
|
11 |
+
# Supported file types for OpenAI API
|
12 |
+
SUPPORTED_FILE_TYPES = ["mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm"]
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
+
# Function to transcribe audio using OpenAI Whisper API
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
def transcribe_audio(file_path):
|
16 |
+
file_extension = os.path.splitext(file_path)[1][1:]
|
17 |
+
if file_extension not in SUPPORTED_FILE_TYPES:
|
18 |
+
return f"Error: Unsupported file type '{file_extension}'. Please upload a valid file."
|
19 |
+
|
20 |
+
try:
|
21 |
+
with open(file_path, "rb") as file:
|
22 |
+
response = openai.Audio.transcribe(
|
23 |
+
model="whisper-1",
|
24 |
+
file=file,
|
25 |
+
response_format="json"
|
26 |
+
)
|
27 |
+
return response['text']
|
28 |
+
except Exception as e:
|
29 |
+
return f"Error during transcription: {e}"
|
30 |
|
31 |
# Function to get transcript from YouTube
|
32 |
def get_transcript(url):
|
|
|
41 |
except Exception as e:
|
42 |
return str(e)
|
43 |
|
44 |
+
# Function to summarize text using OpenAI API
|
45 |
def summarize_text(text):
|
46 |
try:
|
47 |
+
response = openai.ChatCompletion.create(
|
48 |
+
model="gpt-3.5-turbo",
|
49 |
messages=[
|
50 |
+
{"role": "system", "content": "You are a helpful assistant."},
|
51 |
+
{"role": "user", "content": f"Summarize the following text:\n\n{text}"}
|
|
|
|
|
52 |
],
|
53 |
+
max_tokens=100,
|
54 |
)
|
55 |
+
summary = response.choices[0].message['content'].strip()
|
56 |
return summary
|
57 |
except Exception as e:
|
58 |
return f"Error summarizing text: {e}"
|
59 |
|
60 |
+
# Function to generate quiz questions using OpenAI API
|
61 |
def generate_quiz_questions(text):
|
62 |
try:
|
63 |
+
response = openai.ChatCompletion.create(
|
64 |
+
model="gpt-3.5-turbo",
|
65 |
messages=[
|
66 |
+
{"role": "system", "content": "You are a helpful assistant."},
|
67 |
+
{"role": "user", "content": f"Generate 10 quiz questions from the following text. Make sure the questions cover all key points and are varied in type (e.g., multiple choice, short answer). Number each question and provide the correct answer after the question number:\n\n{text}"}
|
|
|
|
|
68 |
],
|
69 |
+
max_tokens=1000,
|
70 |
)
|
71 |
+
quiz_questions = response.choices[0].message['content'].strip()
|
72 |
return quiz_questions
|
73 |
except Exception as e:
|
74 |
return f"Error generating quiz questions: {e}"
|
|
|
76 |
# Function to parse quiz questions from generated text
|
77 |
def parse_quiz_questions(quiz_text):
|
78 |
questions = []
|
|
|
79 |
current_question = None
|
80 |
current_choices = []
|
81 |
correct_answer = None
|
82 |
+
|
83 |
+
lines = quiz_text.split("\n")
|
84 |
+
for line in lines:
|
85 |
+
line = line.strip()
|
86 |
+
if re.match(r'^\d+\.', line): # This line is a question number
|
87 |
+
if current_question:
|
88 |
+
questions.append({
|
89 |
+
"question": current_question,
|
90 |
+
"choices": current_choices,
|
91 |
+
"correct_answer": correct_answer
|
92 |
+
})
|
93 |
+
current_question = line
|
94 |
+
current_choices = []
|
95 |
+
correct_answer = None
|
96 |
+
elif line.startswith("Answer:"):
|
97 |
+
correct_answer = line.split(":", 1)[1].strip()
|
98 |
+
elif line:
|
99 |
+
current_choices.append(line)
|
100 |
|
101 |
# Add the last question if it exists
|
102 |
+
if current_question:
|
103 |
questions.append({
|
104 |
"question": current_question,
|
105 |
"choices": current_choices,
|
106 |
"correct_answer": correct_answer
|
107 |
})
|
108 |
+
|
109 |
return questions
|
110 |
|
111 |
+
# Function to generate explanation for quiz answers using OpenAI API
|
112 |
def generate_explanation(question, correct_answer, user_answer):
|
113 |
try:
|
114 |
+
response = openai.ChatCompletion.create(
|
115 |
+
model="gpt-3.5-turbo",
|
116 |
messages=[
|
117 |
+
{"role": "system", "content": "You are a helpful assistant."},
|
118 |
+
{"role": "user", "content": f"Explain why the correct answer to the following question is '{correct_answer}' and not '{user_answer}':\n\n{question}"}
|
|
|
|
|
119 |
],
|
120 |
+
max_tokens=100,
|
121 |
)
|
122 |
+
explanation = response.choices[0].message['content'].strip()
|
123 |
return explanation
|
124 |
except Exception as e:
|
125 |
return f"Error generating explanation: {e}"
|
|
|
129 |
feedback = []
|
130 |
correct_count = 0
|
131 |
for i, question in enumerate(questions):
|
132 |
+
correct_answer = question.get('correct_answer')
|
133 |
user_answer = user_answers.get(f"question_{i+1}", "")
|
134 |
if user_answer == correct_answer:
|
135 |
feedback.append({
|
|
|
152 |
|
153 |
# Function to handle uploaded files
|
154 |
def handle_uploaded_file(uploaded_file):
|
155 |
+
file_path = tempfile.mktemp(suffix=os.path.splitext(uploaded_file.name)[1])
|
156 |
+
with open(file_path, "wb") as f:
|
157 |
+
f.write(uploaded_file.read())
|
158 |
+
return file_path
|
159 |
|
160 |
# Streamlit app layout and functionality
|
161 |
st.title("YouTube Transcript Quiz Generator")
|
|
|
176 |
quiz_text = generate_quiz_questions(transcript_text)
|
177 |
questions = parse_quiz_questions(quiz_text)
|
178 |
|
179 |
+
if len(questions) < 10:
|
180 |
st.error("No valid quiz questions could be generated.")
|
181 |
else:
|
182 |
st.session_state.summary = summary
|
183 |
+
st.session_state.questions = questions[:10] # Ensure only 10 questions are taken
|
184 |
st.session_state.user_answers = {}
|
185 |
st.session_state.generated_quiz = True
|
186 |
else:
|
187 |
st.error(transcript_text)
|
188 |
|
189 |
if option == "Upload audio/video file":
|
190 |
+
uploaded_file = st.file_uploader("Choose an audio or video file", type=SUPPORTED_FILE_TYPES)
|
191 |
if uploaded_file:
|
192 |
if st.button("Generate Quiz"):
|
193 |
tmp_file_path = handle_uploaded_file(uploaded_file)
|
|
|
198 |
quiz_text = generate_quiz_questions(transcript_text)
|
199 |
questions = parse_quiz_questions(quiz_text)
|
200 |
|
201 |
+
if len(questions) < 10:
|
202 |
st.error("No valid quiz questions could be generated.")
|
203 |
else:
|
204 |
st.session_state.summary = summary
|
205 |
+
st.session_state.questions = questions[:10] # Ensure only 10 questions are taken
|
206 |
st.session_state.user_answers = {}
|
207 |
st.session_state.generated_quiz = True
|
208 |
else:
|
|
|
235 |
if item['status'] == "Incorrect":
|
236 |
st.write(f"**Explanation:** {item['explanation']}")
|
237 |
else:
|
238 |
+
st.write("Please generate the quiz first.")
|