File size: 7,574 Bytes
00061b3
fce4adb
3dc3050
a75f7b2
 
 
 
 
 
 
7aa4aab
 
 
 
3dc3050
a75f7b2
e90c5c4
a75f7b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fce4adb
a75f7b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fce4adb
 
 
 
 
 
 
 
 
 
 
a75f7b2
 
fce4adb
 
 
 
7aa4aab
1bf49b9
7aa4aab
 
 
138db2f
7aa4aab
138db2f
7aa4aab
 
 
 
 
 
77d149f
 
138db2f
77d149f
 
7aa4aab
 
 
 
 
 
 
 
138db2f
7aa4aab
138db2f
 
 
 
7aa4aab
 
 
 
 
 
 
 
 
fce4adb
138db2f
 
 
 
 
 
 
 
 
 
 
b6700b1
 
 
 
 
 
 
 
f9109d5
76dd0bb
b6700b1
138db2f
 
a96a463
fcb6493
 
31be6d7
138db2f
 
5ce9a64
b6700b1
 
 
 
 
 
 
 
 
138db2f
b6700b1
138db2f
fce4adb
 
 
 
4947947
fce4adb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3dc3050
 
fce4adb
a75f7b2
 
fce4adb
 
138db2f
eae93b4
fce4adb
3dc3050
7aa4aab
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
import gradio as gr
import os
import time
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, StoppingCriteriaList, TextIteratorStreamer, pipeline
from threading import Thread
from peft import PeftModel
import whisperx
import gc 
import pandas as pd
from transformers.utils import logging

logging.set_verbosity_info()
logger = logging.get_logger("transformers")

device = 'cuda' if torch.cuda.is_available() else 'cpu'
q_ctxt, query, ctxt_type = None, None, None


##################################################################
############################## Text ##############################

phi_base_model = AutoModelForCausalLM.from_pretrained(
    'microsoft/phi-2',
    low_cpu_mem_usage=True,
    return_dict=True,
    torch_dtype=torch.float32,
    trust_remote_code=True
)

phi_new_model = "models/phi_adapter"
phi_model = PeftModel.from_pretrained(phi_base_model, phi_new_model)
phi_model = phi_model.merge_and_unload().to(device)

tokenizer = AutoTokenizer.from_pretrained('microsoft/phi-2')
tokenizer.pad_token = tokenizer.unk_token

###################################################################

############################## Audio ##############################

# 1. Transcribe with original whisper (batched)
audio_model_name = "small" #"large-v2"
audio_compute_type = "int8" if device == "cpu" else "float16" #"float16" # change to "int8" if low on GPU mem (may reduce accuracy)
audio_model = whisperx.load_model(audio_model_name, device, compute_type=audio_compute_type)

def get_audio_context(audio_file):
  audio = whisperx.load_audio(audio_file)
  batch_size = 4 if device == "cpu" else 16 #16 # reduce if low on GPU mem
  result = audio_model.transcribe(audio, batch_size=batch_size)
  # print(result["segments"]) # before alignment
  context = " ".join(pd.DataFrame(result["segments"])["text"])

  return context

###################################################################

#-----------------------------------------------------#

# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.

def print_like_dislike(x: gr.LikeData):
    print(x.index, x.value, x.liked)


def add_text(history, text):
    history = history + [(text, None)]
    return history, gr.Textbox(value="", interactive=False)


def add_file(history, file):
    context = get_audio_context(file)
    history = history + [((file.name,context), None)]
    return history


def bot(history):
    try:
        global q_ctxt, query, ctxt_type
        if len(history) > 0 and isinstance(history[-1][0], tuple):
            ctxt_type = "audio"
            q_ctxt = get_audio_context(history[-1][0][0])
            response = "**Based on the given context:** \n" + q_ctxt + "\n. **What do you want to know ?**"
        elif len(history) > 0 and isinstance(history[-1][0],str) and len(history[-1][0].strip()) > 0:
            logger.info("Last History:" + history[-1][0])
            if ctxt_type == "audio" and "[INST]" not in history[-1][0]:
                query = history[-1][0]
                input_text = q_ctxt + query
            elif "[INST]" in history[-1][0]:
                q_ctxt = history[-1][0].split("[INST]")[0]
                query = history[-1][0].split("[INST]")[-1]
                # input_text = history[-1][0].replace("[INST]"," ")
                input_text = q_ctxt + query
                ctxt_type = "text"
            else:
                input_text = q_ctxt + query
            input_tokens = tokenizer.encode(input_text)
            input_ids = torch.tensor(input_tokens, dtype=torch.int32).unsqueeze(0).to(device)
            inputs_embeds = phi_model.get_input_embeddings()(input_ids)
            out = phi_model.generate(inputs_embeds=inputs_embeds, min_new_tokens=10, max_new_tokens=50, bos_token_id=tokenizer.bos_token_id)
            response = tokenizer.decode(out[0], skip_special_tokens=True)
        else:
            ctxt_type = None
            q_ctxt = None
            query = None
            response = "Please ask your query or upload an audio/video to ask query"
        
        logger.info(f"Context: {q_ctxt}")
        logger.info(f"Query: {query}")
        logger.info(f"Context Type: {ctxt_type}")

        history[-1][1] = ""
        for character in response:
            history[-1][1] += character
            time.sleep(0.05)
            yield history
    except Exception as e:
        logger.error(e)
        return e

def reset():
    global q_ctxt, query, ctxt_type
    q_ctxt, query, ctxt_type = None, None, None

    return {
        chatbot: None
    }

## Style

title_markdown = ("""
<div align="center" background-color="#8bd4e2">
    <h1 align="center"><a href="https://github.com/garima-mahato/MuMoLLM"><img src="https://raw.githubusercontent.com/garima-mahato/MuMoLLM/main/images/mumo_logo.png", alt="MuMo" border="0" style="margin: 0 auto; height: 200px;" /></a> </h1>
    <h2 align="center"> MuMo: Multi-Modal Chatter </h2>
    <h5 align="center"> If you like this project, please give a star ✨ on Github.  </h2>
    <h5 align="center"> Note: This version is not multilingual demo </h5>
    <div align="center">
        <div style="display:flex; gap: 0.25rem;" align="center">
            <a href='https://github.com/garima-mahato/MuMoLLM'><img src='https://img.shields.io/badge/Github-Code-blue'></a>
            <a href='https://github.com/garima-mahato/MuMoLLM/stargazers'><img src='https://img.shields.io/github/stars/garima-mahato/MuMoLLM.svg?style=social'></a>
            <a href='https://www.youtube.com/watch?v=0DCZLFmnV0s'><img src='https://img.shields.io/badge/youtube-badge'></a>
        </div>
    </div>
</div>
\n**Notice**: This runs on CPU and may take time in responding.\n
**We recommend only one image or video per conversation session.** \n
If you want to start chatting with new images or videos, we recommend you to **CLEAR** the history to restart.\n
**For Text QnA: Please separate context and query by [INST]**
""")

css = """
pre {
    white-space: pre-wrap;       /* Since CSS 2.1 */
    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
    white-space: -pre-wrap;      /* Opera 4-6 */
    white-space: -o-pre-wrap;    /* Opera 7 */
    word-wrap: break-word;       /* Internet Explorer 5.5+ */
}
"""

## Gradio App Set-up
with gr.Blocks(title="MuMo", css=css) as demo:
    gr.Markdown(title_markdown)
    chatbot = gr.Chatbot(
        [],
        elem_id="chatbot",
        bubble_full_width=False,
        #avatar_images=("https://raw.githubusercontent.com/garima-mahato/MuMoLLM/main/images/user_avatar.png", "https://raw.githubusercontent.com/garima-mahato/MuMoLLM/main/images/mumo_avatar.png"),
    )

    with gr.Row():
        txt = gr.Textbox(
            scale=4,
            show_label=False,
            placeholder="Enter text and press enter, or upload an image",
            container=False,
        )
        btn = gr.UploadButton("📁", file_types=["image", "video", "audio"])

    txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(
        bot, chatbot, chatbot, api_name="bot_response"
    )
    txt_msg.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False)
    file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(
        bot, chatbot, chatbot
    )

    with gr.Row():
        clear = gr.Button("Clear")
    chatbot.like(print_like_dislike, None, None)

    clear.click(reset, None, chatbot, queue=False)


demo.queue()
demo.launch(debug=True)