Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- README.md +5 -7
- app.py +237 -0
- requirements.txt +5 -0
README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
colorTo: blue
|
6 |
sdk: streamlit
|
7 |
-
|
8 |
-
app_file: app.py
|
9 |
-
pinned: false
|
10 |
---
|
11 |
|
12 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: Ask AI over Youtube video
|
3 |
+
emoji: π½
|
4 |
+
colorFrom: indigo
|
5 |
colorTo: blue
|
6 |
sdk: streamlit
|
7 |
+
pinned: true
|
|
|
|
|
8 |
---
|
9 |
|
10 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import logging
|
3 |
+
from typing import Any, List, Mapping, Optional
|
4 |
+
from langchain.llms import HuggingFaceHub
|
5 |
+
from gradio_client import Client
|
6 |
+
from langchain.schema import Document
|
7 |
+
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
8 |
+
from langchain.vectorstores import FAISS
|
9 |
+
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
10 |
+
from langchain.callbacks.manager import CallbackManagerForLLMRun
|
11 |
+
from langchain.llms.base import LLM
|
12 |
+
from langchain.chains import RetrievalQA
|
13 |
+
from langchain.prompts import PromptTemplate
|
14 |
+
import streamlit as st
|
15 |
+
from pytube import YouTube
|
16 |
+
# import replicate
|
17 |
+
|
18 |
+
DESCRIPTION = """
|
19 |
+
<div class="max-w-full overflow-auto">
|
20 |
+
<table>
|
21 |
+
<thead>
|
22 |
+
<tr>
|
23 |
+
<th>Model</th>
|
24 |
+
<th>Llama2</th>
|
25 |
+
<th>Llama2-hf</th>
|
26 |
+
<th>Llama2-chat</th>
|
27 |
+
<th>Llama2-chat-hf</th>
|
28 |
+
</tr>
|
29 |
+
</thead>
|
30 |
+
<tbody>
|
31 |
+
<tr>
|
32 |
+
<td>7B</td>
|
33 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-7b">Link</a></td>
|
34 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-7b-hf">Link</a></td>
|
35 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-7b-chat">Link</a></td>
|
36 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-7b-chat-hf">Link</a></td>
|
37 |
+
</tr>
|
38 |
+
<tr>
|
39 |
+
<td>13B</td>
|
40 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-13b">Link</a></td>
|
41 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-13b-hf">Link</a></td>
|
42 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-13b-chat">Link</a></td>
|
43 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-13b-chat-hf">Link</a></td>
|
44 |
+
</tr>
|
45 |
+
<tr>
|
46 |
+
<td>70B</td>
|
47 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-70b">Link</a></td>
|
48 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-70b-hf">Link</a></td>
|
49 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-70b-chat">Link</a></td>
|
50 |
+
<td><a rel="noopener nofollow" href="https://huggingface.co/meta-llama/Llama-2-70b-chat-hf">Link</a></td>
|
51 |
+
</tr>
|
52 |
+
</tbody>
|
53 |
+
</table>
|
54 |
+
</div>
|
55 |
+
openai/whisper-large-v3
|
56 |
+
"""
|
57 |
+
|
58 |
+
models = {
|
59 |
+
"Llama2-70b": {
|
60 |
+
"model_link": "https://huggingface.co/meta-llama/Llama-2-70b",
|
61 |
+
"chat_link": "https://ysharma-explore-llamav2-with-tgi.hf.space/",
|
62 |
+
},
|
63 |
+
"Llama2-13b": {
|
64 |
+
"model_link": "https://huggingface.co/meta-llama/Llama-2-13b",
|
65 |
+
"chat_link": "https://huggingface-projects-llama-2-13b-chat.hf.space/",
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
DESCRIPTION = """
|
70 |
+
Welcome to the **YouTube Video Chatbot** powered by Llama-2 models. Here's what you can do:
|
71 |
+
- **Transcribe & Understand**: Provide any YouTube video URL, and our system will transcribe it. Our advanced NLP model will then understand the content, ready to answer your questions.
|
72 |
+
- **Ask Anything**: Based on the video's content, ask any question, and get instant, context-aware answers.
|
73 |
+
To get started, simply paste a YouTube video URL and select a model in the sidebar, then start chatting with the model about the video's content. Enjoy the experience!
|
74 |
+
"""
|
75 |
+
st.title("YouTube Video Chatbot")
|
76 |
+
st.markdown(DESCRIPTION)
|
77 |
+
|
78 |
+
def get_video_title(youtube_url: str) -> str:
|
79 |
+
yt = YouTube(youtube_url)
|
80 |
+
embed_url = f"https://www.youtube.com/embed/{yt.video_id}"
|
81 |
+
embed_html = f'<iframe src="{embed_url}" frameborder="0" allowfullscreen></iframe>'
|
82 |
+
return yt.title, embed_html
|
83 |
+
|
84 |
+
def transcribe_video(youtube_url: str, path: str) -> List[Document]:
|
85 |
+
"""
|
86 |
+
Transcribe a video and return its content as a Document.
|
87 |
+
"""
|
88 |
+
logging.info(f"Transcribing video: {youtube_url}")
|
89 |
+
client = Client("https://sanchit-gandhi-whisper-large-v2.hf.space/")
|
90 |
+
result = client.predict(
|
91 |
+
youtube_url,
|
92 |
+
"transcribe",
|
93 |
+
api_name="/predict_2"
|
94 |
+
)
|
95 |
+
return [Document(page_content=result[1], metadata=dict(page=1))]
|
96 |
+
|
97 |
+
# def predict(message: str, system_prompt: str = '', temperature: float = 0.7, max_new_tokens: int = 1024,
|
98 |
+
# topp: float = 0.5, repetition_penalty: float = 1.2) -> Any:
|
99 |
+
# """
|
100 |
+
# Predict a response using a client.
|
101 |
+
# """
|
102 |
+
# client = Client("https://osanseviero-mistral-super-fast.hf.space/")
|
103 |
+
# response = client.predict(
|
104 |
+
# message,
|
105 |
+
# temperature,
|
106 |
+
# max_new_tokens,
|
107 |
+
# topp,
|
108 |
+
# repetition_penalty,
|
109 |
+
# api_name="/chat"
|
110 |
+
# )
|
111 |
+
# return response
|
112 |
+
|
113 |
+
def predict(input, images = []):
|
114 |
+
client = Client("https://roboflow-gemini.hf.space/--replicas/bkd57/")
|
115 |
+
result = client.predict(
|
116 |
+
None,
|
117 |
+
images,
|
118 |
+
0.4,
|
119 |
+
2048,
|
120 |
+
"",
|
121 |
+
32,
|
122 |
+
1,
|
123 |
+
[[input,None]],
|
124 |
+
api_name="/bot"
|
125 |
+
)
|
126 |
+
return result[0][1]
|
127 |
+
|
128 |
+
|
129 |
+
PATH = os.path.join(os.path.expanduser("~"), "Data")
|
130 |
+
|
131 |
+
def initialize_session_state():
|
132 |
+
if "youtube_url" not in st.session_state:
|
133 |
+
st.session_state.youtube_url = ""
|
134 |
+
if "model_choice" not in st.session_state:
|
135 |
+
st.session_state.model_choice = "Llama2-70b"
|
136 |
+
if "setup_done" not in st.session_state:
|
137 |
+
st.session_state.setup_done = False
|
138 |
+
if "doneYoutubeurl" not in st.session_state:
|
139 |
+
st.session_state.doneYoutubeurl = ""
|
140 |
+
|
141 |
+
def sidebar():
|
142 |
+
with st.sidebar:
|
143 |
+
st.markdown("# πΈ **Support our project**")
|
144 |
+
st.markdown("This money would be used for paying for API and supporting our team.")
|
145 |
+
st.markdown("[π Link](https://send.monobank.ua/jar/4mvqDivxmP)")
|
146 |
+
|
147 |
+
st.markdown("")
|
148 |
+
|
149 |
+
st.markdown("# Enter the YouTube Video URL belowπ")
|
150 |
+
st.session_state.youtube_url = st.text_input("YouTube Video URL:")
|
151 |
+
|
152 |
+
model_choice = st.radio("Choose a Model:", list(models.keys()))
|
153 |
+
st.session_state.model_choice = model_choice
|
154 |
+
|
155 |
+
if st.session_state.youtube_url:
|
156 |
+
# Get the video title
|
157 |
+
video_title, embed_html = get_video_title(st.session_state.youtube_url)
|
158 |
+
st.markdown(f"### {video_title}")
|
159 |
+
|
160 |
+
# Embed the video
|
161 |
+
st.markdown(embed_html, unsafe_allow_html=True)
|
162 |
+
sidebar()
|
163 |
+
|
164 |
+
initialize_session_state()
|
165 |
+
|
166 |
+
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
|
167 |
+
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-l6-v2")
|
168 |
+
|
169 |
+
prompt = PromptTemplate(
|
170 |
+
template="""Given the context about a video. Answer the user in a friendly and precise manner.
|
171 |
+
Context: {context}
|
172 |
+
Human: {question}
|
173 |
+
AI:""",
|
174 |
+
input_variables=["context", "question"]
|
175 |
+
)
|
176 |
+
|
177 |
+
class LlamaLLM(LLM):
|
178 |
+
"""
|
179 |
+
Custom LLM class.
|
180 |
+
"""
|
181 |
+
|
182 |
+
@property
|
183 |
+
def _llm_type(self) -> str:
|
184 |
+
return "custom"
|
185 |
+
|
186 |
+
def _call(self, prompt: str, stop: Optional[List[str]] = None, run_manager: Optional[CallbackManagerForLLMRun] = None) -> str:
|
187 |
+
model_link = models[st.session_state.model_choice]["chat_link"]
|
188 |
+
response = predict(prompt)
|
189 |
+
return response
|
190 |
+
|
191 |
+
@property
|
192 |
+
def _identifying_params(self) -> Mapping[str, Any]:
|
193 |
+
"""Get the identifying parameters."""
|
194 |
+
return {}
|
195 |
+
|
196 |
+
# Check if a new YouTube URL is provided
|
197 |
+
if st.session_state.youtube_url != st.session_state.doneYoutubeurl:
|
198 |
+
st.session_state.setup_done = False
|
199 |
+
|
200 |
+
if st.session_state.youtube_url and not st.session_state.setup_done:
|
201 |
+
with st.status("Transcribing video..."):
|
202 |
+
data = transcribe_video(st.session_state.youtube_url, PATH)
|
203 |
+
|
204 |
+
with st.status("Running Embeddings..."):
|
205 |
+
docs = text_splitter.split_documents(data)
|
206 |
+
|
207 |
+
docsearch = FAISS.from_documents(docs, embeddings)
|
208 |
+
retriever = docsearch.as_retriever()
|
209 |
+
retriever.search_kwargs["distance_metric"] = "cos"
|
210 |
+
retriever.search_kwargs["k"] = 4
|
211 |
+
with st.status("Running RetrievalQA..."):
|
212 |
+
llama_instance = LlamaLLM()
|
213 |
+
st.session_state.qa = RetrievalQA.from_chain_type(llm=llama_instance, chain_type="stuff", retriever=retriever, chain_type_kwargs={"prompt": prompt})
|
214 |
+
|
215 |
+
st.session_state.doneYoutubeurl = st.session_state.youtube_url
|
216 |
+
st.session_state.setup_done = True # Mark the setup as done for this URL
|
217 |
+
|
218 |
+
if "messages" not in st.session_state:
|
219 |
+
st.session_state.messages = []
|
220 |
+
|
221 |
+
for message in st.session_state.messages:
|
222 |
+
with st.chat_message(message["role"], avatar=("π§βπ»" if message["role"] == "human" else "π¦")):
|
223 |
+
st.markdown(message["content"])
|
224 |
+
|
225 |
+
textinput = st.chat_input("Ask anything about the video...")
|
226 |
+
|
227 |
+
if prompt := textinput:
|
228 |
+
st.chat_message("human", avatar="π§βπ»").markdown(prompt)
|
229 |
+
st.session_state.messages.append({"role": "human", "content": prompt})
|
230 |
+
with st.status("Requesting Client..."):
|
231 |
+
video_title, _ = get_video_title(st.session_state.youtube_url)
|
232 |
+
additional_context = f"Given the context about a video titled '{video_title}' available at '{st.session_state.youtube_url}'."
|
233 |
+
response = st.session_state.qa.run(prompt + " " + additional_context)
|
234 |
+
with st.chat_message("assistant", avatar="π¦"):
|
235 |
+
st.markdown(response)
|
236 |
+
# Add assistant response to chat history
|
237 |
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio-client
|
2 |
+
langchain
|
3 |
+
sentence-transformers
|
4 |
+
faiss-cpu
|
5 |
+
pytube
|