Cherrytest commited on
Commit
fa891b1
·
1 Parent(s): 8411a7d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +230 -180
app.py CHANGED
@@ -5,7 +5,6 @@ import mimetypes
5
  import os
6
  import requests
7
  import time
8
- import modelscope_studio.components.legacy as legacy
9
  import modelscope_studio.components.antd as antd
10
  import modelscope_studio.components.antdx as antdx
11
  import modelscope_studio.components.base as ms
@@ -16,7 +15,6 @@ from modelscope_studio.components.pro.chatbot import (
16
  from config import DEFAULT_PROMPTS, EXAMPLES, SystemPrompt
17
  import re
18
 
19
-
20
  MODEL_VERSION = os.environ['MODEL_VERSION']
21
  API_URL = os.environ['API_URL']
22
  API_KEY = os.environ['API_KEY']
@@ -42,8 +40,9 @@ def clear():
42
  def retry(chatbot_value, e: gr.EventData):
43
  index = e._data["payload"][0]["index"]
44
  chatbot_value = chatbot_value[:index]
45
-
46
- yield gr.update(loading=True), gr.update(value=chatbot_value), gr.update(disabled=True)
 
47
  for chunk in submit(None, chatbot_value):
48
  yield chunk
49
 
@@ -52,7 +51,8 @@ def cancel(chatbot_value):
52
  chatbot_value[-1]["loading"] = False
53
  chatbot_value[-1]["status"] = "done"
54
  chatbot_value[-1]["footer"] = "Chat completion paused"
55
- return gr.update(value=chatbot_value), gr.update(loading=False), gr.update(disabled=False)
 
56
 
57
 
58
  def add_name_for_message(message):
@@ -109,7 +109,7 @@ def format_history(history):
109
  'role': 'system',
110
  'content': SYSTEM_PROMPT,
111
  })
112
-
113
  for item in history:
114
  if item["role"] == "user":
115
  messages.append({
@@ -120,7 +120,7 @@ def format_history(history):
120
  # Extract reasoning content and main content
121
  reasoning_content = ""
122
  main_content = ""
123
-
124
  if isinstance(item["content"], list):
125
  for content_item in item["content"]:
126
  if content_item.get("type") == "tool":
@@ -129,13 +129,16 @@ def format_history(history):
129
  main_content = content_item.get("content", "")
130
  else:
131
  main_content = item["content"]
132
-
133
  messages.append({
134
- 'role': 'assistant',
135
- 'content': convert_content(main_content),
136
- 'reasoning_content': convert_content(reasoning_content),
 
 
 
137
  })
138
-
139
  return messages
140
 
141
 
@@ -145,25 +148,25 @@ def submit(sender_value, chatbot_value):
145
  "role": "user",
146
  "content": sender_value,
147
  })
148
-
149
  api_messages = format_history(chatbot_value)
150
-
151
  for message in api_messages:
152
  add_name_for_message(message)
153
-
154
  chatbot_value.append({
155
  "role": "assistant",
156
  "content": [],
157
  "loading": True,
158
  "status": "pending"
159
  })
160
-
161
  yield {
162
  sender: gr.update(value=None, loading=True),
163
  clear_btn: gr.update(disabled=True),
164
  chatbot: gr.update(value=chatbot_value)
165
  }
166
-
167
  try:
168
  data = {
169
  'model': MODEL_VERSION,
@@ -173,7 +176,7 @@ def submit(sender_value, chatbot_value):
173
  'temperature': MODEL_CONTROL_DEFAULTS['temperature'],
174
  'top_p': MODEL_CONTROL_DEFAULTS['top_p'],
175
  }
176
-
177
  r = requests.post(
178
  API_URL,
179
  headers={
@@ -183,11 +186,11 @@ def submit(sender_value, chatbot_value):
183
  data=json.dumps(data),
184
  stream=True,
185
  )
186
-
187
  thought_done = False
188
  start_time = time.time()
189
  message_content = chatbot_value[-1]["content"]
190
-
191
  # Reasoning content (tool type)
192
  message_content.append({
193
  "type": "tool",
@@ -196,83 +199,97 @@ def submit(sender_value, chatbot_value):
196
  "title": "🤔 Thinking..."
197
  }
198
  })
199
-
200
  # Main content (text type)
201
  message_content.append({
202
  "type": "text",
203
  "content": "",
204
  })
205
-
206
  reasoning_start_time = None
207
  reasoning_duration = None
208
-
209
  for row in r.iter_lines():
210
  if row.startswith(b'data:'):
211
  data = json.loads(row[5:])
212
  if 'choices' not in data:
213
  raise gr.Error('request failed')
214
  choice = data['choices'][0]
215
-
216
  if 'delta' in choice:
217
  delta = choice['delta']
218
  reasoning_content = delta.get('reasoning_content', '')
219
  content = delta.get('content', '')
220
-
221
  chatbot_value[-1]["loading"] = False
222
-
223
  # Handle reasoning content
224
  if reasoning_content:
225
  if reasoning_start_time is None:
226
  reasoning_start_time = time.time()
227
  message_content[-2]["content"] += reasoning_content
228
-
229
  # Handle main content
230
  if content:
231
  message_content[-1]["content"] += content
232
-
233
  if not thought_done:
234
  thought_done = True
235
  if reasoning_start_time is not None:
236
- reasoning_duration = time.time() - reasoning_start_time
237
- thought_cost_time = "{:.2f}".format(reasoning_duration)
 
 
238
  else:
239
  reasoning_duration = 0.0
240
  thought_cost_time = "0.00"
241
- message_content[-2]["options"] = {"title": f"End of Thought ({thought_cost_time}s)"}
 
 
 
 
242
 
243
  yield {chatbot: gr.update(value=chatbot_value)}
244
-
245
  elif 'message' in choice:
246
  message_data = choice['message']
247
- reasoning_content = message_data.get('reasoning_content', '')
 
248
  main_content = message_data.get('content', '')
249
-
250
  message_content[-2]["content"] = reasoning_content
251
  message_content[-1]["content"] = main_content
252
-
253
  if reasoning_content and main_content:
254
  if reasoning_duration is None:
255
  if reasoning_start_time is not None:
256
- reasoning_duration = time.time() - reasoning_start_time
257
- thought_cost_time = "{:.2f}".format(reasoning_duration)
 
 
258
  else:
259
  reasoning_duration = 0.0
260
  thought_cost_time = "0.00"
261
  else:
262
- thought_cost_time = "{:.2f}".format(reasoning_duration)
263
- message_content[-2]["options"] = {"title": f"End of Thought ({thought_cost_time}s)"}
264
-
 
 
 
 
265
  chatbot_value[-1]["loading"] = False
266
  yield {chatbot: gr.update(value=chatbot_value)}
267
 
268
- chatbot_value[-1]["footer"] = "{:.2f}s".format(time.time() - start_time)
 
269
  chatbot_value[-1]["status"] = "done"
270
  yield {
271
  clear_btn: gr.update(disabled=False),
272
  sender: gr.update(loading=False),
273
  chatbot: gr.update(value=chatbot_value),
274
  }
275
-
276
  except Exception as e:
277
  chatbot_value[-1]["loading"] = False
278
  chatbot_value[-1]["status"] = "done"
@@ -292,22 +309,24 @@ def remove_code_block(text):
292
  r'```\n([\s\S]+?)\n```', # Match code blocks without language markers
293
  r'```([\s\S]+?)```' # Match code blocks without line breaks
294
  ]
295
-
296
  for pattern in patterns:
297
  match = re.search(pattern, text, re.DOTALL)
298
  if match:
299
  extracted = match.group(1).strip()
300
  print("Successfully extracted code block:", extracted)
301
  return extracted
302
-
303
  # If no code block is found, check if the entire text is HTML
304
- if text.strip().startswith('<!DOCTYPE html>') or text.strip().startswith('<html'):
 
305
  print("Text appears to be raw HTML, using as is")
306
  return text.strip()
307
-
308
  print("No code block found in text:", text)
309
  return text.strip()
310
 
 
311
  def send_to_sandbox(code):
312
  # Add a wrapper to inject necessary permissions
313
  wrapped_code = f"""
@@ -351,17 +370,20 @@ def send_to_sandbox(code):
351
  </body>
352
  </html>
353
  """
354
- encoded_html = base64.b64encode(wrapped_code.encode('utf-8')).decode('utf-8')
 
355
  data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
356
  iframe = f'<iframe src="{data_uri}" width="100%" height="920px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-presentation" allow="display-capture"></iframe>'
357
  print("Generated iframe:", iframe)
358
  return iframe
359
 
 
360
  def select_example(example):
361
  if isinstance(example, dict):
362
  return example.get("description", "")
363
  return ""
364
 
 
365
  def generate_code(query: str):
366
  if not query:
367
  return {
@@ -372,7 +394,7 @@ def generate_code(query: str):
372
  output_tabs: gr.update(active_key="reasoning", visible=False),
373
  loading: gr.update(tip="Thinking...")
374
  }
375
-
376
  print("Starting code generation with query:", query)
377
  messages = [{
378
  'role': 'system',
@@ -381,10 +403,10 @@ def generate_code(query: str):
381
  'role': 'user',
382
  'content': query
383
  }]
384
-
385
  max_retries = 3
386
  retry_count = 0
387
-
388
  while retry_count < max_retries:
389
  try:
390
  data = {
@@ -395,8 +417,10 @@ def generate_code(query: str):
395
  'temperature': MODEL_CONTROL_DEFAULTS['temperature'],
396
  'top_p': MODEL_CONTROL_DEFAULTS['top_p'],
397
  }
398
-
399
- print(f"Attempt {retry_count + 1}: Sending request to API with data:", json.dumps(data, indent=2))
 
 
400
  r = requests.post(
401
  API_URL,
402
  headers={
@@ -407,76 +431,101 @@ def generate_code(query: str):
407
  stream=True,
408
  timeout=60 # Set 60 seconds timeout
409
  )
410
-
411
  content = ""
412
  reasoning_content = ""
413
  loading_text = "Thinking..."
414
-
415
  for row in r.iter_lines():
416
  if row.startswith(b'data:'):
417
  data = json.loads(row[5:])
418
- print("Received data from API:", json.dumps(data, indent=2))
 
419
  if 'choices' not in data:
420
  raise gr.Error('request failed')
421
  choice = data['choices'][0]
422
-
423
  if 'delta' in choice:
424
  delta = choice['delta']
425
  content += delta.get('content', '')
426
  reasoning_content += delta.get('reasoning_content', '')
427
-
428
  # Update loading text based on content
429
  if content and not loading_text == "Generating code...":
430
  loading_text = "Generating code..."
431
  yield {
432
- code_output: gr.update(value=content),
433
- reasoning_output: gr.update(value=reasoning_content + "\n"),
434
- sandbox: gr.update(value=None),
435
- state_tab: gr.update(active_key="loading"),
436
- output_tabs: gr.update(active_key="reasoning", visible=True),
437
- loading: gr.update(tip=loading_text)
 
 
 
 
 
 
 
438
  }
439
  else:
440
  yield {
441
- code_output: gr.update(value=content),
442
- reasoning_output: gr.update(value=reasoning_content + "\n"),
443
- sandbox: gr.update(value=None),
444
- state_tab: gr.update(active_key="loading"),
445
- output_tabs: gr.update(active_key="reasoning", visible=True),
446
- loading: gr.update(tip=loading_text)
 
 
 
 
 
 
 
447
  }
448
  elif 'message' in choice:
449
  message_data = choice['message']
450
  content = message_data.get('content', '')
451
- reasoning_content = message_data.get('reasoning_content', '')
 
452
  print("Final content:", content)
453
  print("Final reasoning:", reasoning_content)
454
  html_content = remove_code_block(content)
455
  print("Extracted HTML:", html_content)
456
  yield {
457
- code_output: gr.update(value=content),
458
- reasoning_output: gr.update(value=reasoning_content + "\n"),
459
- sandbox: gr.update(value=send_to_sandbox(html_content)),
460
- state_tab: gr.update(active_key="render"),
461
- output_tabs: gr.update(active_key="code", visible=True),
462
- loading: gr.update(tip="Done")
 
 
 
 
 
 
463
  }
464
-
465
  # If successful, break out of retry loop
466
  break
467
-
468
- except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
 
469
  retry_count += 1
470
  if retry_count == max_retries:
471
  print(f"Failed after {max_retries} attempts:", str(e))
472
- raise gr.Error(f"Request failed after {max_retries} attempts: {str(e)}")
 
473
  print(f"Attempt {retry_count} failed, retrying...")
474
  time.sleep(1) # Wait 1 second before retrying
475
-
476
  except Exception as e:
477
  print("Error occurred:", str(e))
478
  raise gr.Error(str(e))
479
 
 
480
  css = """
481
  /* Add styles for the main container */
482
  .ant-tabs-content {
@@ -490,27 +539,25 @@ css = """
490
  }
491
 
492
  /* Modify existing styles */
493
- .output-loading {
494
  display: flex;
495
  flex-direction: column;
496
  align-items: center;
497
  justify-content: center;
498
  width: 100%;
499
- height: 100%;
500
- min-height: unset;
501
  }
502
 
503
  .output-html {
504
  display: flex;
505
  flex-direction: column;
506
  width: 100%;
507
- height: 100%;
508
- min-height: unset;
509
- background: #fff;
510
- border-radius: 8px;
511
- border: 1px solid #e8e8e8;
512
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
513
- overflow: hidden;
514
  }
515
 
516
  .right_content {
@@ -588,19 +635,16 @@ css = """
588
  }
589
 
590
  .reasoning-box {
591
- height: 300px;
592
  overflow-y: auto;
593
- background-color: #f5f5f5;
594
  border-radius: 4px;
595
- margin-bottom: 12px;
596
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
597
  font-size: 14px;
598
- line-height: 1.2;
599
- white-space: pre-wrap;
600
- word-break: break-word;
601
  width: 100%;
602
- box-sizing: border-box;
603
  scroll-behavior: smooth;
 
 
604
  }
605
 
606
  .reasoning-box .ms-markdown {
@@ -626,19 +670,16 @@ css = """
626
  }
627
 
628
  .markdown-container {
629
- height: 300px;
630
  overflow-y: auto;
631
- background-color: #f5f5f5;
632
  border-radius: 4px;
633
- margin-bottom: 12px;
634
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
635
  font-size: 14px;
636
  line-height: 1.6;
637
- white-space: pre-wrap;
638
- word-break: break-word;
639
  width: 100%;
640
- box-sizing: border-box;
641
  scroll-behavior: smooth;
 
 
642
  }
643
 
644
  /* Example card styles */
@@ -710,6 +751,7 @@ css = """
710
  }
711
  """
712
 
 
713
  def scroll_to_bottom():
714
  return """
715
  function() {
@@ -726,13 +768,18 @@ def scroll_to_bottom():
726
  }
727
  """
728
 
729
- with gr.Blocks(css=css) as demo, ms.Application(), antdx.XProvider():
 
 
730
  with antd.Tabs() as tabs:
731
  with antd.Tabs.Item(key="chat", label="Chatbot"):
732
- with antd.Flex(vertical=True, gap="middle"):
 
 
733
  chatbot = pro.Chatbot(
734
- height="calc(100vh - 200px)",
735
- markdown_config=ChatbotMarkdownConfig(allow_tags=["think"]),
 
736
  welcome_config=ChatbotWelcomeConfig(
737
  variant="borderless",
738
  icon="./assets/minimax-logo.png",
@@ -748,20 +795,18 @@ with gr.Blocks(css=css) as demo, ms.Application(), antdx.XProvider():
748
  "flex": 1,
749
  },
750
  },
751
- items=DEFAULT_PROMPTS
752
- )
753
- ),
754
  user_config=ChatbotUserConfig(actions=["copy", "edit"]),
755
  bot_config=ChatbotBotConfig(
756
  header=MODEL_NAME,
757
  avatar="./assets/minimax-logo.png",
758
- actions=["copy", "retry"]
759
- )
760
- )
761
 
762
  with antdx.Sender() as sender:
763
  with ms.Slot("prefix"):
764
- with antd.Button(value=None, color="default", variant="text") as clear_btn:
 
 
765
  with ms.Slot("icon"):
766
  antd.Icon("ClearOutlined")
767
 
@@ -769,93 +814,98 @@ with gr.Blocks(css=css) as demo, ms.Application(), antdx.XProvider():
769
  submit_event = sender.submit(
770
  fn=submit,
771
  inputs=[sender, chatbot],
772
- outputs=[sender, chatbot, clear_btn]
773
- )
774
- sender.cancel(
775
- fn=cancel,
776
- inputs=[chatbot],
777
- outputs=[chatbot, sender, clear_btn],
778
- cancels=[submit_event],
779
- queue=False
780
- )
781
- chatbot.retry(
782
- fn=retry,
783
- inputs=[chatbot],
784
- outputs=[sender, chatbot, clear_btn]
785
- )
786
- chatbot.welcome_prompt_select(fn=prompt_select, outputs=[sender])
787
 
788
  with antd.Tabs.Item(key="code", label="Code Playground (WebDev)"):
789
- with antd.Row(gutter=[32, 12], elem_classes="code-playground-container"):
790
- with antd.Col(span=12):
 
791
  with antd.Flex(vertical=True, gap="middle"):
792
- code_input = antd.InputTextarea(
793
  size="large",
794
  allow_clear=True,
795
- placeholder="Please enter what kind of application you want or choose an example below and click the button"
 
 
796
  )
797
- code_btn = antd.Button("Generate Code", type="primary", size="large")
798
- with antd.Tabs(active_key="reasoning", visible=False) as output_tabs:
799
- with antd.Tabs.Item(key="reasoning", label="🤔 Thinking Process"):
800
- reasoning_output = legacy.Markdown(
801
- elem_classes="reasoning-box"
802
- )
803
- with antd.Tabs.Item(key="code", label="💻 Generated Code"):
804
- code_output = legacy.Markdown(elem_classes="markdown-container")
805
-
 
 
 
 
 
806
  antd.Divider("Examples")
807
 
808
  # Examples with categories
809
- with antd.Tabs(elem_classes="example-tabs") as example_tabs:
 
810
  for category, examples in EXAMPLES.items():
811
- with antd.Tabs.Item(key=category, label=category):
 
812
  with antd.Flex(gap="small", wrap=True):
813
  for example in examples:
814
  with antd.Card(
815
- elem_classes="example-card",
816
- hoverable=True
817
  ) as example_card:
818
  antd.Card.Meta(
819
  title=example['title'],
820
- description=example['description']
821
- )
822
 
823
  example_card.click(
824
  fn=select_example,
825
  inputs=[gr.State(example)],
826
- outputs=[code_input]
827
- )
828
-
829
- with antd.Col(span=12):
830
- with ms.Div(elem_classes="right_panel"):
831
- gr.HTML('''
832
- <div class="render_header">
833
- <span class="header_btn"></span>
834
- <span class="header_btn"></span>
835
- <span class="header_btn"></span>
836
- </div>
837
- ''')
838
-
839
- with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab:
840
  with antd.Tabs.Item(key="empty"):
841
- empty = antd.Empty(description="empty input", elem_classes="right_content")
 
 
 
842
  with antd.Tabs.Item(key="loading"):
843
- loading = antd.Spin(True, tip="Thinking and coding...", size="large", elem_classes="output-loading")
 
 
 
 
 
 
844
  with antd.Tabs.Item(key="render"):
845
  sandbox = gr.HTML(elem_classes="output-html")
846
 
847
- code_btn.click(
848
- generate_code,
849
- inputs=[code_input],
850
- outputs=[
851
- code_output,
852
- reasoning_output,
853
- sandbox,
854
- state_tab,
855
- output_tabs,
856
- loading
857
- ]
858
- )
859
 
860
  # Add auto-scroll functionality
861
  reasoning_output.change(
@@ -869,14 +919,14 @@ with gr.Blocks(css=css) as demo, ms.Application(), antdx.XProvider():
869
  outputs=[],
870
  )
871
 
872
- def on_tab_change(tab_key):
 
873
  return gr.update(active_key=tab_key, visible=True)
874
 
875
  output_tabs.change(
876
  fn=on_tab_change,
877
- inputs=[output_tabs],
878
  outputs=[output_tabs],
879
  )
880
 
881
  if __name__ == '__main__':
882
- demo.queue(default_concurrency_limit=50).launch(ssr_mode=False)
 
5
  import os
6
  import requests
7
  import time
 
8
  import modelscope_studio.components.antd as antd
9
  import modelscope_studio.components.antdx as antdx
10
  import modelscope_studio.components.base as ms
 
15
  from config import DEFAULT_PROMPTS, EXAMPLES, SystemPrompt
16
  import re
17
 
 
18
  MODEL_VERSION = os.environ['MODEL_VERSION']
19
  API_URL = os.environ['API_URL']
20
  API_KEY = os.environ['API_KEY']
 
40
  def retry(chatbot_value, e: gr.EventData):
41
  index = e._data["payload"][0]["index"]
42
  chatbot_value = chatbot_value[:index]
43
+
44
+ yield gr.update(loading=True), gr.update(value=chatbot_value), gr.update(
45
+ disabled=True)
46
  for chunk in submit(None, chatbot_value):
47
  yield chunk
48
 
 
51
  chatbot_value[-1]["loading"] = False
52
  chatbot_value[-1]["status"] = "done"
53
  chatbot_value[-1]["footer"] = "Chat completion paused"
54
+ return gr.update(value=chatbot_value), gr.update(loading=False), gr.update(
55
+ disabled=False)
56
 
57
 
58
  def add_name_for_message(message):
 
109
  'role': 'system',
110
  'content': SYSTEM_PROMPT,
111
  })
112
+
113
  for item in history:
114
  if item["role"] == "user":
115
  messages.append({
 
120
  # Extract reasoning content and main content
121
  reasoning_content = ""
122
  main_content = ""
123
+
124
  if isinstance(item["content"], list):
125
  for content_item in item["content"]:
126
  if content_item.get("type") == "tool":
 
129
  main_content = content_item.get("content", "")
130
  else:
131
  main_content = item["content"]
132
+
133
  messages.append({
134
+ 'role':
135
+ 'assistant',
136
+ 'content':
137
+ convert_content(main_content),
138
+ 'reasoning_content':
139
+ convert_content(reasoning_content),
140
  })
141
+
142
  return messages
143
 
144
 
 
148
  "role": "user",
149
  "content": sender_value,
150
  })
151
+
152
  api_messages = format_history(chatbot_value)
153
+
154
  for message in api_messages:
155
  add_name_for_message(message)
156
+
157
  chatbot_value.append({
158
  "role": "assistant",
159
  "content": [],
160
  "loading": True,
161
  "status": "pending"
162
  })
163
+
164
  yield {
165
  sender: gr.update(value=None, loading=True),
166
  clear_btn: gr.update(disabled=True),
167
  chatbot: gr.update(value=chatbot_value)
168
  }
169
+
170
  try:
171
  data = {
172
  'model': MODEL_VERSION,
 
176
  'temperature': MODEL_CONTROL_DEFAULTS['temperature'],
177
  'top_p': MODEL_CONTROL_DEFAULTS['top_p'],
178
  }
179
+
180
  r = requests.post(
181
  API_URL,
182
  headers={
 
186
  data=json.dumps(data),
187
  stream=True,
188
  )
189
+
190
  thought_done = False
191
  start_time = time.time()
192
  message_content = chatbot_value[-1]["content"]
193
+
194
  # Reasoning content (tool type)
195
  message_content.append({
196
  "type": "tool",
 
199
  "title": "🤔 Thinking..."
200
  }
201
  })
202
+
203
  # Main content (text type)
204
  message_content.append({
205
  "type": "text",
206
  "content": "",
207
  })
208
+
209
  reasoning_start_time = None
210
  reasoning_duration = None
211
+
212
  for row in r.iter_lines():
213
  if row.startswith(b'data:'):
214
  data = json.loads(row[5:])
215
  if 'choices' not in data:
216
  raise gr.Error('request failed')
217
  choice = data['choices'][0]
218
+
219
  if 'delta' in choice:
220
  delta = choice['delta']
221
  reasoning_content = delta.get('reasoning_content', '')
222
  content = delta.get('content', '')
223
+
224
  chatbot_value[-1]["loading"] = False
225
+
226
  # Handle reasoning content
227
  if reasoning_content:
228
  if reasoning_start_time is None:
229
  reasoning_start_time = time.time()
230
  message_content[-2]["content"] += reasoning_content
231
+
232
  # Handle main content
233
  if content:
234
  message_content[-1]["content"] += content
235
+
236
  if not thought_done:
237
  thought_done = True
238
  if reasoning_start_time is not None:
239
+ reasoning_duration = time.time(
240
+ ) - reasoning_start_time
241
+ thought_cost_time = "{:.2f}".format(
242
+ reasoning_duration)
243
  else:
244
  reasoning_duration = 0.0
245
  thought_cost_time = "0.00"
246
+ message_content[-2]["options"] = {
247
+ "title":
248
+ f"End of Thought ({thought_cost_time}s)",
249
+ "status": "done"
250
+ }
251
 
252
  yield {chatbot: gr.update(value=chatbot_value)}
253
+
254
  elif 'message' in choice:
255
  message_data = choice['message']
256
+ reasoning_content = message_data.get(
257
+ 'reasoning_content', '')
258
  main_content = message_data.get('content', '')
259
+
260
  message_content[-2]["content"] = reasoning_content
261
  message_content[-1]["content"] = main_content
262
+
263
  if reasoning_content and main_content:
264
  if reasoning_duration is None:
265
  if reasoning_start_time is not None:
266
+ reasoning_duration = time.time(
267
+ ) - reasoning_start_time
268
+ thought_cost_time = "{:.2f}".format(
269
+ reasoning_duration)
270
  else:
271
  reasoning_duration = 0.0
272
  thought_cost_time = "0.00"
273
  else:
274
+ thought_cost_time = "{:.2f}".format(
275
+ reasoning_duration)
276
+ message_content[-2]["options"] = {
277
+ "title": f"End of Thought ({thought_cost_time}s)",
278
+ "status": "done"
279
+ }
280
+
281
  chatbot_value[-1]["loading"] = False
282
  yield {chatbot: gr.update(value=chatbot_value)}
283
 
284
+ chatbot_value[-1]["footer"] = "{:.2f}s".format(time.time() -
285
+ start_time)
286
  chatbot_value[-1]["status"] = "done"
287
  yield {
288
  clear_btn: gr.update(disabled=False),
289
  sender: gr.update(loading=False),
290
  chatbot: gr.update(value=chatbot_value),
291
  }
292
+
293
  except Exception as e:
294
  chatbot_value[-1]["loading"] = False
295
  chatbot_value[-1]["status"] = "done"
 
309
  r'```\n([\s\S]+?)\n```', # Match code blocks without language markers
310
  r'```([\s\S]+?)```' # Match code blocks without line breaks
311
  ]
312
+
313
  for pattern in patterns:
314
  match = re.search(pattern, text, re.DOTALL)
315
  if match:
316
  extracted = match.group(1).strip()
317
  print("Successfully extracted code block:", extracted)
318
  return extracted
319
+
320
  # If no code block is found, check if the entire text is HTML
321
+ if text.strip().startswith('<!DOCTYPE html>') or text.strip().startswith(
322
+ '<html'):
323
  print("Text appears to be raw HTML, using as is")
324
  return text.strip()
325
+
326
  print("No code block found in text:", text)
327
  return text.strip()
328
 
329
+
330
  def send_to_sandbox(code):
331
  # Add a wrapper to inject necessary permissions
332
  wrapped_code = f"""
 
370
  </body>
371
  </html>
372
  """
373
+ encoded_html = base64.b64encode(
374
+ wrapped_code.encode('utf-8')).decode('utf-8')
375
  data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
376
  iframe = f'<iframe src="{data_uri}" width="100%" height="920px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-presentation" allow="display-capture"></iframe>'
377
  print("Generated iframe:", iframe)
378
  return iframe
379
 
380
+
381
  def select_example(example):
382
  if isinstance(example, dict):
383
  return example.get("description", "")
384
  return ""
385
 
386
+
387
  def generate_code(query: str):
388
  if not query:
389
  return {
 
394
  output_tabs: gr.update(active_key="reasoning", visible=False),
395
  loading: gr.update(tip="Thinking...")
396
  }
397
+
398
  print("Starting code generation with query:", query)
399
  messages = [{
400
  'role': 'system',
 
403
  'role': 'user',
404
  'content': query
405
  }]
406
+
407
  max_retries = 3
408
  retry_count = 0
409
+
410
  while retry_count < max_retries:
411
  try:
412
  data = {
 
417
  'temperature': MODEL_CONTROL_DEFAULTS['temperature'],
418
  'top_p': MODEL_CONTROL_DEFAULTS['top_p'],
419
  }
420
+
421
+ print(
422
+ f"Attempt {retry_count + 1}: Sending request to API with data:",
423
+ json.dumps(data, indent=2))
424
  r = requests.post(
425
  API_URL,
426
  headers={
 
431
  stream=True,
432
  timeout=60 # Set 60 seconds timeout
433
  )
434
+
435
  content = ""
436
  reasoning_content = ""
437
  loading_text = "Thinking..."
438
+
439
  for row in r.iter_lines():
440
  if row.startswith(b'data:'):
441
  data = json.loads(row[5:])
442
+ print("Received data from API:", json.dumps(data,
443
+ indent=2))
444
  if 'choices' not in data:
445
  raise gr.Error('request failed')
446
  choice = data['choices'][0]
447
+
448
  if 'delta' in choice:
449
  delta = choice['delta']
450
  content += delta.get('content', '')
451
  reasoning_content += delta.get('reasoning_content', '')
452
+
453
  # Update loading text based on content
454
  if content and not loading_text == "Generating code...":
455
  loading_text = "Generating code..."
456
  yield {
457
+ code_output:
458
+ gr.update(value=content),
459
+ reasoning_output:
460
+ gr.update(value=reasoning_content + "\n"),
461
+ sandbox:
462
+ gr.update(value=None),
463
+ state_tab:
464
+ gr.update(active_key="loading"),
465
+ output_tabs:
466
+ gr.update(active_key="reasoning",
467
+ visible=True),
468
+ loading:
469
+ gr.update(tip=loading_text)
470
  }
471
  else:
472
  yield {
473
+ code_output:
474
+ gr.update(value=content),
475
+ reasoning_output:
476
+ gr.update(value=reasoning_content + "\n"),
477
+ sandbox:
478
+ gr.update(value=None),
479
+ state_tab:
480
+ gr.update(active_key="loading"),
481
+ output_tabs:
482
+ gr.update(active_key="reasoning",
483
+ visible=True),
484
+ loading:
485
+ gr.update(tip=loading_text)
486
  }
487
  elif 'message' in choice:
488
  message_data = choice['message']
489
  content = message_data.get('content', '')
490
+ reasoning_content = message_data.get(
491
+ 'reasoning_content', '')
492
  print("Final content:", content)
493
  print("Final reasoning:", reasoning_content)
494
  html_content = remove_code_block(content)
495
  print("Extracted HTML:", html_content)
496
  yield {
497
+ code_output:
498
+ gr.update(value=content),
499
+ reasoning_output:
500
+ gr.update(value=reasoning_content + "\n"),
501
+ sandbox:
502
+ gr.update(value=send_to_sandbox(html_content)),
503
+ state_tab:
504
+ gr.update(active_key="render"),
505
+ output_tabs:
506
+ gr.update(active_key="code", visible=True),
507
+ loading:
508
+ gr.update(tip="Done")
509
  }
510
+
511
  # If successful, break out of retry loop
512
  break
513
+
514
+ except (requests.exceptions.Timeout,
515
+ requests.exceptions.ConnectionError) as e:
516
  retry_count += 1
517
  if retry_count == max_retries:
518
  print(f"Failed after {max_retries} attempts:", str(e))
519
+ raise gr.Error(
520
+ f"Request failed after {max_retries} attempts: {str(e)}")
521
  print(f"Attempt {retry_count} failed, retrying...")
522
  time.sleep(1) # Wait 1 second before retrying
523
+
524
  except Exception as e:
525
  print("Error occurred:", str(e))
526
  raise gr.Error(str(e))
527
 
528
+
529
  css = """
530
  /* Add styles for the main container */
531
  .ant-tabs-content {
 
539
  }
540
 
541
  /* Modify existing styles */
542
+ .output-empty,.output-loading {
543
  display: flex;
544
  flex-direction: column;
545
  align-items: center;
546
  justify-content: center;
547
  width: 100%;
548
+ min-height: 680px;
549
+ position: relative;
550
  }
551
 
552
  .output-html {
553
  display: flex;
554
  flex-direction: column;
555
  width: 100%;
556
+ min-height: 680px;
557
+ }
558
+
559
+ .output-html > iframe {
560
+ flex: 1;
 
 
561
  }
562
 
563
  .right_content {
 
635
  }
636
 
637
  .reasoning-box {
638
+ max-height: 300px;
639
  overflow-y: auto;
 
640
  border-radius: 4px;
 
641
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
642
  font-size: 14px;
643
+ line-height: 1.6;
 
 
644
  width: 100%;
 
645
  scroll-behavior: smooth;
646
+ display: flex;
647
+ flex-direction: column-reverse;
648
  }
649
 
650
  .reasoning-box .ms-markdown {
 
670
  }
671
 
672
  .markdown-container {
673
+ max-height: 300px;
674
  overflow-y: auto;
 
675
  border-radius: 4px;
 
676
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
677
  font-size: 14px;
678
  line-height: 1.6;
 
 
679
  width: 100%;
 
680
  scroll-behavior: smooth;
681
+ display: flex;
682
+ flex-direction: column-reverse;
683
  }
684
 
685
  /* Example card styles */
 
751
  }
752
  """
753
 
754
+
755
  def scroll_to_bottom():
756
  return """
757
  function() {
 
768
  }
769
  """
770
 
771
+
772
+ with gr.Blocks(css=css) as demo, ms.Application(), antdx.XProvider(
773
+ ), ms.AutoLoading():
774
  with antd.Tabs() as tabs:
775
  with antd.Tabs.Item(key="chat", label="Chatbot"):
776
+ with antd.Flex(vertical=True,
777
+ gap="middle",
778
+ elem_style=dict(height="calc(100vh - 150px)")):
779
  chatbot = pro.Chatbot(
780
+ elem_style=dict(flex=1, maxHeight=1200, height=0),
781
+ markdown_config=ChatbotMarkdownConfig(
782
+ allow_tags=["think"]),
783
  welcome_config=ChatbotWelcomeConfig(
784
  variant="borderless",
785
  icon="./assets/minimax-logo.png",
 
795
  "flex": 1,
796
  },
797
  },
798
+ items=DEFAULT_PROMPTS)),
 
 
799
  user_config=ChatbotUserConfig(actions=["copy", "edit"]),
800
  bot_config=ChatbotBotConfig(
801
  header=MODEL_NAME,
802
  avatar="./assets/minimax-logo.png",
803
+ actions=["copy", "retry"]))
 
 
804
 
805
  with antdx.Sender() as sender:
806
  with ms.Slot("prefix"):
807
+ with antd.Button(value=None,
808
+ color="default",
809
+ variant="text") as clear_btn:
810
  with ms.Slot("icon"):
811
  antd.Icon("ClearOutlined")
812
 
 
814
  submit_event = sender.submit(
815
  fn=submit,
816
  inputs=[sender, chatbot],
817
+ outputs=[sender, chatbot, clear_btn])
818
+ sender.cancel(fn=cancel,
819
+ inputs=[chatbot],
820
+ outputs=[chatbot, sender, clear_btn],
821
+ cancels=[submit_event],
822
+ queue=False)
823
+ chatbot.retry(fn=retry,
824
+ inputs=[chatbot],
825
+ outputs=[sender, chatbot, clear_btn])
826
+ chatbot.welcome_prompt_select(fn=prompt_select,
827
+ outputs=[sender])
 
 
 
 
828
 
829
  with antd.Tabs.Item(key="code", label="Code Playground (WebDev)"):
830
+ with antd.Row(gutter=[32, 12],
831
+ elem_classes="code-playground-container"):
832
+ with antd.Col(span=24, md=12):
833
  with antd.Flex(vertical=True, gap="middle"):
834
+ code_input = antd.Input.Textarea(
835
  size="large",
836
  allow_clear=True,
837
+ auto_size=dict(minRows=2, maxRows=6),
838
+ placeholder=
839
+ "Please enter what kind of application you want or choose an example below and click the button"
840
  )
841
+ code_btn = antd.Button("Generate Code",
842
+ type="primary",
843
+ size="large")
844
+ with antd.Tabs(active_key="reasoning",
845
+ visible=False) as output_tabs:
846
+ with antd.Tabs.Item(key="reasoning",
847
+ label="🤔 Thinking Process"):
848
+ reasoning_output = ms.Markdown(
849
+ elem_classes="reasoning-box")
850
+ with antd.Tabs.Item(key="code",
851
+ label="💻 Generated Code"):
852
+ code_output = ms.Markdown(
853
+ elem_classes="markdown-container")
854
+
855
  antd.Divider("Examples")
856
 
857
  # Examples with categories
858
+ with antd.Tabs(
859
+ elem_classes="example-tabs") as example_tabs:
860
  for category, examples in EXAMPLES.items():
861
+ with antd.Tabs.Item(key=category,
862
+ label=category):
863
  with antd.Flex(gap="small", wrap=True):
864
  for example in examples:
865
  with antd.Card(
866
+ elem_classes="example-card",
867
+ hoverable=True
868
  ) as example_card:
869
  antd.Card.Meta(
870
  title=example['title'],
871
+ description=example[
872
+ 'description'])
873
 
874
  example_card.click(
875
  fn=select_example,
876
  inputs=[gr.State(example)],
877
+ outputs=[code_input])
878
+
879
+ with antd.Col(span=24, md=12):
880
+ with antd.Card(title="Output",
881
+ elem_style=dict(height="100%"),
882
+ styles=dict(body=dict(height="100%")),
883
+ elem_id="output-container"):
884
+ with antd.Tabs(
885
+ active_key="empty",
886
+ render_tab_bar="() => null") as state_tab:
 
 
 
 
887
  with antd.Tabs.Item(key="empty"):
888
+ empty = antd.Empty(
889
+ description=
890
+ "Enter your request to generate code",
891
+ elem_classes="output-empty")
892
  with antd.Tabs.Item(key="loading"):
893
+ with antd.Spin(True,
894
+ tip="Thinking and coding...",
895
+ size="large",
896
+ elem_classes="output-loading"
897
+ ) as loading:
898
+ # placeholder
899
+ ms.Div()
900
  with antd.Tabs.Item(key="render"):
901
  sandbox = gr.HTML(elem_classes="output-html")
902
 
903
+ code_btn.click(generate_code,
904
+ inputs=[code_input],
905
+ outputs=[
906
+ code_output, reasoning_output, sandbox,
907
+ state_tab, output_tabs, loading
908
+ ])
 
 
 
 
 
 
909
 
910
  # Add auto-scroll functionality
911
  reasoning_output.change(
 
919
  outputs=[],
920
  )
921
 
922
+ def on_tab_change(e: gr.EventData):
923
+ tab_key = e._data["payload"][0]
924
  return gr.update(active_key=tab_key, visible=True)
925
 
926
  output_tabs.change(
927
  fn=on_tab_change,
 
928
  outputs=[output_tabs],
929
  )
930
 
931
  if __name__ == '__main__':
932
+ demo.queue(default_concurrency_limit=50).launch(ssr_mode=False)