File size: 7,684 Bytes
c7759ea
 
 
bfbbbea
c7759ea
00e285e
 
 
c7759ea
00e285e
4c992c2
00e285e
c7759ea
dfb781f
0b3012a
a65c301
8e1c60e
bcf5794
a1543a8
a65c301
bdf3e70
a1543a8
c7759ea
a65c301
966d5eb
e9f9106
bcf5794
09ca515
86e8aa3
d959e7d
6b0a5a8
b1cf10f
776965a
5933b37
9b85101
a65c301
3f2bb99
b817f2f
a65c301
09ca515
9b85101
 
b87318d
e991c57
b87318d
a40632d
173a2dc
82dcd78
173a2dc
 
 
 
 
 
 
 
 
0455ffc
 
 
9b85101
0a667af
82dcd78
46920c2
 
ccc3d18
9b85101
0a667af
9b85101
 
57298a6
14afe69
96dfd33
 
 
 
2dbace5
46920c2
 
2f6ac46
 
96dfd33
57298a6
e14f3cb
57298a6
82dcd78
32beee3
57298a6
9ba0986
57298a6
 
35df5ff
00e285e
f01a006
 
5330115
f01a006
a52308c
c7759ea
 
d97af7d
aeb447f
c7759ea
 
dd2f155
4b13329
f0bdafb
e14f3cb
 
2f1a468
c7759ea
 
c94b771
e14f3cb
 
cc486b1
 
0a9c38b
 
 
57298a6
0a9c38b
49a1ca0
57298a6
a152ff1
0f7ad5c
c7759ea
3776d77
a152ff1
9675192
cc486b1
 
0f7ad5c
cc486b1
 
bcc4d5e
 
 
 
e14f3cb
 
 
 
c7759ea
 
c94b771
e14f3cb
 
c94b771
5933b37
c94b771
 
c7759ea
bc1c38e
c7759ea
b87318d
 
 
4df0f2d
5933b37
b87318d
0455ffc
173a2dc
0455ffc
 
 
 
f17a9c5
173a2dc
 
0455ffc
 
f547f69
52589e7
 
c7759ea
52589e7
c7759ea
 
8e1c60e
 
 
 
173a2dc
b37ee8c
 
d0538e8
8e1c60e
 
 
 
 
 
 
 
b817f2f
 
 
0455ffc
8e1c60e
c7759ea
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
###########################
# UI for Meeting RAG Q&A. #
###########################

##################### Imports #####################
import uuid
import threading

import gradio as gr
import spaces
import os

from utilities.setup import get_files

from connections.pinecone import PineconeConnector
from connections.model import InferencePipeline

from services.embed_service.embed import EmbeddingService
from services.embed_service.utils import VTTTranscriptLoader, clean_text
from services.qa_service.qna import QAService


#################### Functions ####################
@spaces.GPU
def process_transcripts(files, context, session_key):
    
    with EmbeddingService(conf, 
                          pinecone=pc_connector,
                          session_key=session_key) as e:
        f = e.run(files)
    return "Completed Loading Data"

@spaces.GPU(duration=120)
def retrieve_answer(question, goals, session_key):
    keycheck = namespace_check(session_key)
    with QAService(conf, 
                   pinecone=pc_connector, 
                   model_pipeline=pipelines, 
                   question=question, 
                   goals=goals,
                   session_key=session_key,
                   keycheck=keycheck) as q:
        f, c = q.run()

    return f, c

def return_stored_transcripts(conf):
    print("Returning stored transcript")
    store = conf["layout"]["stored_meetings"]
    meeting_paths = os.listdir(store)
    combined_paths = [store + i for i in meeting_paths]
    loader = VTTTranscriptLoader(combined_paths)
    results = loader.load()
    meetings = []
    for d in range(len(results)):
        meetings.append(clean_text(results[d].text))
    return meetings, meeting_paths



def namespace_check(arg):
    """This piece of code should be moved to the backend QA Service"""
    print("Checking namespace")
    pc = pc_connector._connection()
    index = pc.Index(conf["embeddings"]["index_name"])
    stats = index.describe_index_stats()
    name_list = stats['namespaces'].keys()
    name_list = [item for item in name_list if item != '']
    return arg in name_list


def drop_namespace(arg):
    if conf["embeddings"]["override"]:
        pass
        print("Maintained Namespace: " + conf["embeddings"]["demo_namespace"])
    else:
        namecheck = namespace_check(arg)
        if namecheck:
            pc = pc_connector._connection()
            index = pc.Index(conf["embeddings"]["index_name"])
            index.delete(namespace=arg, delete_all=True)
        print("Deleted namespace: " + arg)


def generate_key():
    print("Generating key")
    unique_key = str(uuid.uuid1())
    unique_key = 'User_' + unique_key
    timer = threading.Timer(conf["session"]["user_timeout"], drop_namespace, [unique_key]) 
    timer.start()
    
    return unique_key
                                                          

def b_clicked(o):
    return gr.Button(interactive=True)
    

##################### Process #####################
def main(conf):
    with gr.Blocks(theme=gr.themes.Soft(text_size="lg")) as demo:
    
        # Main page
        with gr.TabItem(conf["layout"]["page_names"][0]):
            gr.Markdown("# 🤝 Multi-Meeting Q&A RAG")
            gr.Markdown("![](file/emoji_meeting_resized.png)")
            gr.Markdown(get_files.load_markdown_file(conf["layout"]["about"]))


        
        # User config page
        with gr.TabItem(conf["layout"]["page_names"][1]):
            gr.Markdown("# 📁 Upload your own meeting docs")
            gr.Markdown("""Be sure to retain your session key. This key is your ID to 
                           your stored documents and is live for 1 hour after generation""")
            create_unique_key = gr.Button("Generate session key")
            output_unique_key = gr.Textbox(label="Copy key",
                                           interactive=True ,
                                           show_copy_button=True, 
                                           show_label=True)
            create_unique_key.click(fn=generate_key,
                                    outputs=output_unique_key)


            ### This should not be visible until key is generated.
            
            load_file = gr.UploadButton(label="Upload Transcript (.vtt)", 
                                                     file_types=conf["session"]["filetypes"],
                                        file_count='multiple', interactive=False)
            repository = gr.Textbox(label="Progress", value="Waiting for load...", visible=True)
            gr.Markdown("## Additional context you want to provide?", visible=False)
            gr.Markdown("Try to keep this portion as concise as possible.", visible=False)            
            goals = gr.Textbox(label="Analysis Goals",
                               value=conf["defaults"]["goals"],
                               visible=False) # not incorporated yet. Will be with Q&A.
            load_file.upload(process_transcripts, [load_file, goals, output_unique_key], repository)
            create_unique_key.click(fn=b_clicked,
                                    inputs=create_unique_key,
                                    outputs=load_file)

        
        
        
        # Meeting Question & Answer Page
        with gr.TabItem(conf["layout"]["page_names"][2]):
            gr.Markdown("# ❓ Query meeting docs")
            gr.Markdown("""Paste session key below to query your own personal docs. Otherwise, skip and ask a question to analyze the pre-stored meetings.
                           After asking the question, an answer will populate along with the meeting snippets retrieved.""")
            session_key = gr.Textbox(label="Session key here",
                                     value="")

            gr.Markdown("### Query")
            question = gr.Textbox(label="Ask a Question",
                                  value=conf["defaults"]["question"])
            ask_button = gr.Button("Ask!")
            model_output = gr.Markdown("### Answer")
            context_output = gr.components.Textbox(label="Retrieved Context")
            
            ask_button.click(fn=retrieve_answer,
                             inputs=[question, goals, session_key],
                             outputs=[model_output,context_output])

        with gr.TabItem(conf["layout"]["page_names"][3]):
            gr.Markdown("# 👀 View stored meeting docs")
            gr.Markdown("""These are just some example meeting docs of very clean, brief synthetic meetings generated by LLMs.
                           Compare these to the demo outputs you get when you don't enter a token to see what contex was retrieved.""")
            
            for i in range(len(meeting_paths)):
                with gr.Accordion(meeting_paths[i], open=False):
                    gr.Textbox(value=meetings[i],lines=10)
            
        
        demo.launch(server_name="0.0.0.0", allowed_paths=["/"])


##################### Execute #####################
if __name__ == "__main__":
    # Get config
    conf = get_files.json_cfg()
    
    # Get keys
    keys = get_files.get_keys()

    # Get stored meetings
    meetings, meeting_paths = return_stored_transcripts(conf)
    
    
    # initialize pinecone connector
    pc_connector = PineconeConnector(
        api_key=keys["pinecone"],
        index_name=conf["embeddings"]["index_name"],
        embedding=conf["embeddings"]["embedding"],
    )

    # initialize model connector
    pipelines = InferencePipeline(conf,
                                  api_key=keys["huggingface"]
                                  )
    
    # run main
    main(conf)