Spaces:
Build error
Build error
Upload folder using huggingface_hub
Browse files- app.py +58 -30
- explanations.py +46 -0
- transcript_transformer.py +20 -17
app.py
CHANGED
|
@@ -1,42 +1,70 @@
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
|
|
|
|
| 3 |
from transcript_transformer import TranscriptTransformer
|
| 4 |
|
| 5 |
transformer = TranscriptTransformer()
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
-
def process_transcript(
|
| 9 |
yield gr.update(value="Building the lecture..", visible=True)
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
transformed_transcript = transformer.generate_lecture(transcript, duration)
|
| 12 |
-
|
| 13 |
yield gr.update(value=transformed_transcript, visible=True)
|
| 14 |
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
gr.
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
)
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
from pypdf import PdfReader
|
| 3 |
|
| 4 |
+
from explanations import explanation1, explanation2, explanation3
|
| 5 |
from transcript_transformer import TranscriptTransformer
|
| 6 |
|
| 7 |
transformer = TranscriptTransformer()
|
| 8 |
|
| 9 |
+
def process_pdf(pdf_file):
|
| 10 |
+
pdf_reader = PdfReader(pdf_file.name)
|
| 11 |
+
text = ""
|
| 12 |
+
for page in pdf_reader.pages:
|
| 13 |
+
text += page.extract_text()
|
| 14 |
+
return text
|
| 15 |
|
| 16 |
+
def process_transcript(transcript_text: str, pdf_file, duration: int):
|
| 17 |
yield gr.update(value="Building the lecture..", visible=True)
|
| 18 |
+
|
| 19 |
+
# Use PDF content if provided, otherwise use transcript text
|
| 20 |
+
if pdf_file:
|
| 21 |
+
transcript = process_pdf(pdf_file)
|
| 22 |
+
else:
|
| 23 |
+
transcript = transcript_text
|
| 24 |
+
|
| 25 |
transformed_transcript = transformer.generate_lecture(transcript, duration)
|
|
|
|
| 26 |
yield gr.update(value=transformed_transcript, visible=True)
|
| 27 |
|
| 28 |
|
| 29 |
+
with gr.Blocks() as demo:
|
| 30 |
+
accordion1 = gr.Accordion("How prompts were engineered and refined?", open=False)
|
| 31 |
+
with accordion1:
|
| 32 |
+
gr.Markdown(explanation1)
|
| 33 |
+
|
| 34 |
+
accordion2 = gr.Accordion("Challenges faced", open=False)
|
| 35 |
+
with accordion2:
|
| 36 |
+
gr.Markdown(explanation2)
|
| 37 |
+
|
| 38 |
+
accordion3 = gr.Accordion("How the system can be extended or scaled?", open=False)
|
| 39 |
+
with accordion3:
|
| 40 |
+
gr.Markdown(explanation3)
|
| 41 |
+
|
| 42 |
+
gr.Interface(
|
| 43 |
+
fn=process_transcript,
|
| 44 |
+
inputs=[
|
| 45 |
+
gr.Textbox(
|
| 46 |
+
label="Input Transcript",
|
| 47 |
+
placeholder="Paste your transcript here...",
|
| 48 |
+
lines=10,
|
| 49 |
+
),
|
| 50 |
+
gr.File(
|
| 51 |
+
label="Or Upload PDF",
|
| 52 |
+
file_types=[".pdf"],
|
| 53 |
+
),
|
| 54 |
+
gr.Slider(
|
| 55 |
+
minimum=15,
|
| 56 |
+
maximum=60,
|
| 57 |
+
value=30,
|
| 58 |
+
step=15,
|
| 59 |
+
label="Lecture Duration (minutes)",
|
| 60 |
+
),
|
| 61 |
+
],
|
| 62 |
+
outputs=gr.Markdown(label="Transformed Teaching Transcript"),
|
| 63 |
+
title="Transcript to Teaching Material Transformer",
|
| 64 |
+
description="""Transform transcripts into teaching materials.
|
| 65 |
+
The output will be formatted as a complete lecture with clear sections,
|
| 66 |
+
examples, and interactive elements.""",
|
| 67 |
+
theme="default",
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
demo.launch()
|
explanations.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
explanation1 = """
|
| 2 |
+
I used two system prompts: one for summarizing the chunks if they surpass the amount of tokens
|
| 3 |
+
of gpt-4o-mini (the LLM model used for this app) and another one for the final response.
|
| 4 |
+
These were just to guide the AI that it is an expert educational content creator and to act like one.
|
| 5 |
+
|
| 6 |
+
I also used two user prompts for the same reason. One for summarizing chunks (if needed) and another
|
| 7 |
+
one for the final response. The user prompt for summarizing chunks includes the context of the previous
|
| 8 |
+
chunk and the current chunk. The user prompt for the final response includes the duration of the lecture
|
| 9 |
+
and the word count of the transcript. The word count of the transcript assumes that an average paced lecturer
|
| 10 |
+
speaks 130 words per minute.
|
| 11 |
+
|
| 12 |
+
They system prompt to generate the lecture tells the AI that it must focus on clarity,
|
| 13 |
+
logical flow, and educational value.
|
| 14 |
+
|
| 15 |
+
The user prompt to generate the lecture clearly describes the requirements to give structure to
|
| 16 |
+
the lecture and to make it more understandable, stating that it must:
|
| 17 |
+
|
| 18 |
+
1. Create a clear introduction that sets context and learning objectives
|
| 19 |
+
2. Organize the content into logical sections with clear headings
|
| 20 |
+
3. Include practical examples and real-world applications
|
| 21 |
+
4. Add discussion questions or interactive elements
|
| 22 |
+
5. Conclude with a summary and key takeaways
|
| 23 |
+
6. Target approximately {word_count} words
|
| 24 |
+
|
| 25 |
+
and to format the output in markdown with clear section headers and proper spacing.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
explanation2 = """
|
| 29 |
+
The main challenge was to maintain the context of the different
|
| 30 |
+
chunks of the transcript and then combine them (if the total amount of tokens of the transcript surpasses the limit).
|
| 31 |
+
I had to make sure that the AI understands the context of the previous chunk and then summarize the current chunk
|
| 32 |
+
accordingly.
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
explanation3 = """
|
| 36 |
+
The system can be extended by adding dynamic model selection.
|
| 37 |
+
This means using other LLMs like Claude or open source LLMs from HuggingFace to see different results and
|
| 38 |
+
stay with the one that is the best in terms of costs and performance.
|
| 39 |
+
|
| 40 |
+
Another idea is to generate content according to the level of difficulty.
|
| 41 |
+
For example, content for beginners, intermediate learners, or advanced audiences.
|
| 42 |
+
|
| 43 |
+
Also the system could handle videos, written articles, or interactive presentations.
|
| 44 |
+
|
| 45 |
+
Finally, the system could be deployed as an API to integrate it with other services.
|
| 46 |
+
"""
|
transcript_transformer.py
CHANGED
|
@@ -5,14 +5,19 @@ load_dotenv()
|
|
| 5 |
|
| 6 |
|
| 7 |
class TranscriptTransformer:
|
| 8 |
-
def __init__(self):
|
| 9 |
-
|
| 10 |
-
self.
|
|
|
|
| 11 |
Your task is to transform informal transcripts into structured, engaging teaching materials.
|
| 12 |
Focus on clarity, logical flow, and educational value."""
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
Requirements:
|
| 18 |
1. Create a clear introduction that sets context and learning objectives
|
|
@@ -25,7 +30,11 @@ class TranscriptTransformer:
|
|
| 25 |
Format the output in markdown with clear section headers and proper spacing.
|
| 26 |
"""
|
| 27 |
|
| 28 |
-
self.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
def split_text_into_chunks(self, text: str) -> list[str]:
|
| 31 |
"""Split the text into chunks that fit within the token limit."""
|
|
@@ -55,17 +64,11 @@ class TranscriptTransformer:
|
|
| 55 |
else ""
|
| 56 |
)
|
| 57 |
|
| 58 |
-
prompt = f"""
|
| 59 |
-
{context}
|
| 60 |
-
Summarize the following transcript chunk:
|
| 61 |
-
{chunk}
|
| 62 |
-
"""
|
| 63 |
-
|
| 64 |
response = openai.chat.completions.create(
|
| 65 |
-
model=
|
| 66 |
messages=[
|
| 67 |
-
{"role": "system", "content":
|
| 68 |
-
{"role": "user", "content":
|
| 69 |
],
|
| 70 |
max_tokens=max_output_tokens,
|
| 71 |
temperature=0.7,
|
|
@@ -96,11 +99,11 @@ class TranscriptTransformer:
|
|
| 96 |
summarized_transcript = self.summarize_text(
|
| 97 |
raw_text, max_output_tokens=max_output_tokens
|
| 98 |
)
|
| 99 |
-
full_text = f"{self.
|
| 100 |
final_response = openai.chat.completions.create(
|
| 101 |
model="gpt-4o-mini",
|
| 102 |
messages=[
|
| 103 |
-
{"role": "system", "content": self.
|
| 104 |
{"role": "user", "content": full_text},
|
| 105 |
],
|
| 106 |
max_tokens=max_output_tokens,
|
|
|
|
| 5 |
|
| 6 |
|
| 7 |
class TranscriptTransformer:
|
| 8 |
+
def __init__(self, model="gpt-4o-mini", max_tokens=128000):
|
| 9 |
+
self.model = model
|
| 10 |
+
self.max_model_tokens = max_tokens
|
| 11 |
+
self.final_response_system_prompt = """You are an expert educational content creator.
|
| 12 |
Your task is to transform informal transcripts into structured, engaging teaching materials.
|
| 13 |
Focus on clarity, logical flow, and educational value."""
|
| 14 |
|
| 15 |
+
self.summarizer_system_prompt = """You are an expert educational content creator.
|
| 16 |
+
Your task is to summarize the following transcript chunk.
|
| 17 |
+
Ensure that the summary is concise and captures the main points.
|
| 18 |
+
"""
|
| 19 |
+
|
| 20 |
+
self.final_response_user_prompt = """Transform the following transcript into a structured {duration}-minute lecture.
|
| 21 |
|
| 22 |
Requirements:
|
| 23 |
1. Create a clear introduction that sets context and learning objectives
|
|
|
|
| 30 |
Format the output in markdown with clear section headers and proper spacing.
|
| 31 |
"""
|
| 32 |
|
| 33 |
+
self.summarizer_user_prompt = """
|
| 34 |
+
{context}
|
| 35 |
+
Summarize the following transcript chunk:
|
| 36 |
+
{chunk}
|
| 37 |
+
"""
|
| 38 |
|
| 39 |
def split_text_into_chunks(self, text: str) -> list[str]:
|
| 40 |
"""Split the text into chunks that fit within the token limit."""
|
|
|
|
| 64 |
else ""
|
| 65 |
)
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
response = openai.chat.completions.create(
|
| 68 |
+
model=self.model,
|
| 69 |
messages=[
|
| 70 |
+
{"role": "system", "content": self.summarizer_system_prompt},
|
| 71 |
+
{"role": "user", "content": self.summarizer_system_prompt.format(context=context, chunk=chunk)},
|
| 72 |
],
|
| 73 |
max_tokens=max_output_tokens,
|
| 74 |
temperature=0.7,
|
|
|
|
| 99 |
summarized_transcript = self.summarize_text(
|
| 100 |
raw_text, max_output_tokens=max_output_tokens
|
| 101 |
)
|
| 102 |
+
full_text = f"{self.final_response_user_prompt.format(duration=lecture_duration, word_count=max_output_tokens)}\n\nTranscript:\n{summarized_transcript}"
|
| 103 |
final_response = openai.chat.completions.create(
|
| 104 |
model="gpt-4o-mini",
|
| 105 |
messages=[
|
| 106 |
+
{"role": "system", "content": self.final_response_system_prompt},
|
| 107 |
{"role": "user", "content": full_text},
|
| 108 |
],
|
| 109 |
max_tokens=max_output_tokens,
|