File size: 5,740 Bytes
d17095f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
455e88a
d17095f
 
 
 
 
 
 
 
 
 
 
 
 
 
455e88a
 
 
 
 
 
 
d17095f
 
 
 
 
 
 
 
 
 
 
 
455e88a
d17095f
455e88a
d17095f
 
455e88a
 
 
 
 
 
 
 
d17095f
 
 
455e88a
 
 
 
 
 
 
 
 
 
 
d17095f
 
455e88a
 
 
 
 
 
 
 
 
d17095f
ce9c45f
d17095f
 
 
455e88a
d17095f
 
 
455e88a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d17095f
455e88a
 
 
d17095f
 
455e88a
 
 
 
 
 
d17095f
455e88a
 
 
 
 
 
d17095f
455e88a
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
__import__('pysqlite3')
import sys
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')

import streamlit as st
from PIL import Image
import whisper
import torch
import os
from streamlit_lottie import st_lottie 
from pytube import YouTube
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import DataFrameLoader
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQAWithSourcesChain
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.llms import OpenAI
import pandas as pd
import requests

st.set_page_config(layout="centered", page_title="Youtube QnA")

hide_streamlit_style = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True) 

def load_lottieurl(url: str):
    try:
        r = requests.get(url)
        if r.status_code != 200:
            return None
        return r.json()
    except Exception as e:
        st.error(f"Failed to load Lottie animation: {e}")
        return None
    
url_lottie1 = "https://lottie.host/d860aaf2-a646-42f2-8a51-3efe3be59bf2/tpZB5YYkuT.json"
url_lottie2 = "https://lottie.host/93dcafc4-8531-4406-891c-89c28e4f76e1/lWpokVrjB9.json"
lottie_hello1 = load_lottieurl(url_lottie2)
place1 = st.empty()

logo1 = "aai_white.png"
logo2 = "alphaGPT-2k.png"
logo3 = "banner.png"
with place1.container():
    st.header("Youtube Question Answering Bot")
    anima1, anima2 = st.columns([1,1])
    with anima1:
        st.image("logo.png", width=300, use_column_width=True)
    with anima2:
        st_lottie(
            lottie_hello1,
            speed=1,
            reverse=False,
            loop=True,
            quality="high",
            height=250,
            width=250,
            key=None,
        )

def extract_and_save_audio(video_URL, destination, final_filename):
    try:
        video = YouTube(video_URL)
        audio = video.streams.filter(only_audio=True).first()
        output = audio.download(output_path=destination)
        _, ext = os.path.splitext(output)
        new_file = final_filename + '.mp3'
        os.rename(output, new_file)
        return new_file
    except Exception as e:
        st.error(f"Failed to extract audio: {e}")
        return None

def chunk_clips(transcription, clip_size):
    texts = []
    sources = []
    for i in range(0, len(transcription), clip_size):
        clip_df = transcription.iloc[i:i+clip_size, :]
        text = " ".join(clip_df['text'].to_list())
        source = str(round(clip_df.iloc[0]['start']/60, 2)) + " - " + str(round(clip_df.iloc[-1]['end']/60, 2)) + " min"
        texts.append(text)
        sources.append(source)
    return [texts, sources]

openai_api_key = st.sidebar.text_input("OpenAI API Key", type="password")
if not openai_api_key:
    st.info("Please add your OpenAI API key to continue.")
    st.stop()

state = st.session_state
site = st.text_input("Enter your URL here")
if st.button("Build Model"):
    if site is None:
        st.info("Enter URL to Build QnA Bot")
    elif site:
        try:
            my_bar = st.progress(0, text="Fetching the video. Please wait.")
            device = "cuda" if torch.cuda.is_available() else "cpu"
            whisper_model = whisper.load_model("base", device=device)
            video_URL = site
            destination = "."
            final_filename = "AlphaGPT"
            audio_file = extract_and_save_audio(video_URL, destination, final_filename)
            if audio_file is None:
                st.error("Failed to extract audio. Please try again with a different URL.")
                st.stop()

            my_bar.progress(50, text="Transcribing the video.")
            result = whisper_model.transcribe(audio_file, fp16=False, language='English')
            transcription = pd.DataFrame(result['segments'])
            chunks = chunk_clips(transcription, 50)
            documents = chunks[0]
            sources = chunks[1]

            my_bar.progress(75, text="Building QnA model.")
            embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
            vStore = Chroma.from_texts(documents, embeddings, metadatas=[{"source": s} for s in sources])
            model_name = "gpt-3.5-turbo"
            retriever = vStore.as_retriever()
            retriever.search_kwargs = {'k': 2}
            llm = OpenAI(model_name=model_name, openai_api_key=openai_api_key)
            model = RetrievalQAWithSourcesChain.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever)

            my_bar.progress(100, text="Model is ready.")
            st.session_state['crawling'] = True
            st.session_state['model'] = model
            st.session_state['site'] = site

        except Exception as e:
            st.error(f"An error occurred: {e}")
            st.error('Oops, crawling resulted in an error :( Please try again with a different URL.')

if site and ("crawling" in state):
    st.header("Ask your data")
    model = st.session_state['model']
    site = st.session_state['site']
    st.video(site, format="video/mp4", start_time=0)
    user_q = st.text_input("Enter your questions here")
    if st.button("Get Response"):
        try:
            with st.spinner("Model is working on it..."):
                result = model({"question": user_q}, return_only_outputs=True)
                st.subheader('Your response:')
                st.write(result["answer"])
                st.subheader('Sources:')
                st.write(result["sources"])
        except Exception as e:
            st.error(f"An error occurred: {e}")
            st.error('Oops, the GPT response resulted in an error :( Please try again with a different question.')