DuckyBlender
commited on
Commit
·
766eb70
1
Parent(s):
257b9bf
done!
Browse files- README.md +1 -1
- main.py +150 -0
- requirements.txt +8 -0
README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
---
|
2 |
title: Phi3 Youtube Summarizer
|
3 |
-
emoji:
|
4 |
colorFrom: blue
|
5 |
colorTo: yellow
|
6 |
sdk: gradio
|
|
|
1 |
---
|
2 |
title: Phi3 Youtube Summarizer
|
3 |
+
emoji: 📹
|
4 |
colorFrom: blue
|
5 |
colorTo: yellow
|
6 |
sdk: gradio
|
main.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from youtube_transcript_api import YouTubeTranscriptApi
|
3 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, BitsAndBytesConfig
|
4 |
+
import re
|
5 |
+
import os
|
6 |
+
import torch
|
7 |
+
|
8 |
+
# import dotenv
|
9 |
+
# dotenv.load_dotenv()
|
10 |
+
|
11 |
+
import subprocess
|
12 |
+
subprocess.run(
|
13 |
+
"pip install flash_attn --no-build-isolation --break-system-packages",
|
14 |
+
env={"FLASH_ATTENTION_SKIP_CUDA_BUILD": "TRUE"},
|
15 |
+
shell=True,
|
16 |
+
)
|
17 |
+
|
18 |
+
# Uncomment and set your Hugging Face token if needed
|
19 |
+
token = os.environ["HF_TOKEN"]
|
20 |
+
|
21 |
+
# Configure 4-bit quantization for model loading
|
22 |
+
bnb_config = BitsAndBytesConfig(
|
23 |
+
load_in_4bit=True,
|
24 |
+
bnb_4bit_use_double_quant=True,
|
25 |
+
bnb_4bit_quant_type="nf4",
|
26 |
+
bnb_4bit_compute_dtype=torch.bfloat16,
|
27 |
+
attn_implementation="flash_attention_2",
|
28 |
+
)
|
29 |
+
|
30 |
+
# Load the Phi-3 model and tokenizer
|
31 |
+
print("Loading model and tokenizer...")
|
32 |
+
model_id = "microsoft/Phi-3-mini-128k-instruct"
|
33 |
+
model = AutoModelForCausalLM.from_pretrained(
|
34 |
+
model_id,
|
35 |
+
device_map="cuda",
|
36 |
+
quantization_config=bnb_config,
|
37 |
+
trust_remote_code=True,
|
38 |
+
|
39 |
+
).eval()
|
40 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
41 |
+
|
42 |
+
# Define the system prompt and generation pipeline
|
43 |
+
system_prompt = "Summarize this YouTube video. Give a brief summary of the video content with the key points and main takeaways."
|
44 |
+
messages = [{"role": "system", "content": system_prompt}]
|
45 |
+
|
46 |
+
pipe = pipeline(
|
47 |
+
"text-generation",
|
48 |
+
model=model,
|
49 |
+
tokenizer=tokenizer,
|
50 |
+
)
|
51 |
+
|
52 |
+
generation_args = {
|
53 |
+
"max_new_tokens": 32767,
|
54 |
+
"return_full_text": False,
|
55 |
+
"do_sample": True,
|
56 |
+
"temperature": 0.2,
|
57 |
+
}
|
58 |
+
|
59 |
+
# Function to extract the video ID from a YouTube URL
|
60 |
+
def extract_video_id(url):
|
61 |
+
video_id_match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11}).*", url)
|
62 |
+
if video_id_match:
|
63 |
+
print(f"Extracted video ID: {video_id_match.group(1)}")
|
64 |
+
return video_id_match.group(1)
|
65 |
+
return None
|
66 |
+
|
67 |
+
# Function to get the transcript of a YouTube video
|
68 |
+
def get_transcript(video_id):
|
69 |
+
try:
|
70 |
+
transcript = YouTubeTranscriptApi.get_transcript(video_id)
|
71 |
+
transcription = [entry['text'] for entry in transcript]
|
72 |
+
print(f"Transcript: {transcription}")
|
73 |
+
return " ".join(transcription)
|
74 |
+
except Exception as e:
|
75 |
+
return f"Error fetching transcript: {str(e)}"
|
76 |
+
|
77 |
+
# Function to summarize the text using the model
|
78 |
+
def summarize_text(text):
|
79 |
+
messages.append({"role": "user", "content": text})
|
80 |
+
output = pipe(messages, **generation_args)
|
81 |
+
output = output[0]['generated_text'].strip() # type: ignore
|
82 |
+
print(f"Summary: {output}")
|
83 |
+
return output
|
84 |
+
|
85 |
+
# Main function to process the video URL
|
86 |
+
def process_video(url):
|
87 |
+
video_id = extract_video_id(url)
|
88 |
+
if not video_id:
|
89 |
+
print("Invalid YouTube URL")
|
90 |
+
return "Invalid YouTube URL"
|
91 |
+
|
92 |
+
transcript = get_transcript(video_id)
|
93 |
+
if transcript.startswith("Error"):
|
94 |
+
return transcript
|
95 |
+
|
96 |
+
summary = summarize_text(transcript)
|
97 |
+
return summary, transcript
|
98 |
+
|
99 |
+
# Function to update the embedded video player
|
100 |
+
def update_embed(url):
|
101 |
+
video_id = extract_video_id(url)
|
102 |
+
if video_id:
|
103 |
+
embed_url = f"https://www.youtube.com/embed/{video_id}"
|
104 |
+
return f"<div class='gradio-embed-container'><iframe class='gradio-embed' src='{embed_url}' frameborder='0' allowfullscreen></iframe></div>"
|
105 |
+
return "<div class='gradio-embed-container'><iframe class='gradio-embed' src='' frameborder='0' allowfullscreen></iframe></div>"
|
106 |
+
|
107 |
+
# Gradio UI setup
|
108 |
+
with gr.Blocks(css="""
|
109 |
+
.gradio-embed-container { position: relative; width: 100%; padding-bottom: 56.25%; height: 0; }
|
110 |
+
.gradio-embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
111 |
+
.small-font { font-size: 0.6em; }
|
112 |
+
""") as demo:
|
113 |
+
|
114 |
+
gr.Markdown("""
|
115 |
+
# YouTube Video Summarizer using Phi-3-mini-128k-instruct
|
116 |
+
Summarize any YouTube video using the Phi-3-mini-128k-instruct model.
|
117 |
+
""")
|
118 |
+
|
119 |
+
with gr.Row():
|
120 |
+
with gr.Column(scale=1):
|
121 |
+
url = gr.Textbox(
|
122 |
+
label="YouTube URL",
|
123 |
+
placeholder="https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
124 |
+
max_lines=1
|
125 |
+
)
|
126 |
+
summary = gr.Textbox(
|
127 |
+
label="Summary",
|
128 |
+
placeholder="Summary will appear here...",
|
129 |
+
lines=10,
|
130 |
+
show_label=True,
|
131 |
+
show_copy_button=True,
|
132 |
+
elem_classes="small-font"
|
133 |
+
)
|
134 |
+
transcript = gr.Textbox(
|
135 |
+
label="Transcript",
|
136 |
+
placeholder="Transcript will appear here...",
|
137 |
+
lines=1,
|
138 |
+
show_label=True,
|
139 |
+
show_copy_button=True,
|
140 |
+
elem_classes="small-font"
|
141 |
+
)
|
142 |
+
btn = gr.Button("Summarize")
|
143 |
+
btn.click(fn=process_video, inputs=url, outputs=[summary, transcript])
|
144 |
+
|
145 |
+
with gr.Column(scale=1):
|
146 |
+
video_embed = gr.HTML("<div class='gradio-embed-container'><iframe class='gradio-embed' src='' frameborder='0' allowfullscreen></iframe></div>")
|
147 |
+
|
148 |
+
url.change(fn=update_embed, inputs=url, outputs=video_embed)
|
149 |
+
|
150 |
+
demo.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
torch
|
3 |
+
transformers
|
4 |
+
youtube_transcript_api
|
5 |
+
google-api-python-client
|
6 |
+
bitsandbytes
|
7 |
+
# python-dotenv
|
8 |
+
accelerate
|