handsomeFace786 commited on
Commit
d3658d9
Β·
verified Β·
1 Parent(s): cd3c6b5

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +242 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,244 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
 
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
1
+ # πŸ§‘β€πŸ« AI-Powered YouTube Teaching Assistant β€” Enhanced Colorful UI
2
+
3
+ import os
4
+ import re
5
  import streamlit as st
6
+ from youtube_transcript_api import YouTubeTranscriptApi, TranscriptsDisabled
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain_together import ChatTogether, TogetherEmbeddings
10
+ from langchain_core.prompts import PromptTemplate
11
+ from langchain_core.runnables import RunnableParallel, RunnablePassthrough, RunnableLambda
12
+ from langchain_core.output_parsers import StrOutputParser
13
+ from langchain.agents import initialize_agent, Tool
14
+ from langchain_community.tools.tavily_search import TavilySearchResults
15
+
16
+ # Set API Keys
17
+ os.environ["TOGETHER_API_KEY"] = "5c22e5f0d9af71d1cd7dfac4284fcde8260ca7db9c81a678387c74d0679da268"
18
+
19
+ # LLM and Embeddings
20
+ llm = ChatTogether(model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free", temperature=0.2)
21
+ embeddings = TogetherEmbeddings(model="togethercomputer/m2-bert-80M-32k-retrieval")
22
+
23
+ # Prompts
24
+ note_prompt = PromptTemplate(
25
+ template="""
26
+ You're a note-taking assistant. Convert the following transcript into clear, concise lecture notes:
27
+ - Headings
28
+ - Bullet points
29
+ - Definitions
30
+ - Examples
31
+
32
+ Transcript:
33
+ {chunk}
34
+ """,
35
+ input_variables=["chunk"]
36
+ )
37
+
38
+ quiz_prompt = PromptTemplate(
39
+ template="""
40
+ Generate 3 multiple-choice questions from the following transcript. Include correct answers.
41
+
42
+ Transcript:
43
+ {chunk}
44
+ """,
45
+ input_variables=["chunk"]
46
+ )
47
+
48
+ assignment_prompt = PromptTemplate(
49
+ template="""
50
+ Based on the transcript below, generate 2 beginner-level coding exercises and short answers.
51
+
52
+ Transcript:
53
+ {chunk}
54
+ """,
55
+ input_variables=["chunk"]
56
+ )
57
+
58
+ compare_prompt = PromptTemplate(
59
+ template="""
60
+ Compare the following two transcripts. Highlight:
61
+ - Similarities
62
+ - Differences
63
+ - Unique insights
64
+
65
+ Transcript 1:
66
+ {transcript1}
67
+
68
+ Transcript 2:
69
+ {transcript2}
70
+ """,
71
+ input_variables=["transcript1", "transcript2"]
72
+ )
73
+
74
+ # Helper Functions
75
+ def extract_video_id(url):
76
+ match = re.search(r"(?:v=|youtu\\.be/)([^&?]+)", url)
77
+ return match.group(1) if match else None
78
+
79
+ def get_transcript(video_id):
80
+ try:
81
+ transcript_list = YouTubeTranscriptApi.get_transcript(video_id, languages=["en"])
82
+ return " ".join(chunk["text"] for chunk in transcript_list)
83
+ except TranscriptsDisabled:
84
+ return None
85
+
86
+ def split_transcript(transcript):
87
+ splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
88
+ return splitter.create_documents([transcript])
89
+
90
+ def create_vector_store(docs):
91
+ return FAISS.from_documents(docs, embeddings)
92
+
93
+ def format_docs(docs):
94
+ return "\n\n".join(doc.page_content for doc in docs)
95
+
96
+ def generate_notes(chunks):
97
+ return [llm.invoke(note_prompt.invoke({"chunk": chunk.page_content})).content for chunk in chunks]
98
+
99
+ def generate_quiz(chunks):
100
+ return [llm.invoke(quiz_prompt.invoke({"chunk": chunk.page_content})).content for chunk in chunks]
101
+
102
+ def generate_assignments(chunks):
103
+ return [llm.invoke(assignment_prompt.invoke({"chunk": chunk.page_content})).content for chunk in chunks]
104
+
105
+ def find_resources(query):
106
+ tavily = TavilySearchResults()
107
+ tools = [Tool.from_function(name="search", func=tavily.run, description="Web search")]
108
+ agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=False)
109
+ return agent.run(query)
110
+
111
+ def compare_videos(t1, t2):
112
+ return llm.invoke(compare_prompt.invoke({"transcript1": t1, "transcript2": t2})).content
113
+
114
+ # Streamlit UI
115
+ st.set_page_config(page_title="🎨 AI Teaching Assistant", layout="centered")
116
+ st.markdown("""
117
+ <style>
118
+ .main {
119
+ background: linear-gradient(145deg, #f0f4f8, #c3e0e5);
120
+ padding: 2rem;
121
+ border-radius: 12px;
122
+ }
123
+ .stTextInput>div>div>input {
124
+ border-radius: 0.75rem;
125
+ border: 2px solid #5dade2;
126
+ background-color: #fefefe;
127
+ }
128
+ .stSelectbox>div>div>div {
129
+ border-radius: 0.75rem;
130
+ background-color: #ebf5fb;
131
+ font-weight: bold;
132
+ color: #2e4053;
133
+ }
134
+ .stButton>button {
135
+ border-radius: 0.5rem;
136
+ background: linear-gradient(to right, #00c6ff, #0072ff);
137
+ color: white;
138
+ font-weight: bold;
139
+ padding: 0.6rem 1.2rem;
140
+ }
141
+ .block-container {
142
+ padding: 2rem 3rem;
143
+ }
144
+ </style>
145
+ """, unsafe_allow_html=True)
146
+
147
+ st.markdown("""
148
+ <h1 style='text-align: center; color: #154360;'>πŸŽ“ AI Teaching Assistant</h1>
149
+ <p style='text-align: center; font-size: 18px; color: #1b2631;'>Transform YouTube videos into interactive, intelligent content effortlessly!</p>
150
+ <hr style='border-top: 1px solid #aed6f1;'>
151
+ """, unsafe_allow_html=True)
152
+
153
+ option = st.selectbox("🎯 What do you want to do?", [
154
+ "Summarize",
155
+ "Ask a custom question",
156
+ "Compare with another video",
157
+ "Lecture Notes Generator",
158
+ "Quiz Generator",
159
+ "Assignment / Coding Problems Generator",
160
+ "Follow-up Resource Finder"
161
+ ])
162
+
163
+ video_url = st.text_input("πŸ”— Enter YouTube video URL")
164
+ video_id = extract_video_id(video_url)
165
+ transcript = get_transcript(video_id) if video_id else None
166
+
167
+ if option == "Compare with another video":
168
+ second_url = st.text_input("πŸ” Enter second video URL to compare")
169
+ if st.button("🧠 Compare Videos"):
170
+ t1, t2 = get_transcript(extract_video_id(video_url)), get_transcript(extract_video_id(second_url))
171
+ if t1 and t2:
172
+ result = compare_videos(t1[:4000], t2[:4000])
173
+ st.markdown(result)
174
+ else:
175
+ st.error("One or both transcripts unavailable.")
176
+
177
+ elif transcript:
178
+ chunks = split_transcript(transcript)
179
+ if option == "Summarize":
180
+ retriever = create_vector_store(chunks).as_retriever()
181
+ question = "Summarize this video"
182
+ chain = RunnableParallel({
183
+ "context": retriever | RunnableLambda(format_docs),
184
+ "question": RunnablePassthrough()
185
+ }) | PromptTemplate(
186
+ template="""
187
+ You are a helpful assistant. Use only the provided context to answer.
188
+
189
+ {context}
190
+ Question: {question}
191
+ """,
192
+ input_variables=["context", "question"]
193
+ ) | llm | StrOutputParser()
194
+ summary = chain.invoke(question)
195
+ st.text_area("πŸ“„ Summary", summary, height=300)
196
+
197
+ elif option == "Ask a custom question":
198
+ custom_q = st.text_input("πŸ’¬ Your question about the video")
199
+ if st.button("🧠 Ask"):
200
+ retriever = create_vector_store(chunks).as_retriever()
201
+ chain = RunnableParallel({
202
+ "context": retriever | RunnableLambda(format_docs),
203
+ "question": RunnablePassthrough()
204
+ }) | PromptTemplate(
205
+ template="""
206
+ You are a helpful assistant. Use only the provided context to answer.
207
+
208
+ {context}
209
+ Question: {question}
210
+ """,
211
+ input_variables=["context", "question"]
212
+ ) | llm | StrOutputParser()
213
+ answer = chain.invoke(custom_q)
214
+ st.text_area("πŸ’‘ AI Answer", answer, height=300)
215
+
216
+ elif option == "Lecture Notes Generator":
217
+ if st.button("πŸ“ Generate Notes"):
218
+ notes = generate_notes(chunks)
219
+ for i, n in enumerate(notes):
220
+ st.markdown(f"### πŸ“˜ Section {i+1}")
221
+ st.markdown(n)
222
+
223
+ elif option == "Quiz Generator":
224
+ if st.button("πŸ§ͺ Generate Quiz"):
225
+ quiz = generate_quiz(chunks)
226
+ for i, q in enumerate(quiz):
227
+ st.markdown(f"### ❓ Quiz {i+1}")
228
+ st.markdown(q)
229
+ st.success("βœ”οΈ Quiz Generated. (Manual review for answers)")
230
+
231
+ elif option == "Assignment / Coding Problems Generator":
232
+ if st.button("πŸ‘¨β€πŸ’» Generate Assignments"):
233
+ tasks = generate_assignments(chunks)
234
+ for i, t in enumerate(tasks):
235
+ st.markdown(f"### βš™οΈ Task {i+1}")
236
+ st.markdown(t)
237
+
238
+ elif option == "Follow-up Resource Finder":
239
+ if st.button("🌐 Find More Resources"):
240
+ followup = find_resources(f"learning resources about: {transcript[:300]}")
241
+ st.markdown(followup)
242
 
243
+ else:
244
+ st.warning("⚠️ Please enter a valid YouTube URL with available transcript.")