Spaces:
Running
on
Zero
Running
on
Zero
Upload folder using huggingface_hub
Browse files
app.py
CHANGED
|
@@ -197,70 +197,66 @@ def _history_to_messages(history):
|
|
| 197 |
|
| 198 |
# ==========================================
|
| 199 |
@gpu_decorator
|
| 200 |
-
def respond(
|
| 201 |
"""
|
| 202 |
-
|
| 203 |
-
history:
|
| 204 |
"""
|
| 205 |
-
files = user_msg.get("files", [])
|
| 206 |
-
text = user_msg.get("text", "")
|
| 207 |
|
| 208 |
-
# 1.
|
| 209 |
-
|
| 210 |
|
| 211 |
-
#
|
| 212 |
-
|
| 213 |
-
for
|
| 214 |
-
|
| 215 |
|
| 216 |
-
#
|
|
|
|
| 217 |
if text:
|
| 218 |
-
|
| 219 |
-
history.append([text, None])
|
| 220 |
-
elif not text and files:
|
| 221 |
-
# 如果只有图片没文本,添加一个空的占位符,让机器人回复图片
|
| 222 |
-
# 注意:这里我们用 (None, None) 可能会报错,用 ("(image uploaded)", None) 或者
|
| 223 |
-
# 更常见的做法是:最后一项的 user 部分必须非空才能看起来正常,
|
| 224 |
-
# 但我们可以在下面立即生成回复填补 bot 部分。
|
| 225 |
-
pass
|
| 226 |
|
| 227 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
yield history, gr.MultimodalTextbox(value=None, interactive=False)
|
| 229 |
|
| 230 |
-
# 2. 调用模型
|
| 231 |
-
# -------------------------------------------------
|
| 232 |
try:
|
| 233 |
handler = get_model_handler()
|
| 234 |
|
| 235 |
-
#
|
| 236 |
-
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
| 238 |
|
| 239 |
-
# 在界面上为机器人的回复预留位置
|
| 240 |
-
# 如果最后一条是 [user_content, None],我们把它改成 [user_content, ""]
|
| 241 |
-
if history and history[-1][1] is None:
|
| 242 |
-
history[-1][1] = ""
|
| 243 |
-
else:
|
| 244 |
-
# 如果万一没有对应行,加一行
|
| 245 |
-
history.append([None, ""])
|
| 246 |
-
|
| 247 |
-
# 流式生成
|
| 248 |
full_response = ""
|
| 249 |
-
for chunk in handler.predict(
|
| 250 |
full_response += chunk
|
| 251 |
-
|
|
|
|
| 252 |
yield history, gr.MultimodalTextbox(interactive=False)
|
| 253 |
|
| 254 |
except Exception as e:
|
| 255 |
import traceback
|
| 256 |
traceback.print_exc()
|
| 257 |
-
|
| 258 |
-
if history and history[-1][
|
| 259 |
-
history[-1][
|
| 260 |
else:
|
| 261 |
-
history.append(
|
|
|
|
| 262 |
yield history, gr.MultimodalTextbox(interactive=True)
|
| 263 |
|
|
|
|
| 264 |
yield history, gr.MultimodalTextbox(interactive=True)
|
| 265 |
|
| 266 |
def create_chat_ui():
|
|
@@ -280,7 +276,7 @@ def create_chat_ui():
|
|
| 280 |
elem_id="chatbot",
|
| 281 |
label="Chat",
|
| 282 |
avatar_images=(None, "https://api.dicebear.com/7.x/bottts/svg?seed=Qwen"),
|
| 283 |
-
height=650
|
| 284 |
)
|
| 285 |
|
| 286 |
chat_input = gr.MultimodalTextbox(
|
|
|
|
| 197 |
|
| 198 |
# ==========================================
|
| 199 |
@gpu_decorator
|
| 200 |
+
def respond(user_input, history, temp, tokens):
|
| 201 |
"""
|
| 202 |
+
user_input: MultimodalTextbox 返回的字典 {'text': '...', 'files': [...]}
|
| 203 |
+
history: 这里的 history 是 Gradio 自动维护的 [{'role': 'user', ...}, ...] 列表
|
| 204 |
"""
|
|
|
|
|
|
|
| 205 |
|
| 206 |
+
# 1. 构建当前用户的消息对象
|
| 207 |
+
user_content = []
|
| 208 |
|
| 209 |
+
# 处理图片
|
| 210 |
+
files = user_input.get("files", [])
|
| 211 |
+
for file_path in files:
|
| 212 |
+
user_content.append({"type": "image", "image": file_path})
|
| 213 |
|
| 214 |
+
# 处理文本
|
| 215 |
+
text = user_input.get("text", "")
|
| 216 |
if text:
|
| 217 |
+
user_content.append({"type": "text", "text": text})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
|
| 219 |
+
# 如果没有内容,直接返回
|
| 220 |
+
if not user_content:
|
| 221 |
+
yield history, gr.MultimodalTextbox(interactive=True)
|
| 222 |
+
return
|
| 223 |
+
|
| 224 |
+
# 2. 将用户消息加入历史
|
| 225 |
+
# 注意:history 必须是 [{'role': 'user', 'content': [...]}, ...] 格式
|
| 226 |
+
history.append({"role": "user", "content": user_content})
|
| 227 |
+
|
| 228 |
+
# 立即更新 UI,清空输入框
|
| 229 |
yield history, gr.MultimodalTextbox(value=None, interactive=False)
|
| 230 |
|
|
|
|
|
|
|
| 231 |
try:
|
| 232 |
handler = get_model_handler()
|
| 233 |
|
| 234 |
+
# 3. 预先加入一个空的助手消息,用于流式显示
|
| 235 |
+
history.append({"role": "assistant", "content": ""})
|
| 236 |
+
|
| 237 |
+
# 4. 调用模型
|
| 238 |
+
# 我们传入 history 的副本(不包含刚才加的空 assistant),以免污染
|
| 239 |
+
input_messages = copy.deepcopy(history[:-1])
|
| 240 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
full_response = ""
|
| 242 |
+
for chunk in handler.predict(input_messages, temp, tokens):
|
| 243 |
full_response += chunk
|
| 244 |
+
# 实时更新最后一条消息的内容
|
| 245 |
+
history[-1]["content"] = full_response
|
| 246 |
yield history, gr.MultimodalTextbox(interactive=False)
|
| 247 |
|
| 248 |
except Exception as e:
|
| 249 |
import traceback
|
| 250 |
traceback.print_exc()
|
| 251 |
+
# 出错时显示错误信息
|
| 252 |
+
if history and history[-1]["role"] == "assistant":
|
| 253 |
+
history[-1]["content"] += f"\n❌ Error: {str(e)}"
|
| 254 |
else:
|
| 255 |
+
history.append({"role": "assistant", "content": f"❌ Error: {str(e)}"})
|
| 256 |
+
|
| 257 |
yield history, gr.MultimodalTextbox(interactive=True)
|
| 258 |
|
| 259 |
+
# 最后恢复输入框
|
| 260 |
yield history, gr.MultimodalTextbox(interactive=True)
|
| 261 |
|
| 262 |
def create_chat_ui():
|
|
|
|
| 276 |
elem_id="chatbot",
|
| 277 |
label="Chat",
|
| 278 |
avatar_images=(None, "https://api.dicebear.com/7.x/bottts/svg?seed=Qwen"),
|
| 279 |
+
height=650
|
| 280 |
)
|
| 281 |
|
| 282 |
chat_input = gr.MultimodalTextbox(
|