|
| 1 | +from pathlib import Path |
| 2 | +import gradio as gr |
| 3 | + |
| 4 | + |
| 5 | +from PIL import Image |
| 6 | +import numpy as np |
| 7 | +import requests |
| 8 | +from threading import Event, Thread |
| 9 | +import inspect |
| 10 | +from queue import Queue |
| 11 | + |
| 12 | +example_image_urls = [ |
| 13 | + ( |
| 14 | + "https://github.com/openvinotoolkit/openvino_notebooks/assets/29454499/1d6a0188-5613-418d-a1fd-4560aae1d907", |
| 15 | + "bee.jpg", |
| 16 | + ), |
| 17 | + ( |
| 18 | + "https://github.com/openvinotoolkit/openvino_notebooks/assets/29454499/6cc7feeb-0721-4b5d-8791-2576ed9d2863", |
| 19 | + "baklava.png", |
| 20 | + ), |
| 21 | +] |
| 22 | +for url, file_name in example_image_urls: |
| 23 | + if not Path(file_name).exists(): |
| 24 | + Image.open(requests.get(url, stream=True, timeout=30).raw).save(file_name) |
| 25 | + |
| 26 | + |
| 27 | +def make_demo(model): |
| 28 | + import openvino_genai |
| 29 | + import openvino as ov |
| 30 | + |
| 31 | + has_additonal_buttons = "undo_button" in inspect.signature(gr.ChatInterface.__init__).parameters |
| 32 | + |
| 33 | + def read_image(path: str) -> ov.Tensor: |
| 34 | + """ |
| 35 | + Args: |
| 36 | + path: The path to the image. |
| 37 | +
|
| 38 | + Returns: the ov.Tensor containing the image. |
| 39 | + """ |
| 40 | + pic = Image.open(path).convert("RGB") |
| 41 | + image_data = np.array(pic.getdata()).reshape(1, pic.size[1], pic.size[0], 3).astype(np.uint8) |
| 42 | + return ov.Tensor(image_data) |
| 43 | + |
| 44 | + class TextQueue: |
| 45 | + def __init__(self) -> None: |
| 46 | + self.text_queue = Queue() |
| 47 | + self.stop_signal = None |
| 48 | + self.stop_tokens = [] |
| 49 | + |
| 50 | + def __call__(self, text): |
| 51 | + self.text_queue.put(text) |
| 52 | + |
| 53 | + def __iter__(self): |
| 54 | + return self |
| 55 | + |
| 56 | + def __next__(self): |
| 57 | + value = self.text_queue.get() |
| 58 | + if value == self.stop_signal or value in self.stop_tokens: |
| 59 | + raise StopIteration() |
| 60 | + else: |
| 61 | + return value |
| 62 | + |
| 63 | + def reset(self): |
| 64 | + self.text_queue = Queue() |
| 65 | + |
| 66 | + def end(self): |
| 67 | + self.text_queue.put(self.stop_signal) |
| 68 | + |
| 69 | + def bot_streaming(message, history): |
| 70 | + print(f"message is - {message}") |
| 71 | + print(f"history is - {history}") |
| 72 | + |
| 73 | + if not history: |
| 74 | + model.start_chat() |
| 75 | + generation_config = openvino_genai.GenerationConfig() |
| 76 | + generation_config.max_new_tokens = 128 |
| 77 | + files = message["files"] if isinstance(message, dict) else message.files |
| 78 | + message_text = message["text"] if isinstance(message, dict) else message.text |
| 79 | + |
| 80 | + image = None |
| 81 | + if files: |
| 82 | + # message["files"][-1] is a Dict or just a string |
| 83 | + if isinstance(files[-1], dict): |
| 84 | + image = files[-1]["path"] |
| 85 | + else: |
| 86 | + if isinstance(files[-1], (str, Path)): |
| 87 | + image = files[-1] |
| 88 | + else: |
| 89 | + image = files[-1] if isinstance(files[-1], (list, tuple)) else files[-1].path |
| 90 | + if image is not None: |
| 91 | + image = read_image(image) |
| 92 | + streamer = TextQueue() |
| 93 | + stream_complete = Event() |
| 94 | + |
| 95 | + def generate_and_signal_complete(): |
| 96 | + """ |
| 97 | + generation function for single thread |
| 98 | + """ |
| 99 | + streamer.reset() |
| 100 | + generation_kwargs = {"prompt": message_text, "generation_config": generation_config, "streamer": streamer} |
| 101 | + if image is not None: |
| 102 | + generation_kwargs["image"] = image |
| 103 | + model.generate(**generation_kwargs) |
| 104 | + stream_complete.set() |
| 105 | + streamer.end() |
| 106 | + |
| 107 | + t1 = Thread(target=generate_and_signal_complete) |
| 108 | + t1.start() |
| 109 | + |
| 110 | + buffer = "" |
| 111 | + for new_text in streamer: |
| 112 | + buffer += new_text |
| 113 | + yield buffer |
| 114 | + |
| 115 | + additional_buttons = {} |
| 116 | + if has_additonal_buttons: |
| 117 | + additional_buttons = {"undo_button": None, "retry_button": None} |
| 118 | + demo = gr.ChatInterface( |
| 119 | + fn=bot_streaming, |
| 120 | + title="Qwen3-VL OpenVINO GenAI Demo", |
| 121 | + examples=[ |
| 122 | + {"text": "What is on the flower?", "files": ["./bee.jpg"]}, |
| 123 | + {"text": "How to make this pastry?", "files": ["./baklava.png"]}, |
| 124 | + ], |
| 125 | + stop_btn=None, |
| 126 | + multimodal=True, |
| 127 | + **additional_buttons, |
| 128 | + ) |
| 129 | + return demo |
0 commit comments