Coloring commited on
Commit
4e0488c
·
1 Parent(s): a1b8841

feat: update

Browse files
layout_templates/chatbot/README-zh_CN.md CHANGED
@@ -2,6 +2,14 @@
2
 
3
  用于构建聊天机器人界面的应用模板。
4
 
 
 
 
 
 
 
 
 
5
  ## 示例
6
 
7
  <demo name="app" position="bottom" collapsible="true"></demo>
 
2
 
3
  用于构建聊天机器人界面的应用模板。
4
 
5
+ 该模板提供以下功能:
6
+
7
+ - 支持对话管理,可以同时开启多个对话。
8
+ - 支持对话历史管理,可以对任意 message 进行重新生成、删除等操作,可以一键清空历史。
9
+ - 支持对话中断,可以中断当前的对话消息,并给出提示。
10
+ - 支持通过输入`/`为用户展示输入建议。
11
+ - 支持附件上传,可以手动控制最大上传个数以及上传格式。
12
+
13
  ## 示例
14
 
15
  <demo name="app" position="bottom" collapsible="true"></demo>
layout_templates/chatbot/README.md CHANGED
@@ -1,6 +1,14 @@
1
  # Chatbot
2
 
3
- A application template for building chatbot interfaces.
 
 
 
 
 
 
 
 
4
 
5
  ## Examples
6
 
 
1
  # Chatbot
2
 
3
+ Application templates for building chatbot interfaces.
4
+
5
+ This template provides the following features:
6
+
7
+ - Supports conversation management, allowing multiple conversations to be opened simultaneously.
8
+ - Enables conversation history management, including operations like regenerating or deleting any message, and clearing all history with one click.
9
+ - Allows interrupting ongoing conversations and displaying notifications.
10
+ - Displays input suggestions when users type `/`.
11
+ - Supports attachment uploads with manual configuration of maximum upload count and allowed formats.
12
 
13
  ## Examples
14
 
layout_templates/chatbot/demos/app.py CHANGED
@@ -117,13 +117,14 @@ class Gradio_Events:
117
  messages.append(item)
118
  return messages
119
 
120
- history = state_value["conversations_histories"][
121
  state_value["conversation_id"]]
122
  history_messages = format_history(history)
123
 
124
  history.append({
125
  "role": "assistant",
126
  "content": "",
 
127
  "meta": {},
128
  "loading": True,
129
  })
@@ -160,22 +161,25 @@ class Gradio_Events:
160
  raise e
161
 
162
  @staticmethod
163
- def preprocess_submit(sender_value, attachments_value, state_value):
164
  if not state_value["conversation_id"]:
165
  random_id = str(uuid.uuid4())
166
  history = []
167
  state_value["conversation_id"] = random_id
168
- state_value["conversations_histories"][random_id] = history
169
  state_value["conversations"].append({
170
  "label": sender_value,
171
  "key": random_id
172
  })
173
 
174
- history = state_value["conversations_histories"][
175
  state_value["conversation_id"]]
176
  history.append({
177
  "role":
178
  "user",
 
 
 
179
  "content":
180
  dict(text=sender_value,
181
  files=[
@@ -183,57 +187,142 @@ class Gradio_Events:
183
  for f in attachments_value
184
  ])
185
  })
186
- return {
187
- add_conversation_btn:
188
- gr.update(disabled=True),
189
- sender:
190
- gr.update(value=None, loading=True),
191
- attachments:
192
- gr.update(value=[]),
193
- attachments_badge:
194
- gr.update(dot=False),
195
- clear_btn:
196
- gr.update(disabled=True),
197
- conversations:
198
- gr.update(active_key=state_value["conversation_id"],
199
- items=list(
200
- map(
201
- lambda item: {
202
- **item,
203
- "disabled":
204
- True if item["key"] != state_value[
205
- "conversation_id"] else False,
206
- }, state_value["conversations"]))),
207
- conversation_delete_menu_item:
208
- gr.update(disabled=True),
209
- state:
210
- gr.update(value=state_value),
211
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
  @staticmethod
214
  def postprocess_submit(state_value):
 
 
 
 
 
215
  return {
216
  sender: gr.update(loading=False),
217
  conversation_delete_menu_item: gr.update(disabled=False),
218
  clear_btn: gr.update(disabled=False),
219
  conversations: gr.update(items=state_value["conversations"]),
220
- add_conversation_btn: gr.update(disabled=False)
 
 
221
  }
222
 
223
  @staticmethod
224
  def cancel(state_value):
225
- history = state_value["conversations_histories"][
226
  state_value["conversation_id"]]
227
  history[-1]["loading"] = False
228
  history[-1]["meta"]["end"] = True
229
- return {
230
- **Gradio_Events.postprocess_submit(state_value),
231
- chatbot:
232
- gr.update(items=state_value["conversations_histories"][
233
- state_value["conversation_id"]]),
234
- state:
235
- gr.update(value=state_value),
236
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
  @staticmethod
239
  def select_suggestion(sender_value, e: gr.EventData):
@@ -255,19 +344,19 @@ class Gradio_Events:
255
  def select_conversation(state_value, e: gr.EventData):
256
  active_key = e._data["payload"][0]
257
  if state_value["conversation_id"] == active_key or (
258
- active_key not in state_value["conversations_histories"]):
259
  return gr.skip()
260
  state_value["conversation_id"] = active_key
261
  return gr.update(active_key=active_key), gr.update(
262
- items=state_value["conversations_histories"]
263
- [active_key]), gr.update(value=state_value)
264
 
265
  @staticmethod
266
  def click_conversation_menu(state_value, e: gr.EventData):
267
  conversation_id = e._data["payload"][0]["key"]
268
  operation = e._data["payload"][1]["key"]
269
  if operation == "delete":
270
- del state_value["conversations_histories"][conversation_id]
271
 
272
  state_value["conversations"] = [
273
  item for item in state_value["conversations"]
@@ -291,7 +380,7 @@ class Gradio_Events:
291
  def clear_conversation_history(state_value):
292
  if not state_value["conversation_id"]:
293
  return gr.skip()
294
- state_value["conversations_histories"][
295
  state_value["conversation_id"]] = []
296
  return gr.update(items=DEFAULT_CONVERSATIONS_HISTORY), gr.update(
297
  value=state_value)
@@ -341,8 +430,21 @@ css = """
341
  #chatbot .chatbot-chat .chatbot-chat-messages {
342
  flex: 1;
343
  }
344
- #chatbot .chatbot-sender-actions .ms-gr-ant-sender-actions-btn-loading-button {
345
- color: var(--ms-gr-ant-color-primary);
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
  """
348
 
@@ -364,7 +466,7 @@ def logo():
364
 
365
  with gr.Blocks(css=css) as demo:
366
  state = gr.State({
367
- "conversations_histories": {},
368
  "conversations": [],
369
  "conversation_id": "",
370
  "attachments_open": False,
@@ -384,7 +486,8 @@ with gr.Blocks(css=css) as demo:
384
  logo()
385
 
386
  # New Conversation Button
387
- with antd.Button(color="primary",
 
388
  variant="filled",
389
  block=True) as add_conversation_btn:
390
  ms.Text("New Conversation")
@@ -455,6 +558,9 @@ with gr.Blocks(css=css) as demo:
455
  with antdx.Bubble.List.Role(
456
  role="user",
457
  placement="end",
 
 
 
458
  styles=dict(content=dict(
459
  maxWidth="100%",
460
  overflow='auto',
@@ -470,6 +576,7 @@ with gr.Blocks(css=css) as demo:
470
  }
471
  return { content: content.text, files_container: content.files?.length > 0 ? undefined : { style: { display: 'none' }}, files: (content.files || []).map(file => ({ item: file }))}
472
  }"""):
 
473
  with antd.Flex(vertical=True,
474
  gap="middle"):
475
  with antd.Flex(
@@ -479,10 +586,53 @@ with gr.Blocks(css=css) as demo:
479
  with ms.Each(as_item="files"):
480
  antdx.Attachments.FileCard()
481
  ms.Markdown(as_item="content")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  # Chatbot Role
483
  with antdx.Bubble.List.Role(
484
  role="assistant",
485
  placement="start",
 
 
 
486
  styles=dict(content=dict(
487
  maxWidth="100%", overflow='auto'))):
488
  with ms.Slot("avatar"):
@@ -491,28 +641,112 @@ with gr.Blocks(css=css) as demo:
491
  antd.Icon("RobotOutlined")
492
  with ms.Slot(
493
  "messageRender",
494
- params_mapping=
495
- "(content) => ({ value: content })"):
 
 
 
 
496
  ms.Markdown()
 
 
 
 
 
497
  with ms.Slot("footer",
498
  params_mapping="""(bubble) => {
499
- return bubble?.meta?.end ? { copyable: { text: bubble.content, tooltips: false } } : { style: { display: 'none' } }
500
- }"""):
501
- with antd.Typography.Text(copyable=dict(
502
- tooltips=False)):
503
- with ms.Slot("copyable.icon"):
504
- with antd.Button(value=None,
505
- size="small",
506
- color="default",
507
- variant="text"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  with ms.Slot("icon"):
509
- antd.Icon("CopyOutlined")
510
- with antd.Button(value=None,
511
- size="small",
512
- color="default",
513
- variant="text"):
 
 
 
 
 
 
 
 
 
 
514
  with ms.Slot("icon"):
515
- antd.Icon("CheckOutlined")
516
  # Error Chatbot Role
517
  with antdx.Bubble.List.Role(
518
  role="assistant-error",
@@ -548,8 +782,6 @@ with gr.Blocks(css=css) as demo:
548
  }""") as suggestion:
549
  with ms.Slot("children"):
550
  with antdx.Sender(
551
- class_names=dict(
552
- actions="chatbot-sender-actions"),
553
  placeholder="Enter / to get suggestions"
554
  ) as sender:
555
  with ms.Slot("prefix"):
@@ -637,23 +869,62 @@ with gr.Blocks(css=css) as demo:
637
  sender.paste_file(fn=Gradio_Events.paste_file,
638
  inputs=[attachments, state],
639
  outputs=[attachments, sender_header, state])
640
-
641
- submit_event = sender.submit(fn=Gradio_Events.preprocess_submit,
642
- inputs=[sender, attachments, state],
643
- outputs=[
644
- sender, attachments, attachments_badge,
645
- clear_btn, conversation_delete_menu_item,
646
- add_conversation_btn, conversations, state
647
- ]).then(fn=Gradio_Events.submit,
648
- inputs=[state],
649
- outputs=[chatbot, state])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
650
  submit_event.then(fn=Gradio_Events.postprocess_submit,
651
  inputs=[state],
652
  outputs=[
653
  sender, conversation_delete_menu_item, clear_btn,
654
- conversations, add_conversation_btn
655
  ])
656
- sender.cancel(fn=None, cancels=[submit_event])
657
  sender.cancel(fn=Gradio_Events.cancel,
658
  inputs=[state],
659
  outputs=[
 
117
  messages.append(item)
118
  return messages
119
 
120
+ history = state_value["conversations_history"][
121
  state_value["conversation_id"]]
122
  history_messages = format_history(history)
123
 
124
  history.append({
125
  "role": "assistant",
126
  "content": "",
127
+ "key": str(uuid.uuid4()),
128
  "meta": {},
129
  "loading": True,
130
  })
 
161
  raise e
162
 
163
  @staticmethod
164
+ def add_user_message(sender_value, attachments_value, state_value):
165
  if not state_value["conversation_id"]:
166
  random_id = str(uuid.uuid4())
167
  history = []
168
  state_value["conversation_id"] = random_id
169
+ state_value["conversations_history"][random_id] = history
170
  state_value["conversations"].append({
171
  "label": sender_value,
172
  "key": random_id
173
  })
174
 
175
+ history = state_value["conversations_history"][
176
  state_value["conversation_id"]]
177
  history.append({
178
  "role":
179
  "user",
180
+ "meta": {},
181
+ "key":
182
+ str(uuid.uuid4()),
183
  "content":
184
  dict(text=sender_value,
185
  files=[
 
187
  for f in attachments_value
188
  ])
189
  })
190
+ return gr.update(value=state_value)
191
+
192
+ @staticmethod
193
+ def preprocess_submit(clear_input=True):
194
+
195
+ def preprocess_submit_handler(state_value):
196
+ history = state_value["conversations_history"][
197
+ state_value["conversation_id"]]
198
+ for conversation in history:
199
+ if "meta" in conversation:
200
+ conversation["meta"]["disabled"] = True
201
+ return {
202
+ **({
203
+ sender: gr.update(value=None, loading=True),
204
+ attachments: gr.update(value=[]),
205
+ attachments_badge: gr.update(dot=False),
206
+ } if clear_input else {}),
207
+ conversations:
208
+ gr.update(active_key=state_value["conversation_id"],
209
+ items=list(
210
+ map(
211
+ lambda item: {
212
+ **item,
213
+ "disabled":
214
+ True if item["key"] != state_value[
215
+ "conversation_id"] else False,
216
+ }, state_value["conversations"]))),
217
+ add_conversation_btn:
218
+ gr.update(disabled=True),
219
+ clear_btn:
220
+ gr.update(disabled=True),
221
+ conversation_delete_menu_item:
222
+ gr.update(disabled=True),
223
+ chatbot:
224
+ gr.update(items=history),
225
+ state:
226
+ gr.update(value=state_value),
227
+ }
228
+
229
+ return preprocess_submit_handler
230
 
231
  @staticmethod
232
  def postprocess_submit(state_value):
233
+ history = state_value["conversations_history"][
234
+ state_value["conversation_id"]]
235
+ for conversation in history:
236
+ if "meta" in conversation:
237
+ conversation["meta"]["disabled"] = False
238
  return {
239
  sender: gr.update(loading=False),
240
  conversation_delete_menu_item: gr.update(disabled=False),
241
  clear_btn: gr.update(disabled=False),
242
  conversations: gr.update(items=state_value["conversations"]),
243
+ add_conversation_btn: gr.update(disabled=False),
244
+ chatbot: gr.update(items=history),
245
+ state: gr.update(value=state_value),
246
  }
247
 
248
  @staticmethod
249
  def cancel(state_value):
250
+ history = state_value["conversations_history"][
251
  state_value["conversation_id"]]
252
  history[-1]["loading"] = False
253
  history[-1]["meta"]["end"] = True
254
+ history[-1]["meta"]["canceled"] = True
255
+ return Gradio_Events.postprocess_submit(state_value)
256
+
257
+ @staticmethod
258
+ def like(state_value, e: gr.EventData):
259
+ conversation_key = e._data["component"]["conversationKey"]
260
+ history = state_value["conversations_history"][
261
+ state_value["conversation_id"]]
262
+ index = -1
263
+ for i, conversation in enumerate(history):
264
+ if conversation["key"] == conversation_key:
265
+ index = i
266
+ break
267
+ if index == -1:
268
+ return gr.skip()
269
+ if history[index]["meta"].get("action") == "like":
270
+ history[index]["meta"]["action"] = None
271
+ else:
272
+ history[index]["meta"]["action"] = "like"
273
+
274
+ # custom code
275
+ return gr.update(items=history), gr.update(value=state_value)
276
+
277
+ @staticmethod
278
+ def dislike(state_value, e: gr.EventData):
279
+ conversation_key = e._data["component"]["conversationKey"]
280
+ history = state_value["conversations_history"][
281
+ state_value["conversation_id"]]
282
+ index = -1
283
+ for i, conversation in enumerate(history):
284
+ if conversation["key"] == conversation_key:
285
+ index = i
286
+ break
287
+ if index == -1:
288
+ return gr.skip()
289
+ if history[index]["meta"].get("action") == "dislike":
290
+ history[index]["meta"]["action"] = None
291
+ else:
292
+ history[index]["meta"]["action"] = "dislike"
293
+ # custom code
294
+ return gr.update(items=history), gr.update(value=state_value)
295
+
296
+ @staticmethod
297
+ def delete_message(state_value, e: gr.EventData):
298
+ conversation_key = e._data["component"]["conversationKey"]
299
+ history = state_value["conversations_history"][
300
+ state_value["conversation_id"]]
301
+ history = [item for item in history if item["key"] != conversation_key]
302
+ state_value["conversations_history"][
303
+ state_value["conversation_id"]] = history
304
+
305
+ return gr.update(items=history if len(history) >
306
+ 0 else DEFAULT_CONVERSATIONS_HISTORY), gr.update(
307
+ value=state_value)
308
+
309
+ @staticmethod
310
+ def regenerating(state_value, e: gr.EventData):
311
+ conversation_key = e._data["component"]["conversationKey"]
312
+ history = state_value["conversations_history"][
313
+ state_value["conversation_id"]]
314
+ index = -1
315
+ for i, conversation in enumerate(history):
316
+ if conversation["key"] == conversation_key:
317
+ index = i
318
+ break
319
+ if index == -1:
320
+ return gr.skip()
321
+ history = history[:index]
322
+ state_value["conversations_history"][
323
+ state_value["conversation_id"]] = history
324
+ # custom code
325
+ return gr.update(items=history), gr.update(value=state_value)
326
 
327
  @staticmethod
328
  def select_suggestion(sender_value, e: gr.EventData):
 
344
  def select_conversation(state_value, e: gr.EventData):
345
  active_key = e._data["payload"][0]
346
  if state_value["conversation_id"] == active_key or (
347
+ active_key not in state_value["conversations_history"]):
348
  return gr.skip()
349
  state_value["conversation_id"] = active_key
350
  return gr.update(active_key=active_key), gr.update(
351
+ items=state_value["conversations_history"][active_key]), gr.update(
352
+ value=state_value)
353
 
354
  @staticmethod
355
  def click_conversation_menu(state_value, e: gr.EventData):
356
  conversation_id = e._data["payload"][0]["key"]
357
  operation = e._data["payload"][1]["key"]
358
  if operation == "delete":
359
+ del state_value["conversations_history"][conversation_id]
360
 
361
  state_value["conversations"] = [
362
  item for item in state_value["conversations"]
 
380
  def clear_conversation_history(state_value):
381
  if not state_value["conversation_id"]:
382
  return gr.skip()
383
+ state_value["conversations_history"][
384
  state_value["conversation_id"]] = []
385
  return gr.update(items=DEFAULT_CONVERSATIONS_HISTORY), gr.update(
386
  value=state_value)
 
430
  #chatbot .chatbot-chat .chatbot-chat-messages {
431
  flex: 1;
432
  }
433
+
434
+ #chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message .chatbot-chat-message-footer {
435
+ visibility: hidden;
436
+ opacity: 0;
437
+ transition: opacity 0.2s;
438
+ }
439
+
440
+ #chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message:last-child .chatbot-chat-message-footer {
441
+ visibility: visible;
442
+ opacity: 1;
443
+ }
444
+
445
+ #chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message:hover .chatbot-chat-message-footer {
446
+ visibility: visible;
447
+ opacity: 1;
448
  }
449
  """
450
 
 
466
 
467
  with gr.Blocks(css=css) as demo:
468
  state = gr.State({
469
+ "conversations_history": {},
470
  "conversations": [],
471
  "conversation_id": "",
472
  "attachments_open": False,
 
486
  logo()
487
 
488
  # New Conversation Button
489
+ with antd.Button(value=None,
490
+ color="primary",
491
  variant="filled",
492
  block=True) as add_conversation_btn:
493
  ms.Text("New Conversation")
 
558
  with antdx.Bubble.List.Role(
559
  role="user",
560
  placement="end",
561
+ elem_classes="chatbot-chat-message",
562
+ class_names=dict(
563
+ footer="chatbot-chat-message-footer"),
564
  styles=dict(content=dict(
565
  maxWidth="100%",
566
  overflow='auto',
 
576
  }
577
  return { content: content.text, files_container: content.files?.length > 0 ? undefined : { style: { display: 'none' }}, files: (content.files || []).map(file => ({ item: file }))}
578
  }"""):
579
+
580
  with antd.Flex(vertical=True,
581
  gap="middle"):
582
  with antd.Flex(
 
586
  with ms.Each(as_item="files"):
587
  antdx.Attachments.FileCard()
588
  ms.Markdown(as_item="content")
589
+ with ms.Slot("footer",
590
+ params_mapping="""(bubble) => {
591
+ return {
592
+ copy_btn: {
593
+ copyable: { text: typeof bubble.content === 'string' ? bubble.content : bubble.content?.text, tooltips: false },
594
+ },
595
+ delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
596
+ };
597
+ }"""):
598
+ with antd.Typography.Text(
599
+ copyable=dict(tooltips=False),
600
+ as_item="copy_btn"):
601
+ with ms.Slot("copyable.icon"):
602
+ with antd.Button(value=None,
603
+ size="small",
604
+ color="default",
605
+ variant="text"):
606
+ with ms.Slot("icon"):
607
+ antd.Icon("CopyOutlined")
608
+ with antd.Button(value=None,
609
+ size="small",
610
+ color="default",
611
+ variant="text"):
612
+ with ms.Slot("icon"):
613
+ antd.Icon("CheckOutlined")
614
+ with antd.Popconfirm(
615
+ title="Delete the message",
616
+ description=
617
+ "Are you sure to delete this message?",
618
+ ok_button_props=dict(danger=True),
619
+ as_item="delete_btn"
620
+ ) as user_delete_popconfirm:
621
+ with antd.Button(value=None,
622
+ size="small",
623
+ color="default",
624
+ variant="text",
625
+ as_item="delete_btn"):
626
+ with ms.Slot("icon"):
627
+ antd.Icon("DeleteOutlined")
628
+
629
  # Chatbot Role
630
  with antdx.Bubble.List.Role(
631
  role="assistant",
632
  placement="start",
633
+ elem_classes="chatbot-chat-message",
634
+ class_names=dict(
635
+ footer="chatbot-chat-message-footer"),
636
  styles=dict(content=dict(
637
  maxWidth="100%", overflow='auto'))):
638
  with ms.Slot("avatar"):
 
641
  antd.Icon("RobotOutlined")
642
  with ms.Slot(
643
  "messageRender",
644
+ params_mapping="""(content, bubble) => {
645
+ if (bubble.meta?.canceled) {
646
+ return { value: content }
647
+ }
648
+ return { value: content, canceled: { style: { display: 'none' } } }
649
+ }"""):
650
  ms.Markdown()
651
+ antd.Divider(as_item="canceled")
652
+ antd.Typography.Text(
653
+ "Chat completion paused.",
654
+ as_item="canceled",
655
+ type="warning")
656
  with ms.Slot("footer",
657
  params_mapping="""(bubble) => {
658
+ if (bubble?.meta?.end) {
659
+ return {
660
+ copy_btn: {
661
+ copyable: { text: bubble.content, tooltips: false },
662
+ },
663
+ regenerating_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
664
+ delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
665
+ like_btn: {
666
+ conversationKey: bubble.key,
667
+ color: bubble.meta?.action === 'like' ? 'primary' : 'default',
668
+ },
669
+ dislike_btn: {
670
+ conversationKey: bubble.key,
671
+ color: bubble.meta?.action === 'dislike' ? 'primary' : 'default',
672
+ },
673
+ };
674
+ }
675
+ return { actions_container: { style: { display: 'none' } } };
676
+ }"""):
677
+ with ms.Div(as_item="actions_container"):
678
+ with antd.Typography.Text(
679
+ copyable=dict(tooltips=False),
680
+ as_item="copy_btn"):
681
+ with ms.Slot("copyable.icon"):
682
+ with antd.Button(
683
+ value=None,
684
+ size="small",
685
+ color="default",
686
+ variant="text"):
687
+ with ms.Slot("icon"):
688
+ antd.Icon(
689
+ "CopyOutlined")
690
+ with antd.Button(
691
+ value=None,
692
+ size="small",
693
+ color="default",
694
+ variant="text"):
695
+ with ms.Slot("icon"):
696
+ antd.Icon(
697
+ "CheckOutlined")
698
+
699
+ with antd.Button(value=None,
700
+ size="small",
701
+ color="default",
702
+ variant="text",
703
+ as_item="like_btn"
704
+ ) as chatbot_like_btn:
705
+ with ms.Slot("icon"):
706
+ antd.Icon("LikeOutlined")
707
+ with antd.Button(
708
+ value=None,
709
+ size="small",
710
+ color="default",
711
+ variant="text",
712
+ as_item="dislike_btn"
713
+ ) as chatbot_dislike_btn:
714
+ with ms.Slot("icon"):
715
+ antd.Icon("DislikeOutlined")
716
+ with antd.Popconfirm(
717
+ title=
718
+ "Regenerating the message",
719
+ description=
720
+ "Regenerating the message will also delete all subsequent messages.",
721
+ ok_button_props=dict(
722
+ danger=True),
723
+ as_item="regenerating_btn"
724
+ ) as chatbot_regenerating_popconfirm:
725
+ with antd.Button(
726
+ value=None,
727
+ size="small",
728
+ color="default",
729
+ variant="text",
730
+ as_item="regenerating_btn",
731
+ ):
732
  with ms.Slot("icon"):
733
+ antd.Icon("SyncOutlined")
734
+ with antd.Popconfirm(
735
+ title="Delete the message",
736
+ description=
737
+ "Are you sure to delete this message?",
738
+ ok_button_props=dict(
739
+ danger=True),
740
+ as_item="delete_btn"
741
+ ) as chatbot_delete_popconfirm:
742
+ with antd.Button(
743
+ value=None,
744
+ size="small",
745
+ color="default",
746
+ variant="text",
747
+ as_item="delete_btn"):
748
  with ms.Slot("icon"):
749
+ antd.Icon("DeleteOutlined")
750
  # Error Chatbot Role
751
  with antdx.Bubble.List.Role(
752
  role="assistant-error",
 
782
  }""") as suggestion:
783
  with ms.Slot("children"):
784
  with antdx.Sender(
 
 
785
  placeholder="Enter / to get suggestions"
786
  ) as sender:
787
  with ms.Slot("prefix"):
 
869
  sender.paste_file(fn=Gradio_Events.paste_file,
870
  inputs=[attachments, state],
871
  outputs=[attachments, sender_header, state])
872
+ chatbot_like_btn.click(fn=Gradio_Events.like,
873
+ inputs=[state],
874
+ outputs=[chatbot, state])
875
+ chatbot_dislike_btn.click(fn=Gradio_Events.dislike,
876
+ inputs=[state],
877
+ outputs=[chatbot, state])
878
+ gr.on(triggers=[
879
+ chatbot_delete_popconfirm.confirm, user_delete_popconfirm.confirm
880
+ ],
881
+ fn=Gradio_Events.delete_message,
882
+ inputs=[state],
883
+ outputs=[chatbot, state])
884
+
885
+ regenerating_event = chatbot_regenerating_popconfirm.confirm(
886
+ fn=Gradio_Events.regenerating,
887
+ inputs=[state],
888
+ outputs=[chatbot, state
889
+ ]).then(fn=Gradio_Events.preprocess_submit(clear_input=False),
890
+ inputs=[state],
891
+ outputs=[
892
+ sender, attachments, attachments_badge, clear_btn,
893
+ conversation_delete_menu_item,
894
+ add_conversation_btn, conversations, chatbot,
895
+ state
896
+ ]).then(fn=Gradio_Events.submit,
897
+ inputs=[state],
898
+ outputs=[chatbot, state])
899
+
900
+ submit_event = sender.submit(
901
+ fn=Gradio_Events.add_user_message,
902
+ inputs=[sender, attachments, state],
903
+ outputs=[state
904
+ ]).then(fn=Gradio_Events.preprocess_submit(clear_input=True),
905
+ inputs=[state],
906
+ outputs=[
907
+ sender, attachments, attachments_badge, clear_btn,
908
+ conversation_delete_menu_item,
909
+ add_conversation_btn, conversations, chatbot,
910
+ state
911
+ ]).then(fn=Gradio_Events.submit,
912
+ inputs=[state],
913
+ outputs=[chatbot, state])
914
+ regenerating_event.then(fn=Gradio_Events.postprocess_submit,
915
+ inputs=[state],
916
+ outputs=[
917
+ sender, conversation_delete_menu_item,
918
+ clear_btn, conversations, add_conversation_btn,
919
+ chatbot, state
920
+ ])
921
  submit_event.then(fn=Gradio_Events.postprocess_submit,
922
  inputs=[state],
923
  outputs=[
924
  sender, conversation_delete_menu_item, clear_btn,
925
+ conversations, add_conversation_btn, chatbot, state
926
  ])
927
+ sender.cancel(fn=None, cancels=[submit_event, regenerating_event])
928
  sender.cancel(fn=Gradio_Events.cancel,
929
  inputs=[state],
930
  outputs=[
layout_templates/coder_artifacts/README.md CHANGED
@@ -1,6 +1,6 @@
1
  # Coder Artifacts
2
 
3
- A Application template for building code generation interfaces.
4
 
5
  ## Examples
6
 
 
1
  # Coder Artifacts
2
 
3
+ Application templates for building code generation interfaces.
4
 
5
  ## Examples
6
 
requirements.txt CHANGED
@@ -1,2 +1,2 @@
1
- modelscope_studio==1.1.6
2
  openai
 
1
+ modelscope_studio==1.1.7
2
  openai
src/pyproject.toml CHANGED
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
8
 
9
  [project]
10
  name = "modelscope_studio"
11
- version = "1.1.6"
12
  description = "A third-party component library based on Gradio."
13
  readme = "README.md"
14
  license = "Apache-2.0"
 
8
 
9
  [project]
10
  name = "modelscope_studio"
11
+ version = "1.1.7"
12
  description = "A third-party component library based on Gradio."
13
  readme = "README.md"
14
  license = "Apache-2.0"