ziffir commited on
Commit
61a13fc
β€’
1 Parent(s): 79964b2

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +5 -7
  2. app.py +237 -0
  3. requirements.txt +5 -0
README.md CHANGED
@@ -1,12 +1,10 @@
1
  ---
2
- title: VYouTubeVideoChatRobot
3
- emoji: πŸ‘
4
- colorFrom: purple
5
  colorTo: blue
6
  sdk: streamlit
7
- sdk_version: 1.29.0
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