Spaces:
Runtime error
Runtime error
import os | |
import logging | |
from typing import Any, List, Mapping, Optional | |
from gradio_client import Client | |
from langchain.schema import Document | |
from langchain.text_splitter import RecursiveCharacterTextSplitter | |
from langchain.vectorstores import FAISS | |
from langchain.embeddings.huggingface import HuggingFaceEmbeddings | |
from langchain.callbacks.manager import CallbackManagerForLLMRun | |
from langchain.llms.base import LLM | |
from langchain.chains import RetrievalQA | |
import streamlit as st | |
from pytube import YouTube | |
models = '''| Model | Llama2 | Llama2-hf | Llama2-chat | Llama2-chat-hf | | |
|---|---|---|---|---| | |
| 70B | [Link](https://huggingface.co/meta-llama/Llama-2-70b) | [Link](https://huggingface.co/meta-llama/Llama-2-70b-hf) | [Link](https://huggingface.co/meta-llama/Llama-2-70b-chat) | [Link](https://huggingface.co/meta-llama/Llama-2-70b-chat-hf) | | |
---''' | |
DESCRIPTION = """ | |
Welcome to the **YouTube Video Chatbot** powered by the state-of-the-art Llama-2-70b model. Here's what you can do: | |
- **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. | |
- **Ask Anything**: Based on the video's content, ask any question, and get instant, context-aware answers. | |
To get started, simply paste a YouTube video URL in the sidebar and start chatting with the model about the video's content. Enjoy the experience! | |
""" | |
st.title("YouTube Video Chatbot") | |
st.markdown(DESCRIPTION) | |
def get_video_title(youtube_url: str) -> str: | |
yt = YouTube(youtube_url) | |
return yt.title | |
def transcribe_video(youtube_url: str, path: str) -> List[Document]: | |
""" | |
Transcribe a video and return its content as a Document. | |
""" | |
logging.info(f"Transcribing video: {youtube_url}") | |
client = Client("https://sanchit-gandhi-whisper-jax.hf.space/") | |
result = client.predict(youtube_url, "translate", True, fn_index=7) | |
return [Document(page_content=result[1], metadata=dict(page=1))] | |
def predict(message: str, system_prompt: str = '', temperature: float = 0.7, max_new_tokens: int = 4096, | |
topp: float = 0.5, repetition_penalty: float = 1.2) -> Any: | |
""" | |
Predict a response using a client. | |
""" | |
client = Client("https://ysharma-explore-llamav2-with-tgi.hf.space/") | |
response = client.predict( | |
message, | |
system_prompt, | |
temperature, | |
max_new_tokens, | |
topp, | |
repetition_penalty, | |
api_name="/chat_1" | |
) | |
return response | |
class LlamaLLM(LLM): | |
""" | |
Custom LLM class. | |
""" | |
def _llm_type(self) -> str: | |
return "custom" | |
def _call(self, prompt: str, stop: Optional[List[str]] = None, | |
run_manager: Optional[CallbackManagerForLLMRun] = None) -> str: | |
response = predict(prompt) | |
return response | |
def _identifying_params(self) -> Mapping[str, Any]: | |
"""Get the identifying parameters.""" | |
return {} | |
PATH = os.path.join(os.path.expanduser("~"), "Data") | |
def initialize_session_state(): | |
if "youtube_url" not in st.session_state: | |
st.session_state.youtube_url = "" | |
if "setup_done" not in st.session_state: # Initialize the setup_done flag | |
st.session_state.setup_done = False | |
if "doneYoutubeurl" not in st.session_state: | |
st.session_state.doneYoutubeurl = "" | |
def sidebar(): | |
def sidebar(): | |
with st.sidebar: | |
st.markdown("Enter the YouTube Video URL below🔗\n") | |
st.session_state.youtube_url = st.text_input("YouTube Video URL:") | |
if st.session_state.youtube_url: | |
# Get the video title | |
video_title = get_video_title(st.session_state.youtube_url) | |
st.markdown(f"### {video_title}") | |
# Embed the video | |
st.markdown( | |
f'<iframe min-width="300" min-height="200" src="{st.session_state.youtube_url.replace("watch?v=", "embed/")}" frameborder="0" allowfullscreen></iframe>', | |
unsafe_allow_html=True | |
) | |
sidebar() | |
initialize_session_state() | |
# Check if a new YouTube URL is provided | |
if st.session_state.youtube_url != st.session_state.doneYoutubeurl: | |
st.session_state.setup_done = False | |
if st.session_state.youtube_url and not st.session_state.setup_done: | |
with st.status("Transcribing video..."): | |
data = transcribe_video(st.session_state.youtube_url, PATH) | |
with st.status("Running Embeddings..."): | |
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0) | |
docs = text_splitter.split_documents(data) | |
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-l6-v2") | |
docsearch = FAISS.from_documents(docs, embeddings) | |
retriever = docsearch.as_retriever() | |
retriever.search_kwargs['distance_metric'] = 'cos' | |
retriever.search_kwargs['k'] = 4 | |
with st.status("Running RetrievalQA..."): | |
llama_instance = LlamaLLM() | |
st.session_state.qa = RetrievalQA.from_chain_type(llm=llama_instance, chain_type="stuff", retriever=retriever) | |
st.session_state.doneYoutubeurl = st.session_state.youtube_url | |
st.session_state.doneYoutubeurl = st.session_state.youtube_url | |
st.session_state.setup_done = True # Mark the setup as done for this URL | |
if "messages" not in st.session_state: | |
st.session_state.messages = [] | |
for message in st.session_state.messages: | |
with st.chat_message(message["role"], avatar=("🧑💻" if message["role"] == 'human' else '🦙')): | |
st.markdown(message["content"]) | |
textinput = st.chat_input("Ask LLama-2-70b anything about the video...") | |
if prompt := textinput: | |
st.chat_message("human",avatar = "🧑💻").markdown(prompt) | |
st.session_state.messages.append({"role": "human", "content": prompt}) | |
with st.status("Requesting Client..."): | |
response = st.session_state.qa.run(prompt) | |
with st.chat_message("assistant", avatar='🦙'): | |
st.markdown(response) | |
# Add assistant response to chat history | |
st.session_state.messages.append({"role": "assistant", "content": response}) |