Spestly commited on
Commit
ccb939a
·
verified ·
1 Parent(s): 5092f71

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -183
app.py CHANGED
@@ -15,102 +15,20 @@ AVAILABLE_MODELS = {
15
  }
16
 
17
  def parse_thinking_tags(text):
18
- """Parse text and extract thinking sections"""
19
  think_pattern = r'<think>(.*?)</think>'
20
- parts = []
21
- last_end = 0
22
 
 
23
  for match in re.finditer(think_pattern, text, re.DOTALL):
24
- # Add text before thinking block
25
- if match.start() > last_end:
26
- before_text = text[last_end:match.start()].strip()
27
- if before_text:
28
- parts.append({"type": "text", "content": before_text})
29
-
30
- # Add thinking block
31
  thinking_content = match.group(1).strip()
32
  if thinking_content:
33
- parts.append({"type": "thinking", "content": thinking_content})
34
-
35
- last_end = match.end()
36
 
37
- # Add remaining text
38
- if last_end < len(text):
39
- remaining_text = text[last_end:].strip()
40
- if remaining_text:
41
- parts.append({"type": "text", "content": remaining_text})
42
 
43
- return parts
44
-
45
- def create_thinking_html(thinking_content, token_count=None):
46
- """Create HTML for thinking block"""
47
- if token_count is None:
48
- token_count = f"{len(thinking_content.split()) * 4:,}" # Rough token estimate
49
-
50
- thinking_id = f"thinking_{hash(thinking_content) % 10000}"
51
-
52
- html = f"""
53
- <div class="thinking-container" style="margin: 16px 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;">
54
- <div class="thinking-header" onclick="toggleThinking('{thinking_id}')"
55
- style="background: #3a3a3a; border-radius: 8px; padding: 12px 16px; cursor: pointer;
56
- display: flex; align-items: center; gap: 10px; transition: all 0.2s ease;
57
- border: 1px solid #4a4a4a;">
58
- <div style="width: 16px; height: 16px; background: #6366f1; border-radius: 50%; position: relative;">
59
- <div style="position: absolute; top: 50%; left: 50%; width: 6px; height: 6px;
60
- background: white; border-radius: 50%; transform: translate(-50%, -50%);"></div>
61
- </div>
62
- <span style="font-weight: 500; color: #f0f0f0;">Thinking completed</span>
63
- <span style="color: #888; font-size: 14px; margin-left: auto;">{token_count} tokens budget</span>
64
- <div class="chevron" id="chevron_{thinking_id}"
65
- style="width: 16px; height: 16px; border: 2px solid #888; border-left: none;
66
- border-bottom: none; transform: rotate(45deg); transition: transform 0.2s ease;"></div>
67
- </div>
68
- <div class="thinking-content" id="{thinking_id}"
69
- style="background: #333; border-radius: 0 0 8px 8px; padding: 20px;
70
- border: 1px solid #4a4a4a; border-top: none; display: none;
71
- max-height: 400px; overflow-y: auto;">
72
- <div style="white-space: pre-wrap; font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
73
- font-size: 14px; line-height: 1.5; color: #d0d0d0;">{thinking_content}</div>
74
- </div>
75
- </div>
76
-
77
- <script>
78
- function toggleThinking(id) {{
79
- const content = document.getElementById(id);
80
- const chevron = document.getElementById('chevron_' + id);
81
- const header = content.previousElementSibling;
82
-
83
- if (content.style.display === 'none' || !content.style.display) {{
84
- content.style.display = 'block';
85
- chevron.style.transform = 'rotate(135deg)';
86
- header.style.background = '#404040';
87
- }} else {{
88
- content.style.display = 'none';
89
- chevron.style.transform = 'rotate(45deg)';
90
- header.style.background = '#3a3a3a';
91
- }}
92
- }}
93
- </script>
94
- """
95
- return html
96
-
97
- def format_response_with_thinking(response_text):
98
- """Format response to include thinking blocks"""
99
- parts = parse_thinking_tags(response_text)
100
-
101
- if not parts:
102
- return response_text
103
-
104
- formatted_html = ""
105
-
106
- for part in parts:
107
- if part["type"] == "thinking":
108
- formatted_html += create_thinking_html(part["content"])
109
- else:
110
- # Regular text content
111
- formatted_html += f'<div style="margin: 16px 0; line-height: 1.6; color: #e0e0e0;">{part["content"]}</div>'
112
-
113
- return formatted_html
114
 
115
  @spaces.GPU
116
  def initialize_model(model_name):
@@ -151,7 +69,7 @@ def generate_response(message, history, model_name, max_length=512, temperature=
151
  try:
152
  model_pipe = initialize_model(model_name)
153
  except Exception as e:
154
- return f"Error loading model {model_name}: {str(e)}"
155
 
156
  # Format the conversation history
157
  messages = []
@@ -160,9 +78,7 @@ def generate_response(message, history, model_name, max_length=512, temperature=
160
  for user_msg, assistant_msg in history:
161
  messages.append({"role": "user", "content": user_msg})
162
  if assistant_msg:
163
- # Parse HTML back to get original content if needed
164
- clean_assistant_msg = re.sub(r'<[^>]+>', '', assistant_msg) if assistant_msg else ""
165
- messages.append({"role": "assistant", "content": clean_assistant_msg})
166
 
167
  # Add current message
168
  messages.append({"role": "user", "content": message})
@@ -216,13 +132,13 @@ def generate_response(message, history, model_name, max_length=512, temperature=
216
  if "Assistant:" in assistant_response:
217
  assistant_response = assistant_response.split("Assistant:")[-1].strip()
218
 
219
- # Format the response with thinking blocks
220
- formatted_response = format_response_with_thinking(assistant_response)
221
 
222
- return formatted_response
223
 
224
  except Exception as e:
225
- return f"Error generating response: {str(e)}"
226
 
227
  @spaces.GPU
228
  def generate(
@@ -284,54 +200,13 @@ def generate(
284
  if system_prompt and system_prompt.strip():
285
  final_user_input = f"System: {system_prompt}\n\nUser: {user_input}"
286
 
287
- # Use the original generate_response function
288
- return generate_response(final_user_input, gradio_history, model, max_tokens, temperature, 0.9)
 
289
 
290
  # Create the Gradio interface
291
  def create_interface():
292
- # Custom CSS for dark theme and thinking blocks
293
- custom_css = """
294
- .dark {
295
- background: #1a1a1a !important;
296
- }
297
-
298
- .chatbot .message-wrap .message {
299
- background: #2a2a2a !important;
300
- border: 1px solid #3a3a3a !important;
301
- }
302
-
303
- .chatbot .message-wrap .message.user {
304
- background: #2d3748 !important;
305
- }
306
-
307
- .chatbot .message-wrap .message.bot {
308
- background: #2a2a2a !important;
309
- }
310
-
311
- .thinking-container {
312
- margin: 16px 0;
313
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
314
- }
315
-
316
- .thinking-header {
317
- background: #3a3a3a;
318
- border-radius: 8px;
319
- padding: 12px 16px;
320
- cursor: pointer;
321
- display: flex;
322
- align-items: center;
323
- gap: 10px;
324
- transition: all 0.2s ease;
325
- border: 1px solid #4a4a4a;
326
- }
327
-
328
- .thinking-header:hover {
329
- background: #404040 !important;
330
- border-color: #5a5a5a !important;
331
- }
332
- """
333
-
334
- with gr.Blocks(title="Multi-Model Chat", theme=gr.themes.Soft(), css=custom_css) as demo:
335
  gr.Markdown("""
336
  # 🚀 Daedalus-1 Model Chat Interface
337
 
@@ -349,13 +224,24 @@ def create_interface():
349
  info="Choose which model to use for generation"
350
  )
351
 
352
- chatbot = gr.Chatbot(
353
- height=500,
354
- placeholder="Select a model and start chatting...",
355
- label="Chat",
356
- render_markdown=False, # Disable markdown to allow custom HTML
357
- elem_classes=["chatbot"]
358
- )
 
 
 
 
 
 
 
 
 
 
 
359
 
360
  msg = gr.Textbox(
361
  placeholder="Type your message here...",
@@ -393,29 +279,6 @@ def create_interface():
393
  info="Controls diversity via nucleus sampling"
394
  )
395
 
396
- # Add JavaScript for thinking block interactions
397
- gr.HTML("""
398
- <script>
399
- function toggleThinking(id) {
400
- const content = document.getElementById(id);
401
- if (!content) return;
402
-
403
- const chevron = document.getElementById('chevron_' + id);
404
- const header = content.previousElementSibling;
405
-
406
- if (content.style.display === 'none' || !content.style.display) {
407
- content.style.display = 'block';
408
- if (chevron) chevron.style.transform = 'rotate(135deg)';
409
- if (header) header.style.background = '#404040';
410
- } else {
411
- content.style.display = 'none';
412
- if (chevron) chevron.style.transform = 'rotate(45deg)';
413
- if (header) header.style.background = '#3a3a3a';
414
- }
415
- }
416
- </script>
417
- """)
418
-
419
  # Event handlers
420
  def user_message(message, history):
421
  return "", history + [[message, None]]
@@ -423,7 +286,7 @@ def create_interface():
423
  def bot_response(history, model_name, max_len, temp, top_p):
424
  if history:
425
  user_message = history[-1][0]
426
- bot_message = generate_response(
427
  user_message,
428
  history[:-1],
429
  model_name,
@@ -431,27 +294,41 @@ def create_interface():
431
  temp,
432
  top_p
433
  )
434
- history[-1][1] = bot_message
435
- return history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
 
437
  def model_changed(model_name):
438
  return gr.update(placeholder=f"Chat with {model_name}...")
439
 
440
  # Wire up the events
441
- msg.submit(user_message, [msg, chatbot], [msg, chatbot]).then(
442
- bot_response, [chatbot, model_selector, max_length, temperature, top_p], chatbot
 
443
  )
444
 
445
- submit_btn.click(user_message, [msg, chatbot], [msg, chatbot]).then(
446
- bot_response, [chatbot, model_selector, max_length, temperature, top_p], chatbot
 
447
  )
448
 
449
- clear_btn.click(lambda: None, None, chatbot, queue=False)
450
 
451
  model_selector.change(model_changed, model_selector, chatbot)
452
 
453
-
454
-
455
  gr.Markdown("""
456
  ---
457
 
@@ -463,7 +340,7 @@ def create_interface():
463
 
464
 
465
  The model is designed for conversational AI and supports various text generation tasks. When the model uses thinking tags (`<think></think>`),
466
- this interface will render them as expandable sections similar to Claude's thinking process visualization.
467
 
468
  This Space uses ZeroGPU for efficient GPU allocation.
469
  """)
 
15
  }
16
 
17
  def parse_thinking_tags(text):
18
+ """Parse text and extract thinking sections, return clean text and thinking content"""
19
  think_pattern = r'<think>(.*?)</think>'
20
+ thinking_blocks = []
 
21
 
22
+ # Extract all thinking blocks
23
  for match in re.finditer(think_pattern, text, re.DOTALL):
 
 
 
 
 
 
 
24
  thinking_content = match.group(1).strip()
25
  if thinking_content:
26
+ thinking_blocks.append(thinking_content)
 
 
27
 
28
+ # Remove thinking tags from the main text
29
+ clean_text = re.sub(think_pattern, '', text, flags=re.DOTALL).strip()
 
 
 
30
 
31
+ return clean_text, thinking_blocks
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  @spaces.GPU
34
  def initialize_model(model_name):
 
69
  try:
70
  model_pipe = initialize_model(model_name)
71
  except Exception as e:
72
+ return f"Error loading model {model_name}: {str(e)}", []
73
 
74
  # Format the conversation history
75
  messages = []
 
78
  for user_msg, assistant_msg in history:
79
  messages.append({"role": "user", "content": user_msg})
80
  if assistant_msg:
81
+ messages.append({"role": "assistant", "content": assistant_msg})
 
 
82
 
83
  # Add current message
84
  messages.append({"role": "user", "content": message})
 
132
  if "Assistant:" in assistant_response:
133
  assistant_response = assistant_response.split("Assistant:")[-1].strip()
134
 
135
+ # Parse thinking tags
136
+ clean_response, thinking_blocks = parse_thinking_tags(assistant_response)
137
 
138
+ return clean_response, thinking_blocks
139
 
140
  except Exception as e:
141
+ return f"Error generating response: {str(e)}", []
142
 
143
  @spaces.GPU
144
  def generate(
 
200
  if system_prompt and system_prompt.strip():
201
  final_user_input = f"System: {system_prompt}\n\nUser: {user_input}"
202
 
203
+ # Use the generate_response function and return only the clean response
204
+ clean_response, thinking_blocks = generate_response(final_user_input, gradio_history, model, max_tokens, temperature, 0.9)
205
+ return clean_response
206
 
207
  # Create the Gradio interface
208
  def create_interface():
209
+ with gr.Blocks(title="Multi-Model Chat", theme=gr.themes.Soft()) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  gr.Markdown("""
211
  # 🚀 Daedalus-1 Model Chat Interface
212
 
 
224
  info="Choose which model to use for generation"
225
  )
226
 
227
+ with gr.Row():
228
+ with gr.Column(scale=2):
229
+ chatbot = gr.Chatbot(
230
+ height=500,
231
+ placeholder="Select a model and start chatting...",
232
+ label="Chat"
233
+ )
234
+
235
+ with gr.Column(scale=1):
236
+ thinking_display = gr.Accordion("💭 Thinking Process", open=True, visible=False)
237
+ with thinking_display:
238
+ thinking_content = gr.Textbox(
239
+ label="Model's Thinking",
240
+ lines=15,
241
+ interactive=False,
242
+ show_label=False,
243
+ container=False
244
+ )
245
 
246
  msg = gr.Textbox(
247
  placeholder="Type your message here...",
 
279
  info="Controls diversity via nucleus sampling"
280
  )
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  # Event handlers
283
  def user_message(message, history):
284
  return "", history + [[message, None]]
 
286
  def bot_response(history, model_name, max_len, temp, top_p):
287
  if history:
288
  user_message = history[-1][0]
289
+ clean_response, thinking_blocks = generate_response(
290
  user_message,
291
  history[:-1],
292
  model_name,
 
294
  temp,
295
  top_p
296
  )
297
+
298
+ # Update chat with clean response
299
+ history[-1][1] = clean_response
300
+
301
+ # Format thinking content for display
302
+ thinking_text = ""
303
+ if thinking_blocks:
304
+ for i, thinking in enumerate(thinking_blocks, 1):
305
+ thinking_text += f"=== Thinking Block {i} ===\n\n{thinking}\n\n"
306
+
307
+ return history, thinking_text, gr.update(visible=bool(thinking_blocks))
308
+
309
+ return history, "", gr.update(visible=False)
310
+
311
+ def clear_chat():
312
+ return None, "", gr.update(visible=False)
313
 
314
  def model_changed(model_name):
315
  return gr.update(placeholder=f"Chat with {model_name}...")
316
 
317
  # Wire up the events
318
+ msg_submit = msg.submit(user_message, [msg, chatbot], [msg, chatbot]).then(
319
+ bot_response, [chatbot, model_selector, max_length, temperature, top_p],
320
+ [chatbot, thinking_content, thinking_display]
321
  )
322
 
323
+ btn_submit = submit_btn.click(user_message, [msg, chatbot], [msg, chatbot]).then(
324
+ bot_response, [chatbot, model_selector, max_length, temperature, top_p],
325
+ [chatbot, thinking_content, thinking_display]
326
  )
327
 
328
+ clear_btn.click(clear_chat, None, [chatbot, thinking_content, thinking_display], queue=False)
329
 
330
  model_selector.change(model_changed, model_selector, chatbot)
331
 
 
 
332
  gr.Markdown("""
333
  ---
334
 
 
340
 
341
 
342
  The model is designed for conversational AI and supports various text generation tasks. When the model uses thinking tags (`<think></think>`),
343
+ this interface will show the thinking process in a separate panel on the right.
344
 
345
  This Space uses ZeroGPU for efficient GPU allocation.
346
  """)