Spaces:
Build error
Build error
Zenith Wang
commited on
Commit
·
0c31809
1
Parent(s):
a370152
Support multiple image upload with File component, remove paste and camera features
Browse files
app.py
CHANGED
|
@@ -27,44 +27,58 @@ def image_to_base64(image):
|
|
| 27 |
|
| 28 |
return None
|
| 29 |
|
| 30 |
-
def process_message(message, history,
|
| 31 |
-
"""
|
| 32 |
print(f"[DEBUG] Processing message: {message[:100] if message else 'None'}...")
|
| 33 |
-
print(f"[DEBUG] Has
|
| 34 |
|
| 35 |
-
if not message and not
|
| 36 |
-
print("[DEBUG] No message or
|
| 37 |
yield history
|
| 38 |
return
|
| 39 |
|
| 40 |
if not STEP_API_KEY:
|
| 41 |
print("[DEBUG] No API key configured")
|
| 42 |
error_msg = "❌ API key not configured. Please add STEP_API_KEY in Settings."
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
history.append([display_msg, error_msg])
|
| 45 |
yield history
|
| 46 |
return
|
| 47 |
|
| 48 |
-
#
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
# 构造显示消息
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
| 68 |
else:
|
| 69 |
display_message = message
|
| 70 |
|
|
@@ -90,10 +104,15 @@ def process_message(message, history, image, system_prompt, temperature, max_tok
|
|
| 90 |
messages.append({"role": "assistant", "content": h[1]})
|
| 91 |
|
| 92 |
# 添加当前消息
|
| 93 |
-
if
|
| 94 |
-
current_content = [
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
if text_content:
|
| 98 |
current_content.append({"type": "text", "text": text_content})
|
| 99 |
messages.append({"role": "user", "content": current_content})
|
|
@@ -266,9 +285,10 @@ with gr.Blocks(title="Step-3", theme=gr.themes.Soft(), css=css) as demo:
|
|
| 266 |
elem_id="message-textbox"
|
| 267 |
)
|
| 268 |
with gr.Column(scale=2):
|
| 269 |
-
image_input = gr.
|
| 270 |
-
label="
|
| 271 |
-
|
|
|
|
| 272 |
height=100,
|
| 273 |
interactive=True,
|
| 274 |
show_label=True,
|
|
@@ -320,22 +340,22 @@ with gr.Blocks(title="Step-3", theme=gr.themes.Soft(), css=css) as demo:
|
|
| 320 |
|
| 321 |
|
| 322 |
# 事件处理函���
|
| 323 |
-
def user_submit(message, history,
|
| 324 |
"""用户提交消息时的处理"""
|
| 325 |
print(f"[DEBUG] user_submit called with message: {message[:50] if message else 'None'}...")
|
| 326 |
-
print(f"[DEBUG] user_submit called with
|
| 327 |
-
if message or
|
| 328 |
# 清空输入,保存消息和图片用于后续处理
|
| 329 |
-
return gr.update(value=""), history, gr.update(value=None), message,
|
| 330 |
-
return gr.update(value=message), history, gr.update(value=
|
| 331 |
|
| 332 |
-
def bot_response(history, saved_message,
|
| 333 |
"""生成机器人响应"""
|
| 334 |
print(f"[DEBUG] bot_response called with saved_message: {saved_message[:50] if saved_message else 'None'}...")
|
| 335 |
-
print(f"[DEBUG] bot_response called with
|
| 336 |
-
if saved_message or
|
| 337 |
# 使用生成器处理消息
|
| 338 |
-
for updated_history in process_message(saved_message, history,
|
| 339 |
yield updated_history
|
| 340 |
else:
|
| 341 |
yield history
|
|
@@ -354,17 +374,17 @@ with gr.Blocks(title="Step-3", theme=gr.themes.Soft(), css=css) as demo:
|
|
| 354 |
|
| 355 |
# 创建隐藏的组件来存储消息和图片
|
| 356 |
saved_msg = gr.State("")
|
| 357 |
-
|
| 358 |
|
| 359 |
# 提交消息 - Enter键
|
| 360 |
msg.submit(
|
| 361 |
user_submit,
|
| 362 |
[msg, chatbot, image_input],
|
| 363 |
-
[msg, chatbot, image_input, saved_msg,
|
| 364 |
queue=False
|
| 365 |
).then(
|
| 366 |
bot_response,
|
| 367 |
-
[chatbot, saved_msg,
|
| 368 |
chatbot
|
| 369 |
)
|
| 370 |
|
|
@@ -372,11 +392,11 @@ with gr.Blocks(title="Step-3", theme=gr.themes.Soft(), css=css) as demo:
|
|
| 372 |
submit_btn.click(
|
| 373 |
user_submit,
|
| 374 |
[msg, chatbot, image_input],
|
| 375 |
-
[msg, chatbot, image_input, saved_msg,
|
| 376 |
queue=False
|
| 377 |
).then(
|
| 378 |
bot_response,
|
| 379 |
-
[chatbot, saved_msg,
|
| 380 |
chatbot
|
| 381 |
)
|
| 382 |
|
|
@@ -401,7 +421,7 @@ with gr.Blocks(title="Step-3", theme=gr.themes.Soft(), css=css) as demo:
|
|
| 401 |
[chatbot, saved_msg]
|
| 402 |
).then(
|
| 403 |
bot_response,
|
| 404 |
-
[chatbot, saved_msg,
|
| 405 |
chatbot
|
| 406 |
)
|
| 407 |
|
|
|
|
| 27 |
|
| 28 |
return None
|
| 29 |
|
| 30 |
+
def process_message(message, history, images, system_prompt, temperature, max_tokens, top_p):
|
| 31 |
+
"""处理消息并生成响应,支持可选的多图片输入"""
|
| 32 |
print(f"[DEBUG] Processing message: {message[:100] if message else 'None'}...")
|
| 33 |
+
print(f"[DEBUG] Has images: {images is not None and len(images) > 0 if images else False}")
|
| 34 |
|
| 35 |
+
if not message and not images:
|
| 36 |
+
print("[DEBUG] No message or images provided, skipping")
|
| 37 |
yield history
|
| 38 |
return
|
| 39 |
|
| 40 |
if not STEP_API_KEY:
|
| 41 |
print("[DEBUG] No API key configured")
|
| 42 |
error_msg = "❌ API key not configured. Please add STEP_API_KEY in Settings."
|
| 43 |
+
if images and message:
|
| 44 |
+
display_msg = f"[{len(images)} Images] {message}"
|
| 45 |
+
elif images:
|
| 46 |
+
display_msg = f"[{len(images)} Images]"
|
| 47 |
+
else:
|
| 48 |
+
display_msg = message
|
| 49 |
history.append([display_msg, error_msg])
|
| 50 |
yield history
|
| 51 |
return
|
| 52 |
|
| 53 |
+
# 处理多张图片
|
| 54 |
+
image_contents = []
|
| 55 |
+
if images:
|
| 56 |
+
for img_path in images:
|
| 57 |
+
try:
|
| 58 |
+
# 获取文件路径
|
| 59 |
+
if hasattr(img_path, 'name'):
|
| 60 |
+
img_file = img_path.name
|
| 61 |
+
else:
|
| 62 |
+
img_file = img_path
|
| 63 |
+
|
| 64 |
+
# 转换图片为base64
|
| 65 |
+
with Image.open(img_file) as img:
|
| 66 |
+
image_content = image_to_base64(img)
|
| 67 |
+
if image_content:
|
| 68 |
+
image_contents.append(image_content)
|
| 69 |
+
print(f"[DEBUG] Image {len(image_contents)} processed successfully")
|
| 70 |
+
except Exception as e:
|
| 71 |
+
print(f"[DEBUG] Failed to process image: {e}")
|
| 72 |
+
history.append([message or f"[{len(images)} Images]", f"❌ Failed to process image: {str(e)}"])
|
| 73 |
+
yield history
|
| 74 |
+
return
|
| 75 |
|
| 76 |
# 构造显示消息
|
| 77 |
+
text_content = message or ""
|
| 78 |
+
if image_contents and message:
|
| 79 |
+
display_message = f"🖼️ [{len(image_contents)} Image{'s' if len(image_contents) > 1 else ''}] {message}"
|
| 80 |
+
elif image_contents:
|
| 81 |
+
display_message = f"🖼️ [{len(image_contents)} Image{'s' if len(image_contents) > 1 else ''}]"
|
| 82 |
else:
|
| 83 |
display_message = message
|
| 84 |
|
|
|
|
| 104 |
messages.append({"role": "assistant", "content": h[1]})
|
| 105 |
|
| 106 |
# 添加当前消息
|
| 107 |
+
if image_contents:
|
| 108 |
+
current_content = []
|
| 109 |
+
# 添加所有图片
|
| 110 |
+
for img_base64 in image_contents:
|
| 111 |
+
current_content.append({
|
| 112 |
+
"type": "image_url",
|
| 113 |
+
"image_url": {"url": f"data:image/jpg;base64,{img_base64}", "detail": "high"}
|
| 114 |
+
})
|
| 115 |
+
# 添加文本
|
| 116 |
if text_content:
|
| 117 |
current_content.append({"type": "text", "text": text_content})
|
| 118 |
messages.append({"role": "user", "content": current_content})
|
|
|
|
| 285 |
elem_id="message-textbox"
|
| 286 |
)
|
| 287 |
with gr.Column(scale=2):
|
| 288 |
+
image_input = gr.File(
|
| 289 |
+
label="Images",
|
| 290 |
+
file_count="multiple",
|
| 291 |
+
file_types=["image"],
|
| 292 |
height=100,
|
| 293 |
interactive=True,
|
| 294 |
show_label=True,
|
|
|
|
| 340 |
|
| 341 |
|
| 342 |
# 事件处理函���
|
| 343 |
+
def user_submit(message, history, images):
|
| 344 |
"""用户提交消息时的处理"""
|
| 345 |
print(f"[DEBUG] user_submit called with message: {message[:50] if message else 'None'}...")
|
| 346 |
+
print(f"[DEBUG] user_submit called with images: {len(images) if images else 0} files")
|
| 347 |
+
if message or images:
|
| 348 |
# 清空输入,保存消息和图片用于后续处理
|
| 349 |
+
return gr.update(value=""), history, gr.update(value=None), message, images
|
| 350 |
+
return gr.update(value=message), history, gr.update(value=images), message, images
|
| 351 |
|
| 352 |
+
def bot_response(history, saved_message, saved_images, system_prompt, temperature, max_tokens, top_p):
|
| 353 |
"""生成机器人响应"""
|
| 354 |
print(f"[DEBUG] bot_response called with saved_message: {saved_message[:50] if saved_message else 'None'}...")
|
| 355 |
+
print(f"[DEBUG] bot_response called with saved_images: {len(saved_images) if saved_images else 0} files")
|
| 356 |
+
if saved_message or saved_images:
|
| 357 |
# 使用生成器处理消息
|
| 358 |
+
for updated_history in process_message(saved_message, history, saved_images, system_prompt, temperature, max_tokens, top_p):
|
| 359 |
yield updated_history
|
| 360 |
else:
|
| 361 |
yield history
|
|
|
|
| 374 |
|
| 375 |
# 创建隐藏的组件来存储消息和图片
|
| 376 |
saved_msg = gr.State("")
|
| 377 |
+
saved_imgs = gr.State([])
|
| 378 |
|
| 379 |
# 提交消息 - Enter键
|
| 380 |
msg.submit(
|
| 381 |
user_submit,
|
| 382 |
[msg, chatbot, image_input],
|
| 383 |
+
[msg, chatbot, image_input, saved_msg, saved_imgs],
|
| 384 |
queue=False
|
| 385 |
).then(
|
| 386 |
bot_response,
|
| 387 |
+
[chatbot, saved_msg, saved_imgs, system_prompt, temperature, max_tokens, top_p],
|
| 388 |
chatbot
|
| 389 |
)
|
| 390 |
|
|
|
|
| 392 |
submit_btn.click(
|
| 393 |
user_submit,
|
| 394 |
[msg, chatbot, image_input],
|
| 395 |
+
[msg, chatbot, image_input, saved_msg, saved_imgs],
|
| 396 |
queue=False
|
| 397 |
).then(
|
| 398 |
bot_response,
|
| 399 |
+
[chatbot, saved_msg, saved_imgs, system_prompt, temperature, max_tokens, top_p],
|
| 400 |
chatbot
|
| 401 |
)
|
| 402 |
|
|
|
|
| 421 |
[chatbot, saved_msg]
|
| 422 |
).then(
|
| 423 |
bot_response,
|
| 424 |
+
[chatbot, saved_msg, saved_imgs, system_prompt, temperature, max_tokens, top_p],
|
| 425 |
chatbot
|
| 426 |
)
|
| 427 |
|