EthanCastro commited on
Commit
f9d56ed
·
verified ·
1 Parent(s): 401720b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -14
app.py CHANGED
@@ -5,7 +5,7 @@ import torch
5
 
6
  # --- CONFIGURATION ---
7
  BASE_MODEL = "unsloth/Qwen3-VL-2B-Instruct-unsloth-bnb-4bit"
8
- LORA_ID = "EthanCastro/qwen3-vl-2b-quickdraw" # <--- Checked: Matches your repo name
9
 
10
  print("Loading model and processor...")
11
  model = AutoModelForImageTextToText.from_pretrained(
@@ -15,26 +15,38 @@ model = AutoModelForImageTextToText.from_pretrained(
15
  trust_remote_code=True
16
  )
17
 
18
- # Load your LoRA adapters
19
  model = PeftModel.from_pretrained(model, LORA_ID)
20
  processor = AutoProcessor.from_pretrained("Qwen/Qwen3-VL-2B-Instruct", trust_remote_code=True)
21
  print("Model Ready!")
22
 
23
  def respond(message, image, history):
 
 
24
  messages = []
25
- # Build conversation history
26
- for user_msg, assistant_msg in history:
27
- messages.append({"role": "user", "content": [{"type": "text", "text": user_msg}]})
28
- messages.append({"role": "assistant", "content": [{"type": "text", "text": assistant_msg}]})
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- # Add current user turn
31
  user_content = []
32
  if image is not None:
33
  user_content.append({"type": "image", "image": image})
34
  user_content.append({"type": "text", "text": message})
35
  messages.append({"role": "user", "content": user_content})
36
 
37
- # Tokenize and Generate
38
  text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
39
 
40
  if image is not None:
@@ -47,7 +59,6 @@ def respond(message, image, history):
47
 
48
  generated_text = processor.batch_decode(outputs, skip_special_tokens=True)[0]
49
 
50
- # Extract only the assistant's response
51
  if "assistant" in generated_text:
52
  response = generated_text.split("assistant")[-1].strip()
53
  else:
@@ -56,11 +67,12 @@ def respond(message, image, history):
56
  return response
57
 
58
  # --- GRADIO INTERFACE ---
59
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
 
60
  gr.Markdown("# 🎨 QuickDraw → tldraw JSON")
61
 
62
- # --- FIX IS HERE: type='tuples' supports your current history format ---
63
- chatbot = gr.Chatbot(height=500, type="tuples")
64
 
65
  with gr.Row():
66
  img_input = gr.Image(type="pil", label="Upload Sketch", scale=1)
@@ -73,11 +85,18 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
73
  submit_btn = gr.Button("Send", variant="primary")
74
 
75
  def chat_wrapper(message, image, history):
 
76
  bot_res = respond(message, image, history)
77
- history.append((message, bot_res))
 
 
 
 
78
  return "", None, history
79
 
 
80
  submit_btn.click(chat_wrapper, [txt_input, img_input, chatbot], [txt_input, img_input, chatbot])
81
  txt_input.submit(chat_wrapper, [txt_input, img_input, chatbot], [txt_input, img_input, chatbot])
82
 
83
- demo.launch()
 
 
5
 
6
  # --- CONFIGURATION ---
7
  BASE_MODEL = "unsloth/Qwen3-VL-2B-Instruct-unsloth-bnb-4bit"
8
+ LORA_ID = "EthanCastro/qwen3-vl-2b-quickdraw"
9
 
10
  print("Loading model and processor...")
11
  model = AutoModelForImageTextToText.from_pretrained(
 
15
  trust_remote_code=True
16
  )
17
 
 
18
  model = PeftModel.from_pretrained(model, LORA_ID)
19
  processor = AutoProcessor.from_pretrained("Qwen/Qwen3-VL-2B-Instruct", trust_remote_code=True)
20
  print("Model Ready!")
21
 
22
  def respond(message, image, history):
23
+ # History is now a list of dictionaries
24
+ # Format: [{"role": "user", "content": "hi"}, {"role": "assistant", "content": "hello"}]
25
  messages = []
26
+
27
+ # 1. Convert history to Qwen's multimodal format
28
+ for msg in history:
29
+ # We need to ensure content is treated as text for the history buffer
30
+ content = msg["content"]
31
+ # If content is a list (multimodal), extract just the text for simplicity
32
+ if isinstance(content, list):
33
+ text_content = next((item['text'] for item in content if item['type'] == 'text'), "")
34
+ else:
35
+ text_content = content
36
+
37
+ messages.append({
38
+ "role": msg["role"],
39
+ "content": [{"type": "text", "text": text_content}]
40
+ })
41
 
42
+ # 2. Add current user turn with the new image
43
  user_content = []
44
  if image is not None:
45
  user_content.append({"type": "image", "image": image})
46
  user_content.append({"type": "text", "text": message})
47
  messages.append({"role": "user", "content": user_content})
48
 
49
+ # 3. Tokenize and Generate
50
  text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
51
 
52
  if image is not None:
 
59
 
60
  generated_text = processor.batch_decode(outputs, skip_special_tokens=True)[0]
61
 
 
62
  if "assistant" in generated_text:
63
  response = generated_text.split("assistant")[-1].strip()
64
  else:
 
67
  return response
68
 
69
  # --- GRADIO INTERFACE ---
70
+ # Note: 'theme' removed from here per Gradio 6 migration guide
71
+ with gr.Blocks() as demo:
72
  gr.Markdown("# 🎨 QuickDraw → tldraw JSON")
73
 
74
+ # Chatbot using default "messages" format (no type argument needed)
75
+ chatbot = gr.Chatbot(height=500)
76
 
77
  with gr.Row():
78
  img_input = gr.Image(type="pil", label="Upload Sketch", scale=1)
 
85
  submit_btn = gr.Button("Send", variant="primary")
86
 
87
  def chat_wrapper(message, image, history):
88
+ # 1. Get response
89
  bot_res = respond(message, image, history)
90
+
91
+ # 2. Update history using DICTIONARIES
92
+ history.append({"role": "user", "content": message})
93
+ history.append({"role": "assistant", "content": bot_res})
94
+
95
  return "", None, history
96
 
97
+ # Initialize state as an empty list
98
  submit_btn.click(chat_wrapper, [txt_input, img_input, chatbot], [txt_input, img_input, chatbot])
99
  txt_input.submit(chat_wrapper, [txt_input, img_input, chatbot], [txt_input, img_input, chatbot])
100
 
101
+ # Theme is now applied here in launch()
102
+ demo.launch(theme=gr.themes.Soft())