Skip to content

Commit 25f4d2e

Browse files
switch Qwen3vl notebook to genai pipeline (#3370)
1 parent 2668aec commit 25f4d2e

2 files changed

Lines changed: 283 additions & 149 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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

Comments
 (0)