File size: 14,371 Bytes
fabaa3c
 
 
 
 
 
 
 
437063b
fabaa3c
 
 
 
 
 
 
 
 
1001ad3
fabaa3c
 
 
0fe027e
1001ad3
 
e9060e2
fabaa3c
43d3ba0
 
cdf9da1
 
1001ad3
 
 
 
 
33f38e0
ce441ed
 
 
cd4b4e1
ce441ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fabaa3c
 
 
 
 
 
795e26d
fabaa3c
 
 
 
795e26d
fabaa3c
 
 
 
20a8bd2
77120c6
fabaa3c
 
7b9282e
 
cc0a5b1
7b9282e
 
 
8ee9612
 
 
 
 
 
fabaa3c
 
a4c2f04
fabaa3c
 
 
 
 
 
 
 
 
 
 
795e26d
fabaa3c
 
 
 
8ee9612
fabaa3c
 
 
 
 
 
 
 
 
 
 
 
 
 
dd7d8ba
c5ecf2c
fabaa3c
dd7d8ba
fabaa3c
1c3458d
fabaa3c
dd7d8ba
 
5b3a290
0e92f07
1c3458d
0e92f07
 
fabaa3c
0e92f07
 
 
 
1c3458d
 
 
0e92f07
 
1c3458d
3736069
0e92f07
 
 
1c3458d
 
 
 
 
 
 
 
 
 
 
 
dd7d8ba
1c3458d
 
 
 
 
 
 
 
fabaa3c
 
437063b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fabaa3c
700b80f
a084afb
700b80f
1001ad3
4f3004e
 
18ba3fa
489c872
fabaa3c
437063b
5c541d7
 
 
fabaa3c
5c541d7
 
 
fabaa3c
5c541d7
aaace13
5c541d7
5e7db30
 
 
 
 
7659619
fabaa3c
1dc45a3
fabaa3c
1dc45a3
fabaa3c
1dc45a3
fabaa3c
700b80f
 
5e7db30
700b80f
 
 
 
 
 
fabaa3c
437063b
fabaa3c
700b80f
fabaa3c
1dc45a3
fabaa3c
4f3004e
1001ad3
4f3004e
 
 
1001ad3
7bbaee5
1001ad3
 
 
4f3004e
 
 
 
 
 
 
 
 
 
 
1001ad3
b38224d
eb2581c
8ee9612
1001ad3
 
 
fabaa3c
1001ad3
 
 
 
eb2581c
fabaa3c
 
 
1001ad3
fabaa3c
 
 
 
 
1001ad3
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
import os
import time
import copy
import requests
import random
from threading import Thread
from typing import List, Dict, Union
import subprocess
# Install flash attention, skipping CUDA build if necessary
subprocess.run(
    "pip install flash-attn --no-build-isolation",
    env={"FLASH_ATTENTION_SKIP_CUDA_BUILD": "TRUE"},
    shell=True,
)
import torch
import gradio as gr
from bs4 import BeautifulSoup
import datasets
from transformers import LlavaProcessor, LlavaForConditionalGeneration, TextIteratorStreamer
from huggingface_hub import InferenceClient
from PIL import Image
import spaces
from functools import lru_cache
import cv2
import re
import io  # Add this import for working with image bytes

# You can also use models that are commented below
# model_id = "llava-hf/llava-interleave-qwen-0.5b-hf"
model_id = "llava-hf/llava-interleave-qwen-7b-hf"
# model_id = "llava-hf/llava-interleave-qwen-7b-dpo-hf"
processor = LlavaProcessor.from_pretrained(model_id)
model = LlavaForConditionalGeneration.from_pretrained(model_id, torch_dtype=torch.float16, use_flash_attention_2=True, low_cpu_mem_usage=True)
model.to("cuda")
# Credit to merve for code of llava interleave qwen

def sample_frames(video_file) :
    try:
        video = cv2.VideoCapture(video_file)
        total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
        num_frames = 12
        interval = total_frames // num_frames
        frames = []
        for i in range(total_frames):
            ret, frame = video.read()
            pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            if not ret:
                continue
            if i % interval == 0:
                frames.append(pil_img)
        video.release()
        return frames
    except:
        frames=[]
        return frames
        

# Path to example images
examples_path = os.path.dirname(__file__)
EXAMPLES = [
    [
        {
            "text": "Bitcoin price live",
        }
    ],
    [
        {
            "text": "Today News about AI",
        }
    ],
    [
        {
            "text": "What unusual happens in this video.",
            "files": [f"{examples_path}/example_video/accident.gif"],
        }
    ],
    [
        {
            "text": "What's name of superhero in this clip",
            "files": [f"{examples_path}/example_video/spiderman.gif"],
        }
    ],
    [
        {
            "text": "What's written on this paper",
            "files": [f"{examples_path}/example_images/paper_with_text.png"],
        }
    ],
    [
        {
            "text": "Who are they? Tell me about both of them",
            "files": [f"{examples_path}/example_images/elon_smoking.jpg",
                      f"{examples_path}/example_images/steve_jobs.jpg", ]
        }
    ],
    [
        {
            "text": "Create five images of supercars, each in a different color.",
        }
    ],
    [
        {
            "text": "Create a Photorealistic image of the Eiffel Tower.",
        }
    ],
    [
        {
            "text": "Create an ad script for this product.",
            "files": [f"{examples_path}/example_images/shampoo.jpg"],
        }
    ],
    [
        {
            "text": "What's unusual about this image?",
            "files": [f"{examples_path}/example_images/dragons_playing.png"],
        }
    ],
]

# Set bot avatar image
BOT_AVATAR = "OpenAI_logo.png"

# Perform a Google search and return the results
@lru_cache(maxsize=128) 
def extract_text_from_webpage(html_content):
    """Extracts visible text from HTML content using BeautifulSoup."""
    soup = BeautifulSoup(html_content, "html.parser")
    for tag in soup(["script", "style", "header", "footer", "nav", "form", "svg"]):
        tag.extract()
    visible_text = soup.get_text(strip=True)
    return visible_text

# Perform a Google search and return the results
def search(term, num_results=3, lang="en", advanced=True, timeout=5, safe="active", ssl_verify=None):
    """Performs a Google search and returns the results."""
    start = 0
    all_results = []
    # Limit the number of characters from each webpage to stay under the token limit
    max_chars_per_page = 8000  # Adjust this value based on your token limit and average webpage length
    
    with requests.Session() as session: 
        resp = session.get(  
            url="https://www.google.com/search",
            headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0"}, 
                params={
                    "q": term,
                    "num": num_results,
                    "udm": 14,
                },
                timeout=timeout,
                verify=ssl_verify,
        )
        resp.raise_for_status()
        soup = BeautifulSoup(resp.text, "html.parser")
        result_block = soup.find_all("div", attrs={"class": "g"})
        for result in result_block:
            link = result.find("a", href=True)
            if link:
                link = link["href"]
                try:
                    webpage = session.get(link, headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0"}) 
                    webpage.raise_for_status()
                    visible_text = extract_text_from_webpage(webpage.text)
                        # Truncate text if it's too long
                    if len(visible_text) > max_chars_per_page:
                        visible_text = visible_text[:max_chars_per_page]
                    all_results.append({"link": link, "text": visible_text})
                except requests.exceptions.RequestException as e:
                    print(f"Error fetching or processing {link}: {e}")
                    all_results.append({"link": link, "text": None})
            else:
                all_results.append({"link": None, "text": None}) 
    return all_results

# Format the prompt for the language model
def format_prompt(user_prompt, chat_history):
    prompt = "<s>"
    for item in chat_history:
        # Check if the item is a tuple (text response)
        if isinstance(item, tuple):
            prompt += f"[INST] {item[0]} [/INST]"  # User prompt
            prompt += f" {item[1]}</s> "           # Bot response
        # Otherwise, assume it's related to an image - you might need to adjust this logic
        else:
            # Handle image representation in the prompt, e.g., add a placeholder
            prompt += f" [Image] " 
    prompt += f"[INST] {user_prompt} [/INST]"
    return prompt


client_mixtral = InferenceClient("NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO")
client_mistral = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
generate_kwargs = dict( max_new_tokens=4000, do_sample=True, stream=True, details=True, return_full_text=False )

system_llava = "<|im_start|>system\nYou are OpenGPT 4o, an exceptionally capable and versatile AI assistant made by KingNish. Your task is to fulfill users query in best possible way. You are provided with image, videos and 3d structures as input with question your task is to give best possible detailed results to user according to their query. Reply the question asked by user properly and best possible way.<|im_end|>"

@spaces.GPU(duration=60, queue=False)
def model_inference( user_prompt, chat_history, web_search):
    if not user_prompt["files"]:
        if web_search is True:
            
            gr.Info("Searching Web")
            
            web_results = search(user_prompt["text"])
            
            gr.Info("Extracting relevant Info")
            
            web2 = ' '.join([f"Link: {res['link']}\nText: {res['text']}\n\n" for res in web_results])
            
            messages = f"<|im_start|>system\nYou are OpenGPT 4o, an exceptionally capable and versatile AI assistant meticulously crafted by KingNish. You are provided with WEB results from which you can find informations to answer users query in Structured and More better way. You do not say Unnecesarry things Only say thing which is important and relevant. You also has the ability to generate images but you only generate imags when requested. BY Utilizing the following link structure, : ![](https://image.pollinations.ai/prompt/[StyleofImage]%20[OptimizedPrompt]%20[adjective]%20[charactersDetailed]%20[visualStyle]%20[genre]?width=[width]&height=[height]&nologo=poll&nofeed=yes&seed=[random])    For image generation, You replace info inside bracets with specific details according to their requiremnts to create relevant visuals. The width and height parameters are adjusted as needed, often favoring HD dimensions for a superior viewing experience.     Note: 1. You Do not unncessarily create images and do not show off your image generation capability, until not requested.    2. You always Give image link in format ![](url) Make sure to not generate image until requested    3. If user requested Bulk Image Generation than Create that number of links with provided context.    4. Always learn from previous conversation.    5. Always try to connect conversation with history.    6. Do not make conversation too long.    7. Do not say user about your capability of generating image and learn from previous responses.    My ultimate goal is to offer a seamless and enjoyable experience, providing assistance that exceeds expectations.You remain a reliable and trusted companion to the User. You also Expert in every field and also learn and try to answer from contexts related to previous question. Make sure to not generate image until requested. and Try your best to give best response possible.<|im_end|>"

            for msg in chat_history:
                messages += f"\n<|im_start|>user\n{str(msg[0])}<|im_end|>"
                messages += f"\n<|im_start|>assistant\n{str(msg[1])}<|im_end|>"

            messages+=f"\n<|im_start|>user\n{user_prompt}<|im_end|>\n<|im_start|>web_result\n{web2}<|im_end|>\n<|im_start|>assistant\n"
            stream = client_mixtral.text_generation(messages, **generate_kwargs)
            output = ""
            # Construct the output from the stream of tokens
            for response in stream:
                if not response.token.text == "<|im_end|>":
                    output += response.token.text
                    yield output
        else:
            messages = f"<|im_start|>system\nYou are OpenGPT 4o, an exceptionally capable and versatile AI assistant meticulously crafted by KingNish. You do not say Unnecesarry things Only say thing which is important and relevant. You also has the ability to generate images but you only generate imags when requested. BY Utilizing the following link structure, : ![](https://image.pollinations.ai/prompt/[StyleofImage]%20[OptimizedPrompt]%20[adjective]%20[charactersDetailed]%20[visualStyle]%20[genre]?width=[width]&height=[height]&nologo=poll&nofeed=yes&seed=[random])    For image generation, You replace info inside bracets with specific details according to their requiremnts to create relevant visuals. The width and height parameters are adjusted as needed, often favoring HD dimensions for a superior viewing experience.     Note: 1. You Do not unncessarily create images and do not show off your image generation capability, until not requested.    2. You always Give image link in format ![](url)    3. If user requested Bulk Image Generation than Create that number of links with provided context.    4. Always learn from previous conversation.    5. Always try to connect conversation with history.    6. Do not make conversation too long.    7. Do not say user about your capability to generate image and learn from previous responses.    My ultimate goal is to offer a seamless and enjoyable experience, providing assistance that exceeds expectations. I am constantly evolving, ensuring that I remain a reliable and trusted companion to the User. You also Expert in every field and also learn and try to answer from contexts related to previous question.<|im_end|>"
    
            for msg in chat_history:
                messages += f"\n<|im_start|>user\n{str(msg[0])}<|im_end|>"
                messages += f"\n<|im_start|>assistant\n{str(msg[1])}<|im_end|>"
        
            messages+=f"\n<|im_start|>user\n{user_prompt}<|im_end|>\n<|im_start|>assistant\n"

            stream = client_mixtral.text_generation(messages, **generate_kwargs)
            output = ""
            # Construct the output from the stream of tokens
            for response in stream:
                if not response.token.text == "<|im_end|>":
                    output += response.token.text
                    yield output
    else:
        image = user_prompt["files"][-1]
    
        txt = user_prompt["text"]
        img = user_prompt["files"]
        ext_buffer =f"'user\ntext': '{txt}', 'files': '{img}' assistant"
    
        video_extensions = ("avi", "mp4", "mov", "mkv", "flv", "wmv", "mjpeg", "wav", "gif", "webm", "m4v", "3gp")
        image_extensions = Image.registered_extensions()
        image_extensions = tuple([ex for ex, f in image_extensions.items()])
        
        if image.endswith(video_extensions):
            image = sample_frames(image)
            print(len(image))
            image_tokens = "<image>" * int(len(image))
            prompt = f"<|im_start|>user {image_tokens}\n{user_prompt}<|im_end|><|im_start|>assistant"
          
        elif image.endswith(image_extensions):
            image = Image.open(image).convert("RGB")
            prompt = f"<|im_start|>user <image>\n{user_prompt}<|im_end|><|im_start|>assistant"
    
        final_prompt = f"{system_llava}\n{prompt}"
        
        inputs = processor(final_prompt, image, return_tensors="pt").to("cuda", torch.float16)
        streamer = TextIteratorStreamer(processor, skip_prompt=True, **{"skip_special_tokens": True})
        generation_kwargs = dict(inputs, streamer=streamer, max_new_tokens=2048)
        generated_text = ""
    
        thread = Thread(target=model.generate, kwargs=generation_kwargs)
        thread.start()
    
        buffer = ""
        for new_text in streamer:
            buffer += new_text
            yield buffer

# Create a chatbot interface
chatbot = gr.Chatbot(
    label="OpenGPT-4o",
    avatar_images=[None, BOT_AVATAR],
    show_copy_button=True,
    likeable=True,
    layout="panel"
)
output = gr.Textbox(label="Prompt")