import streamlit as st from youtube_transcript_api import YouTubeTranscriptApi import re import tempfile import os import warnings from groq import Groq from whisper_jax import FlaxWhisperPipline # Suppress specific warning warnings.filterwarnings("ignore", message="FP16 is not supported on CPU; using FP32 instead") # Set up Groq client client = Groq(api_key=os.environ.get("GROQ_API_KEY")) # Instantiate Whisper JAX pipeline pipeline = FlaxWhisperPipline("openai/whisper-large-v2") # Function to transcribe audio using Whisper JAX def transcribe_audio(file_path): # JIT compile the forward call - slow, but we only do once text = pipeline(file_path) # Used cached function thereafter - super fast!! text = pipeline(file_path) return text # Function to get transcript from YouTube def get_transcript(url): try: video_id_match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11}).*", url) if not video_id_match: return "Error: Invalid YouTube URL" video_id = video_id_match.group(1) transcript = YouTubeTranscriptApi.get_transcript(video_id) transcript_text = ' '.join([entry['text'] for entry in transcript]) return transcript_text except Exception as e: return str(e) # Function to summarize text using Groq API def summarize_text(text): try: response = client.chat.completions.create( messages=[ { "role": "user", "content": f"Summarize the following text:\n\n{text}" } ], model="llama3-8b-8192", ) summary = response.choices[0].message.content.strip() return summary except Exception as e: return f"Error summarizing text: {e}" # Function to generate quiz questions using Groq API def generate_quiz_questions(text): try: response = client.chat.completions.create( messages=[ { "role": "user", "content": f"Generate quiz questions for the following text:\n\n{text}" } ], model="llama3-8b-8192", ) quiz_questions = response.choices[0].message.content.strip() return quiz_questions except Exception as e: return f"Error generating quiz questions: {e}" # Function to parse quiz questions from generated text def parse_quiz_questions(quiz_text): questions = [] question_blocks = quiz_text.split("\n\n") current_question = None current_choices = [] correct_answer = None for block in question_blocks: lines = block.strip().split("\n") if lines: if re.match(r'^\d+\.', lines[0]): # This line is a question number if current_question and current_choices and correct_answer: questions.append({ "question": current_question, "choices": current_choices, "correct_answer": correct_answer }) current_question = lines[0] current_choices = lines[1:5] correct_answer = lines[-1].split(": ")[-1].strip() if len(lines) > 5 else None else: # This line is an answer correct_answer = lines[-1].split(": ")[-1].strip() # Add the last question if it exists if current_question and current_choices and correct_answer: questions.append({ "question": current_question, "choices": current_choices, "correct_answer": correct_answer }) return questions # Function to generate explanation for quiz answers using Groq API def generate_explanation(question, correct_answer, user_answer): try: response = client.chat.completions.create( messages=[ { "role": "user", "content": f"Explain why the correct answer to the following question is '{correct_answer}' and not '{user_answer}':\n\n{question}" } ], model="llama3-8b-8192", ) explanation = response.choices[0].message.content.strip() return explanation except Exception as e: return f"Error generating explanation: {e}" # Function to check answers and provide feedback def check_answers(questions, user_answers): feedback = [] correct_count = 0 for i, question in enumerate(questions): correct_answer = question['correct_answer'] user_answer = user_answers.get(f"question_{i+1}", "") if user_answer == correct_answer: feedback.append({ "question": question['question'], "user_answer": user_answer, "correct_answer": correct_answer, "status": "Correct" }) correct_count += 1 else: explanation = generate_explanation(question['question'], correct_answer, user_answer) feedback.append({ "question": question['question'], "user_answer": user_answer, "correct_answer": correct_answer, "status": "Incorrect", "explanation": explanation }) return feedback # Function to handle uploaded files def handle_uploaded_file(uploaded_file): with tempfile.NamedTemporaryFile(delete=False) as tmp_file: tmp_file.write(uploaded_file.read()) tmp_file_path = tmp_file.name return tmp_file_path # Streamlit app layout and functionality st.title("YouTube Transcript Quiz Generator") st.markdown("**Instructions:** Paste a YouTube link or upload a media file to generate a quiz.") option = st.selectbox("Choose input type", ("YouTube URL", "Upload audio/video file")) if "generated_quiz" not in st.session_state: st.session_state.generated_quiz = False if option == "YouTube URL": url = st.text_input("YouTube URL", value="") if url: if st.button("Generate Quiz"): transcript_text = get_transcript(url) if "Error" not in transcript_text: summary = summarize_text(transcript_text) quiz_text = generate_quiz_questions(transcript_text) questions = parse_quiz_questions(quiz_text) if not questions: st.error("No valid quiz questions could be generated.") else: st.session_state.summary = summary st.session_state.questions = questions st.session_state.user_answers = {} st.session_state.generated_quiz = True else: st.error(transcript_text) if option == "Upload audio/video file": uploaded_file = st.file_uploader("Choose an audio or video file", type=["mp3", "wav", "mp4", "mov"]) if uploaded_file: if st.button("Generate Quiz"): tmp_file_path = handle_uploaded_file(uploaded_file) transcript_text = transcribe_audio(tmp_file_path) os.remove(tmp_file_path) if "Error" not in transcript_text: summary = summarize_text(transcript_text) quiz_text = generate_quiz_questions(transcript_text) questions = parse_quiz_questions(quiz_text) if not questions: st.error("No valid quiz questions could be generated.") else: st.session_state.summary = summary st.session_state.questions = questions st.session_state.user_answers = {} st.session_state.generated_quiz = True else: st.error(transcript_text) if st.session_state.generated_quiz: st.write("## Summary") st.write(st.session_state.summary) st.write("## Quiz Questions") for i, question in enumerate(st.session_state.questions): st.write(f"### Question {i+1}") st.write(question['question']) st.session_state.user_answers[f"question_{i+1}"] = st.radio( label="", options=question['choices'], key=f"question_{i+1}" ) if st.button("Submit Answers"): if "questions" in st.session_state and st.session_state.questions: with st.spinner('ProcessingIf `whisper_jax` is not found, it might not be available on PyPI or installed properly. If you need to use an alternative or similar library, ensure it's correctly installed. Let's try another approach using `whisper` from OpenAI, which should be available on PyPI and can be used similarly. ### Updated `requirements.txt` ```txt streamlit youtube_transcript_api groq whisper