akhaliq HF Staff commited on
Commit
a14c972
·
verified ·
1 Parent(s): 3c2d41e

Deploy Gradio app with multiple files

Browse files
Files changed (2) hide show
  1. app.py +172 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import Qwen3VLForConditionalGeneration, AutoProcessor
3
+ import torch
4
+ from PIL import Image
5
+ import io
6
+ import base64
7
+
8
+ import spaces
9
+
10
+ # Load model and processor
11
+ model = Qwen3VLForConditionalGeneration.from_pretrained(
12
+ "Qwen/Qwen3-VL-2B-Instruct",
13
+ torch_dtype=torch.bfloat16,
14
+ device_map="auto"
15
+ )
16
+ processor = AutoProcessor.from_pretrained("Qwen/Qwen3-VL-2B-Instruct")
17
+
18
+ def process_image(image):
19
+ """Convert image to base64 string for processing"""
20
+ if isinstance(image, str):
21
+ return image
22
+ if isinstance(image, Image.Image):
23
+ buffered = io.BytesIO()
24
+ image.save(buffered, format="PNG")
25
+ img_str = base64.b64encode(buffered.getvalue()).decode()
26
+ return f"data:image/png;base64,{img_str}"
27
+ return image
28
+
29
+ @spaces.GPU(duration=120)
30
+ def qwen_chat(message, image, chat_history):
31
+ """
32
+ Process chat message with optional image input
33
+
34
+ Args:
35
+ message (str): User's text message
36
+ image: Optional image input
37
+ chat_history (list): Previous conversation history
38
+
39
+ Returns:
40
+ tuple: Updated chat history and empty message input
41
+ """
42
+ if not message and image is None:
43
+ return chat_history, ""
44
+
45
+ # Build messages list
46
+ messages = []
47
+
48
+ # Add previous chat history
49
+ for user_msg, assistant_msg in chat_history:
50
+ messages.append({"role": "user", "content": [{"type": "text", "text": user_msg}]})
51
+ messages.append({"role": "assistant", "content": [{"type": "text", "text": assistant_msg}]})
52
+
53
+ # Add current message with optional image
54
+ current_content = []
55
+ if image is not None:
56
+ current_content.append({
57
+ "type": "image",
58
+ "image": image
59
+ })
60
+
61
+ if message:
62
+ current_content.append({
63
+ "type": "text",
64
+ "text": message
65
+ })
66
+
67
+ messages.append({
68
+ "role": "user",
69
+ "content": current_content
70
+ })
71
+
72
+ # Prepare inputs
73
+ inputs = processor.apply_chat_template(
74
+ messages,
75
+ tokenize=True,
76
+ add_generation_prompt=True,
77
+ return_dict=True,
78
+ return_tensors="pt"
79
+ )
80
+ inputs = inputs.to(model.device)
81
+
82
+ # Generate response
83
+ with torch.no_grad():
84
+ generated_ids = model.generate(**inputs, max_new_tokens=256)
85
+
86
+ # Decode output
87
+ generated_ids_trimmed = [
88
+ out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
89
+ ]
90
+ output_text = processor.batch_decode(
91
+ generated_ids_trimmed,
92
+ skip_special_tokens=True,
93
+ clean_up_tokenization_spaces=False
94
+ )[0]
95
+
96
+ # Update chat history
97
+ chat_history.append((message if message else "[Image provided]", output_text))
98
+
99
+ return chat_history, ""
100
+
101
+ # Create Gradio interface
102
+ with gr.Blocks(title="Qwen3-VL Chat") as demo:
103
+ gr.Markdown(
104
+ """
105
+ # 🎨 Qwen3-VL Chat
106
+ Chat with Qwen3-VL-2B-Instruct - A multimodal AI that can understand both text and images!
107
+
108
+ [Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)
109
+ """
110
+ )
111
+
112
+ with gr.Row():
113
+ with gr.Column(scale=3):
114
+ chatbot = gr.Chatbot(
115
+ label="Chat History",
116
+ type="messages",
117
+ height=600,
118
+ show_copy_button=True
119
+ )
120
+
121
+ with gr.Column(scale=1):
122
+ image_input = gr.Image(
123
+ label="Upload Image (Optional)",
124
+ type="pil",
125
+ sources=["upload", "clipboard"],
126
+ interactive=True
127
+ )
128
+
129
+ with gr.Row():
130
+ message_input = gr.Textbox(
131
+ label="Message",
132
+ placeholder="Type your message here...",
133
+ lines=2,
134
+ scale=4
135
+ )
136
+ send_btn = gr.Button("Send", scale=1, variant="primary")
137
+
138
+ with gr.Row():
139
+ clear_btn = gr.Button("Clear Chat", variant="secondary")
140
+
141
+ gr.Markdown(
142
+ """
143
+ ### Tips:
144
+ - Upload an image to ask questions about it
145
+ - Describe what you see or ask for analysis
146
+ - The model can answer questions about images and text
147
+ """
148
+ )
149
+
150
+ # Event handlers
151
+ def send_message(msg, img, history):
152
+ return qwen_chat(msg, img, history)
153
+
154
+ send_btn.click(
155
+ send_message,
156
+ inputs=[message_input, image_input, chatbot],
157
+ outputs=[chatbot, message_input]
158
+ )
159
+
160
+ message_input.submit(
161
+ send_message,
162
+ inputs=[message_input, image_input, chatbot],
163
+ outputs=[chatbot, message_input]
164
+ )
165
+
166
+ clear_btn.click(
167
+ lambda: ([], None, ""),
168
+ outputs=[chatbot, image_input, message_input]
169
+ )
170
+
171
+ if __name__ == "__main__":
172
+ demo.launch(share=False)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio
2
+ transformers
3
+ torch
4
+ torchvision
5
+ pillow
6
+ accelerate
7
+ spaces