alex4cip Claude commited on
Commit
83d2348
Β·
1 Parent(s): e6282fc

refactor: Replace ChatInterface with pure Blocks to fix HTTP/2 errors

Browse files

BREAKING CHANGE: Complete rewrite of chat interface

- Remove ChatInterface completely (causes forced SSE usage)
- Implement manual chat UI using gr.Blocks
- Use tuple format for chat history [[user, bot], ...]
- No queue system, no SSE, no HTTP/2 protocol errors

This is the definitive fix for ERR_HTTP2_PROTOCOL_ERROR and
500 Internal Server Error issues on Hugging Face Spaces.

ChatInterface internally enforces queue/SSE which is incompatible
with HF Spaces infrastructure. Pure Blocks gives full control.

Changes:
- chat_response() now returns updated history list
- Manual gr.Chatbot + gr.Textbox + gr.Button layout
- Direct .click() and .submit() event handlers
- No .queue() call anywhere

πŸ€– Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +62 -35
app.py CHANGED
@@ -119,32 +119,35 @@ def load_model(model_name):
119
 
120
  def chat_response(message, history, model_name):
121
  """
122
- Generate chatbot response
123
 
124
  Args:
125
  message: User input
126
- history: Chat history in Gradio format
127
  model_name: Selected model
128
 
129
  Returns:
130
- Response text
131
  """
 
 
 
132
  try:
133
  # Load model and tokenizer
134
  model, tokenizer = load_model(model_name)
135
 
136
  if model is None or tokenizer is None:
137
- return f"❌ λͺ¨λΈ '{model_name}'을 λ‘œλ“œν•  수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ λͺ¨λΈμ„ μ„ νƒν•΄μ£Όμ„Έμš”."
138
 
139
  model_config = MODELS[model_name]
140
 
141
- # Build conversation context
142
  conversation = ""
143
- for msg in history:
144
- if msg["role"] == "user":
145
- conversation += f"{msg['content']}\n"
146
- elif msg["role"] == "assistant":
147
- conversation += f"{msg['content']}\n"
148
 
149
  # Add current message
150
  conversation += f"{message}\n"
@@ -173,7 +176,7 @@ def chat_response(message, history, model_name):
173
  if not response:
174
  response = "I understand. Could you tell me more?"
175
 
176
- return response
177
 
178
  except Exception as e:
179
  import traceback
@@ -187,11 +190,11 @@ def chat_response(message, history, model_name):
187
  print("=" * 50)
188
 
189
  if "out of memory" in error_msg.lower() or "oom" in error_msg.lower():
190
- return "❌ λ©”λͺ¨λ¦¬ λΆ€μ‘±. 더 μž‘μ€ λͺ¨λΈμ„ μ„ νƒν•˜κ±°λ‚˜ 앱을 μž¬μ‹œμž‘ν•˜μ„Έμš”."
191
  elif "cuda" in error_msg.lower() and device == "cpu":
192
- return "⚠️ GPU 없이 CPU둜 μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€. 응닡이 느릴 수 μžˆμŠ΅λ‹ˆλ‹€."
193
  else:
194
- return f"❌ 였λ₯˜: {error_type}\n{error_msg[:200]}\n\nν„°λ―Έλ„μ—μ„œ 전체 둜그λ₯Ό ν™•μΈν•˜μ„Έμš”."
195
 
196
 
197
  # Global state
@@ -257,25 +260,49 @@ with gr.Blocks(
257
  # Warning message for model requirements
258
  model_warning = gr.Markdown("", visible=False)
259
 
260
- # Chat interface
261
- chatbot = gr.ChatInterface(
262
- fn=chat_response,
263
- type="messages",
264
- additional_inputs=[model_dropdown],
265
- chatbot=gr.Chatbot(
266
- height=500,
267
- placeholder="λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš”...",
268
- type="messages",
269
- ),
270
- textbox=gr.Textbox(
271
  placeholder="πŸ’¬ λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš” (μ˜μ–΄ ꢌμž₯)...",
272
- container=False,
273
- scale=7,
274
  autofocus=True,
275
  elem_classes="chatbot-input",
276
- show_label=False,
277
- ),
278
- # concurrency_limit 제거 - κΈ°λ³Έκ°’ μ‚¬μš©, .queue() ν˜ΈμΆœν•˜μ§€ μ•Šμ•„ 큐 λΉ„ν™œμ„±ν™”
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  )
280
 
281
  # Examples section with model switching
@@ -305,10 +332,10 @@ with gr.Blocks(
305
  def set_example_4():
306
  return "kyujinpy/KoT-Llama2-7B-Chat", "인곡지λŠ₯에 λŒ€ν•΄ κ°„λ‹¨νžˆ μ„€λͺ…ν•΄μ£Όμ„Έμš”."
307
 
308
- example_btn_1.click(set_example_1, outputs=[model_dropdown, chatbot.textbox])
309
- example_btn_2.click(set_example_2, outputs=[model_dropdown, chatbot.textbox])
310
- example_btn_3.click(set_example_3, outputs=[model_dropdown, chatbot.textbox])
311
- example_btn_4.click(set_example_4, outputs=[model_dropdown, chatbot.textbox])
312
 
313
  # Show warning and clear chat when model changes
314
  def on_model_change(new_model):
@@ -331,7 +358,7 @@ with gr.Blocks(
331
  model_dropdown.change(
332
  fn=on_model_change,
333
  inputs=[model_dropdown],
334
- outputs=[chatbot.chatbot_state, model_warning, model_warning],
335
  )
336
 
337
  gr.Markdown(
 
119
 
120
  def chat_response(message, history, model_name):
121
  """
122
+ Generate chatbot response - Returns updated history (for Blocks)
123
 
124
  Args:
125
  message: User input
126
+ history: Chat history as list of [user_msg, bot_msg] pairs
127
  model_name: Selected model
128
 
129
  Returns:
130
+ Updated history list
131
  """
132
+ if not message or not message.strip():
133
+ return history
134
+
135
  try:
136
  # Load model and tokenizer
137
  model, tokenizer = load_model(model_name)
138
 
139
  if model is None or tokenizer is None:
140
+ return history + [[message, f"❌ λͺ¨λΈ '{model_name}'을 λ‘œλ“œν•  수 μ—†μŠ΅λ‹ˆλ‹€."]]
141
 
142
  model_config = MODELS[model_name]
143
 
144
+ # Build conversation context from history
145
  conversation = ""
146
+ for user_msg, bot_msg in history:
147
+ if user_msg:
148
+ conversation += f"{user_msg}\n"
149
+ if bot_msg:
150
+ conversation += f"{bot_msg}\n"
151
 
152
  # Add current message
153
  conversation += f"{message}\n"
 
176
  if not response:
177
  response = "I understand. Could you tell me more?"
178
 
179
+ return history + [[message, response]]
180
 
181
  except Exception as e:
182
  import traceback
 
190
  print("=" * 50)
191
 
192
  if "out of memory" in error_msg.lower() or "oom" in error_msg.lower():
193
+ return history + [[message, "❌ λ©”λͺ¨λ¦¬ λΆ€μ‘±. 더 μž‘μ€ λͺ¨λΈμ„ μ„ νƒν•˜κ±°λ‚˜ 앱을 μž¬μ‹œμž‘ν•˜μ„Έμš”."]]
194
  elif "cuda" in error_msg.lower() and device == "cpu":
195
+ return history + [[message, "⚠️ GPU 없이 CPU둜 μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€. 응닡이 느릴 수 μžˆμŠ΅λ‹ˆλ‹€."]]
196
  else:
197
+ return history + [[message, f"❌ 였λ₯˜: {error_type}\n{error_msg[:200]}"]]
198
 
199
 
200
  # Global state
 
260
  # Warning message for model requirements
261
  model_warning = gr.Markdown("", visible=False)
262
 
263
+ # Chat interface using pure Blocks (NO ChatInterface to avoid SSE issues)
264
+ chatbot_display = gr.Chatbot(
265
+ height=500,
266
+ label="πŸ’¬ λŒ€ν™”",
267
+ show_label=False,
268
+ type="tuples", # Use tuple format [[user_msg, bot_msg], ...]
269
+ )
270
+
271
+ with gr.Row():
272
+ msg_input = gr.Textbox(
 
273
  placeholder="πŸ’¬ λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš” (μ˜μ–΄ ꢌμž₯)...",
274
+ show_label=False,
275
+ scale=9,
276
  autofocus=True,
277
  elem_classes="chatbot-input",
278
+ )
279
+ submit_btn = gr.Button("전솑", scale=1, variant="primary")
280
+
281
+ clear_btn = gr.Button("πŸ—‘οΈ λŒ€ν™” μ΄ˆκΈ°ν™”", size="sm")
282
+
283
+ # Message submission handler
284
+ def submit_message(message, history, model):
285
+ updated_history = chat_response(message, history, model)
286
+ return updated_history, "" # Return updated history and clear input
287
+
288
+ # Button click event (NO queue)
289
+ submit_btn.click(
290
+ fn=submit_message,
291
+ inputs=[msg_input, chatbot_display, model_dropdown],
292
+ outputs=[chatbot_display, msg_input],
293
+ )
294
+
295
+ # Enter key event
296
+ msg_input.submit(
297
+ fn=submit_message,
298
+ inputs=[msg_input, chatbot_display, model_dropdown],
299
+ outputs=[chatbot_display, msg_input],
300
+ )
301
+
302
+ # Clear button
303
+ clear_btn.click(
304
+ fn=lambda: [],
305
+ outputs=chatbot_display,
306
  )
307
 
308
  # Examples section with model switching
 
332
  def set_example_4():
333
  return "kyujinpy/KoT-Llama2-7B-Chat", "인곡지λŠ₯에 λŒ€ν•΄ κ°„λ‹¨νžˆ μ„€λͺ…ν•΄μ£Όμ„Έμš”."
334
 
335
+ example_btn_1.click(set_example_1, outputs=[model_dropdown, msg_input])
336
+ example_btn_2.click(set_example_2, outputs=[model_dropdown, msg_input])
337
+ example_btn_3.click(set_example_3, outputs=[model_dropdown, msg_input])
338
+ example_btn_4.click(set_example_4, outputs=[model_dropdown, msg_input])
339
 
340
  # Show warning and clear chat when model changes
341
  def on_model_change(new_model):
 
358
  model_dropdown.change(
359
  fn=on_model_change,
360
  inputs=[model_dropdown],
361
+ outputs=[chatbot_display, model_warning, model_warning],
362
  )
363
 
364
  gr.Markdown(