hunyuan-t commited on
Commit
85554f4
·
verified ·
1 Parent(s): dd7f425

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +939 -118
app.py CHANGED
@@ -1,136 +1,957 @@
1
  import os
 
2
  import json
3
  from datetime import datetime
4
 
 
5
  import gradio as gr
 
 
 
6
  from openai import OpenAI
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
- def print_now(msg):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  now = datetime.now()
11
- formatted_time = now.strftime("%Y-%m-%d %H:%M:%S.%f")
12
- print(f"{msg}:{formatted_time}")
13
- return formatted_time
14
-
15
- def respond(
16
- message,
17
- history: list[tuple[str, str]],
18
- system_message,
19
- max_tokens,
20
- temperature,
21
- top_p,
22
- ):
23
- try:
24
- weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
25
- now = datetime.now()
26
- weekday_num = now.weekday()
27
- weekday_chinese = weekdays[weekday_num]
28
- formatted_time = now.strftime("%Y-%m-%d %H:%M:%S") + " " + weekday_chinese
29
- default_system = f"你是一个由腾讯开发的有用的人工智能助手,你的名字是“腾讯元宝”,简称“元宝”,你的英文名是“Tencent Yuanbao”,你乐于帮助大家解答问题。\n现在的时间是{formatted_time}"
30
-
31
- messages = [{"Role": "system", "Content": default_system}]
32
- client = OpenAI(
33
- api_key=os.getenv('HUNYUAN_API_KEY'),
34
- base_url="https://api.hunyuan.cloud.tencent.com/v1",
35
- )
36
- for val in history:
37
- if val[0] and val[1]:
38
- messages.append({"Role": "user", "Content": val[0]})
39
- pure_response = val[1].split("**End thinking**")[-1].strip()
40
- messages.append({"Role": "assistant", "Content": pure_response})
41
-
42
-
43
- messages.append({"Role": "user", "Content": message})
44
- completion = client.chat.completions.create(
45
- model="hunyuan-t1-latest",
46
- messages=messages,
47
- stream=True,
48
- extra_body={
49
- "stream_moderation": True,
50
- "enable_enhancement": False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
- )
53
- response = ""
54
- is_reasoning_start = True
55
- is_reasoning_end = True
56
-
57
-
58
- for event in completion:
59
- if message == "深圳哪里好玩?":
60
- print(111111)
61
- print(event.choices[0].delta.reasoning_content)
62
- print(event.choices[0].delta.content)
63
- if hasattr(event.choices[0].delta, 'reasoning_content') and event.choices[0].delta.reasoning_content:
64
- if is_reasoning_start:
65
- response += '> **Start thinking**\n\n'
66
- is_reasoning_start = False
67
- token = event.choices[0].delta.reasoning_content
68
- response += token
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  else:
70
- if is_reasoning_end:
71
- response += '> **End thinking**\n\n'
72
- is_reasoning_end = False
73
- token = event.choices[0].delta.content
74
- response += token
75
- yield response
76
- except Exception as e:
77
- raise gr.Error(f"发生错误: {str(e)}")
78
-
79
- example_prompts = [
80
- [
81
- "Write a short papragraph where the 1st letter of each sentence spells out the word 'CODE'. The message should appear natural and not obviously hide this pattern.",
82
- "System",
83
- 256,
84
- 0.8,
85
- 0.85
86
- ],
87
- [
88
- "Compose an engaging travel blog post about a recent trip to Hawaii, highlighting cultural experiences and must-see attractions.",
89
- "System",
90
- 128,
91
- 0.3,
92
- 0.9
93
- ],
94
- [
95
- "Why has online learning been able to spread rapidly in recent years?",
96
- "System",
97
- 64,
98
- 0.1,
99
- 0.95
100
- ],
101
- [
102
- "How many 'e' in Deeplearning?",
103
- "System",
104
- 512,
105
- 1.2,
106
- 0.75
107
- ],
108
- [
109
- "Write a 3-line poem",
110
- "System",
111
- 384,
112
- 0.6,
113
- 0.88
114
- ]
115
- ]
116
 
117
- latex_delimiters = [
118
- {"left": "$$", "right": "$$", "display": True},
119
- {"left": "\\[", "right": "\\]", "display": True},{"left": "$", "right": "$", "display": False},
120
- {"left": "\\(", "right": "\\)", "display": False}
121
- ]
 
 
 
122
 
 
 
 
123
 
124
- chatbot = gr.Chatbot(latex_delimiters=latex_delimiters, scale=9)
 
 
125
 
 
 
126
 
127
- demo = gr.ChatInterface(respond,
128
- title="Hunyuan-T1",
129
- # examples=example_prompts,
130
- chatbot=chatbot,
131
- description="当前体验demo为非联网Hunyuan-T1 最新推理模型,完整版联网/非联网能力即将在元宝上线,敬请期待!</br>The current demo is the latest reasoning model of Hunyuan-T1. The full version with browsing will be launched on Tencent Yuanbao soon. Stay tuned."
132
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  if __name__ == "__main__":
135
- demo.queue(default_concurrency_limit=100)
136
- demo.launch(max_threads=100)
 
1
  import os
2
+ import uuid
3
  import json
4
  from datetime import datetime
5
 
6
+
7
  import gradio as gr
8
+ import modelscope_studio.components.antd as antd
9
+ import modelscope_studio.components.antdx as antdx
10
+ import modelscope_studio.components.base as ms
11
  from openai import OpenAI
12
 
13
+ # Hunyuan/Hunyuan-T1
14
+
15
+ # =========== Configuration
16
+ # API KEY
17
+ client = OpenAI(
18
+ api_key=os.getenv('HUNYUAN_API_KEY'),
19
+ base_url="https://api.hunyuan.cloud.tencent.com/v1",
20
+ )
21
+
22
+ model = "hunyuan-t1-latest"
23
+
24
+ save_history = False
25
+
26
+ # =========== Configuration
27
+
28
+ is_modelscope_studio = os.getenv('MODELSCOPE_ENVIRONMENT') == 'studio'
29
 
30
+
31
+ def get_text(text: str, cn_text: str):
32
+ if is_modelscope_studio:
33
+ return cn_text
34
+ return text
35
+
36
+
37
+ hunyuan_logo = os.path.join(os.path.dirname(__file__), "hunyuan.png")
38
+
39
+ DEFAULT_PROMPTS = [{
40
+ "category":
41
+ "🖋 Make a plan",
42
+ "prompts": [
43
+ "Help me with a plan to start a business",
44
+ "Help me with a plan to achieve my goals",
45
+ "Help me with a plan for a successful interview"
46
+ ]
47
+ }, {
48
+ "category":
49
+ "📅 Help me write",
50
+ "prompts": [
51
+ "Help me write a story with a twist ending",
52
+ "Help me write a blog post on mental health",
53
+ "Help me write a letter to my future self"
54
+ ]
55
+ }]
56
+
57
+ DEFAULT_SUGGESTIONS = [{
58
+ "label":
59
+ 'Make a plan',
60
+ "value":
61
+ "Make a plan",
62
+ "children": [{
63
+ "label": "Start a business",
64
+ "value": "Help me with a plan to start a business"
65
+ }, {
66
+ "label": "Achieve my goals",
67
+ "value": "Help me with a plan to achieve my goals"
68
+ }, {
69
+ "label": "Successful interview",
70
+ "value": "Help me with a plan for a successful interview"
71
+ }]
72
+ }, {
73
+ "label":
74
+ 'Help me write',
75
+ "value":
76
+ "Help me write",
77
+ "children": [{
78
+ "label": "Story with a twist ending",
79
+ "value": "Help me write a story with a twist ending"
80
+ }, {
81
+ "label": "Blog post on mental health",
82
+ "value": "Help me write a blog post on mental health"
83
+ }, {
84
+ "label": "Letter to my future self",
85
+ "value": "Help me write a letter to my future self"
86
+ }]
87
+ }]
88
+
89
+ DEFAULT_CONVERSATIONS_HISTORY = [{"role": "placeholder"}]
90
+
91
+ DEFAULT_LOCALE = 'zh_CN' if is_modelscope_studio else 'en_US'
92
+
93
+ DEFAULT_THEME = {
94
+ "token": {
95
+ "colorPrimary": "#6A57FF",
96
+ }
97
+ }
98
+
99
+
100
+ def format_history(history):
101
+ weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
102
  now = datetime.now()
103
+ weekday_num = now.weekday()
104
+ weekday_chinese = weekdays[weekday_num]
105
+ formatted_time = now.strftime("%Y-%m-%d %H:%M:%S") + " " + weekday_chinese
106
+ default_system = f"你是一个由腾讯开发的有用的人工智能助手,你的名字是“腾讯元宝”,简称“元宝”,你的英文名是“Tencent Yuanbao”,你乐于帮助大家解答问题。\n现在的时间是{formatted_time}"
107
+ messages = [{"role": "system", "content": default_system}]
108
+ for item in history:
109
+ if item["role"] == "user":
110
+ messages.append({"role": "user", "content": item["content"]})
111
+ elif item["role"] == "assistant":
112
+ messages.append({"role": "assistant", "content": item["content"]})
113
+ return messages
114
+
115
+
116
+ class Gradio_Events:
117
+
118
+ @staticmethod
119
+ def _submit(state_value):
120
+ history = state_value["conversations_history"][
121
+ state_value["conversation_id"]]
122
+ # submit
123
+ history_messages = format_history(history)
124
+
125
+ history.append({
126
+ "role": "assistant",
127
+ "content": "",
128
+ "key": str(uuid.uuid4()),
129
+ "meta": {
130
+ "reason_content": ""
131
+ },
132
+ "loading": True,
133
+ })
134
+
135
+ yield {
136
+ chatbot: gr.update(items=history),
137
+ state: gr.update(value=state_value),
138
+ }
139
+ try:
140
+ response = client.chat.completions.create(
141
+ model=model, # ModelScope Model-Id
142
+ messages=history_messages,
143
+ stream=True,
144
+ extra_body={
145
+ "stream_moderation": True,
146
+ "enable_enhancement": False,
147
+ }
148
+ )
149
+ thought_done = False
150
+ for chunk in response:
151
+ reasoning_content = chunk.choices[0].delta.reasoning_content
152
+ content = chunk.choices[0].delta.content
153
+ history[-1]["loading"] = False
154
+
155
+ if content and not thought_done:
156
+ thought_done = True
157
+ history[-1]["meta"]["reason_content"] = history[-1][
158
+ "content"]
159
+
160
+ print("Reason: ",history[-1]["meta"]["reason_content"])
161
+
162
+ history[-1]["content"] = ""
163
+ history[-1]["meta"]["thought_end_message"] = get_text(
164
+ "End of Thought", "已深度思考")
165
+ if not thought_done:
166
+ history[-1]["content"] += reasoning_content or ""
167
+ else:
168
+ history[-1]["content"] += content or ""
169
+
170
+ yield {
171
+ chatbot: gr.update(items=history),
172
+ state: gr.update(value=state_value)
173
+ }
174
+ history[-1]["meta"]["end"] = True
175
+
176
+ print("Answer: ",history[-1]["content"])
177
+
178
+ yield {
179
+ chatbot: gr.update(items=history),
180
+ state: gr.update(value=state_value),
181
+ }
182
+ except Exception as e:
183
+ history[-1]["loading"] = False
184
+ history[-1]["meta"]["end"] = True
185
+ history[-1]["meta"]["error"] = True
186
+ history[-1]["content"] = "Failed to respond, please try again."
187
+ yield {
188
+ chatbot: gr.update(items=history),
189
+ state: gr.update(value=state_value)
190
  }
191
+ print('Error: ',e)
192
+ raise e
193
+
194
+
195
+ @staticmethod
196
+ def submit(sender_value, state_value):
197
+ if not state_value["conversation_id"]:
198
+ random_id = str(uuid.uuid4())
199
+ history = []
200
+ state_value["conversation_id"] = random_id
201
+ state_value["conversations_history"][random_id] = history
202
+ state_value["conversations"].append({
203
+ "label": sender_value,
204
+ "key": random_id
205
+ })
206
+
207
+ history = state_value["conversations_history"][
208
+ state_value["conversation_id"]]
209
+ history.append({
210
+ "role": "user",
211
+ "meta": {},
212
+ "key": str(uuid.uuid4()),
213
+ "content": sender_value
214
+ })
215
+
216
+ # preprocess submit
217
+ yield Gradio_Events.preprocess_submit()(state_value)
218
+ try:
219
+ for chunk in Gradio_Events._submit(state_value):
220
+ yield chunk
221
+ except Exception as e:
222
+ raise e
223
+ finally:
224
+ # postprocess submit
225
+ yield Gradio_Events.postprocess_submit(state_value)
226
+
227
+ @staticmethod
228
+ def regenerate_message(state_value, e: gr.EventData):
229
+ conversation_key = e._data["component"]["conversationKey"]
230
+ history = state_value["conversations_history"][
231
+ state_value["conversation_id"]]
232
+ index = -1
233
+ for i, conversation in enumerate(history):
234
+ if conversation["key"] == conversation_key:
235
+ index = i
236
+ break
237
+ if index == -1:
238
+ yield gr.skip()
239
+ history = history[:index]
240
+ state_value["conversations_history"][
241
+ state_value["conversation_id"]] = history
242
+
243
+ yield {
244
+ chatbot:gr.update(items=history),
245
+ state: gr.update(value=state_value)
246
+ }
247
+
248
+ # preprocess submit
249
+ yield Gradio_Events.preprocess_submit(clear_input=False)(state_value)
250
+ try:
251
+ for chunk in Gradio_Events._submit(state_value):
252
+ yield chunk
253
+ except Exception as e:
254
+ raise e
255
+ finally:
256
+ # postprocess submit
257
+ yield Gradio_Events.postprocess_submit(state_value)
258
+
259
+
260
+ @staticmethod
261
+ def preprocess_submit(clear_input=True):
262
+
263
+ def preprocess_submit_handler(state_value):
264
+ history = state_value["conversations_history"][
265
+ state_value["conversation_id"]]
266
+ for conversation in history:
267
+ if "meta" in conversation:
268
+ conversation["meta"]["disabled"] = True
269
+ return {
270
+ sender: gr.update(value=None, loading=True) if clear_input else gr.update(loading=True),
271
+ conversations:
272
+ gr.update(active_key=state_value["conversation_id"],
273
+ items=list(
274
+ map(
275
+ lambda item: {
276
+ **item,
277
+ "disabled":
278
+ True if item["key"] != state_value[
279
+ "conversation_id"] else False,
280
+ }, state_value["conversations"]))),
281
+ add_conversation_btn:
282
+ gr.update(disabled=True),
283
+ clear_btn:
284
+ gr.update(disabled=True),
285
+ conversation_delete_menu_item:
286
+ gr.update(disabled=True),
287
+ chatbot:
288
+ gr.update(items=history),
289
+ state:
290
+ gr.update(value=state_value),
291
+ }
292
+
293
+ return preprocess_submit_handler
294
+
295
+ @staticmethod
296
+ def postprocess_submit(state_value):
297
+ history = state_value["conversations_history"][
298
+ state_value["conversation_id"]]
299
+ for conversation in history:
300
+ if "meta" in conversation:
301
+ conversation["meta"]["disabled"] = False
302
+ return {
303
+ sender: gr.update(loading=False),
304
+ conversation_delete_menu_item: gr.update(disabled=False),
305
+ clear_btn: gr.update(disabled=False),
306
+ conversations: gr.update(items=state_value["conversations"]),
307
+ add_conversation_btn: gr.update(disabled=False),
308
+ chatbot: gr.update(items=history),
309
+ state: gr.update(value=state_value),
310
+ }
311
+
312
+ @staticmethod
313
+ def cancel(state_value):
314
+ history = state_value["conversations_history"][
315
+ state_value["conversation_id"]]
316
+ history[-1]["loading"] = False
317
+ history[-1]["meta"]["end"] = True
318
+ history[-1]["meta"]["canceled"] = True
319
+ return Gradio_Events.postprocess_submit(state_value)
320
+
321
+ @staticmethod
322
+ def delete_message(state_value, e: gr.EventData):
323
+ conversation_key = e._data["component"]["conversationKey"]
324
+ history = state_value["conversations_history"][
325
+ state_value["conversation_id"]]
326
+ history = [item for item in history if item["key"] != conversation_key]
327
+ state_value["conversations_history"][
328
+ state_value["conversation_id"]] = history
329
+
330
+ return gr.update(items=history if len(history) >
331
+ 0 else DEFAULT_CONVERSATIONS_HISTORY), gr.update(
332
+ value=state_value)
333
+
334
+
335
+
336
+ @staticmethod
337
+ def edit_message(state_value, e: gr.EventData):
338
+ conversation_key = e._data["component"]["conversationKey"]
339
+ history = state_value["conversations_history"][
340
+ state_value["conversation_id"]]
341
+ index = -1
342
+ for i, conversation in enumerate(history):
343
+ if conversation["key"] == conversation_key:
344
+ index = i
345
+ break
346
+ if index == -1:
347
+ return gr.skip()
348
+ state_value["editing_message_index"] = index
349
+ text = ''
350
+ if isinstance(history[index]["content"], str):
351
+ text = history[index]["content"]
352
+ else:
353
+ text = history[index]["content"]["text"]
354
+ return gr.update(value=text), gr.update(value=state_value)
355
+
356
+ @staticmethod
357
+ def confirm_edit_message(edit_textarea_value, state_value):
358
+ history = state_value["conversations_history"][
359
+ state_value["conversation_id"]]
360
+ message = history[state_value["editing_message_index"]]
361
+ if isinstance(message["content"], str):
362
+ message["content"] = edit_textarea_value
363
+ else:
364
+ message["content"]["text"] = edit_textarea_value
365
+ return gr.update(items=history), gr.update(value=state_value)
366
+
367
+ @staticmethod
368
+ def select_suggestion(sender_value, e: gr.EventData):
369
+ return gr.update(value=sender_value[:-1] + e._data["payload"][0])
370
+
371
+ @staticmethod
372
+ def apply_prompt(e: gr.EventData):
373
+ return gr.update(value=e._data["payload"][0]["data"]["description"])
374
+
375
+ @staticmethod
376
+ def new_chat(state_value):
377
+ if not state_value["conversation_id"]:
378
+ return gr.skip()
379
+ state_value["conversation_id"] = ""
380
+ return gr.update(active_key=state_value["conversation_id"]), gr.update(
381
+ items=DEFAULT_CONVERSATIONS_HISTORY), gr.update(value=state_value)
382
+
383
+ @staticmethod
384
+ def select_conversation(state_value, e: gr.EventData):
385
+ active_key = e._data["payload"][0]
386
+ if state_value["conversation_id"] == active_key or (
387
+ active_key not in state_value["conversations_history"]):
388
+ return gr.skip()
389
+ state_value["conversation_id"] = active_key
390
+ return gr.update(active_key=active_key), gr.update(
391
+ items=state_value["conversations_history"][active_key]), gr.update(
392
+ value=state_value)
393
+
394
+ @staticmethod
395
+ def click_conversation_menu(state_value, e: gr.EventData):
396
+ conversation_id = e._data["payload"][0]["key"]
397
+ operation = e._data["payload"][1]["key"]
398
+ if operation == "delete":
399
+ del state_value["conversations_history"][conversation_id]
400
+
401
+ state_value["conversations"] = [
402
+ item for item in state_value["conversations"]
403
+ if item["key"] != conversation_id
404
+ ]
405
+
406
+ if state_value["conversation_id"] == conversation_id:
407
+ state_value["conversation_id"] = ""
408
+ return gr.update(
409
+ items=state_value["conversations"],
410
+ active_key=state_value["conversation_id"]), gr.update(
411
+ items=DEFAULT_CONVERSATIONS_HISTORY), gr.update(
412
+ value=state_value)
413
  else:
414
+ return gr.update(
415
+ items=state_value["conversations"]), gr.skip(), gr.update(
416
+ value=state_value)
417
+ return gr.skip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
+ @staticmethod
420
+ def clear_conversation_history(state_value):
421
+ if not state_value["conversation_id"]:
422
+ return gr.skip()
423
+ state_value["conversations_history"][
424
+ state_value["conversation_id"]] = []
425
+ return gr.update(items=DEFAULT_CONVERSATIONS_HISTORY), gr.update(
426
+ value=state_value)
427
 
428
+ @staticmethod
429
+ def close_modal():
430
+ return gr.update(open=False)
431
 
432
+ @staticmethod
433
+ def open_modal():
434
+ return gr.update(open=True)
435
 
436
+ @staticmethod
437
+ def update_browser_state(state_value):
438
 
439
+ return gr.update(value=dict(
440
+ conversations=state_value["conversations"],
441
+ conversations_history=state_value["conversations_history"]))
442
+
443
+ @staticmethod
444
+ def apply_browser_state(browser_state_value, state_value):
445
+ state_value["conversations"] = browser_state_value["conversations"]
446
+ state_value["conversations_history"] = browser_state_value[
447
+ "conversations_history"]
448
+ return gr.update(
449
+ items=browser_state_value["conversations"]), gr.update(
450
+ value=state_value)
451
+
452
+
453
+ css = """
454
+ .gradio-container {
455
+ padding: 0 !important;
456
+ }
457
+
458
+ .gradio-container > main.fillable {
459
+ padding: 0 !important;
460
+ }
461
+
462
+ #chatbot {
463
+ height: calc(100vh - 21px - 16px);
464
+ }
465
+
466
+ #chatbot .chatbot-conversations {
467
+ height: 100%;
468
+ background-color: var(--ms-gr-ant-color-bg-layout);
469
+ }
470
+
471
+ #chatbot .chatbot-conversations .chatbot-conversations-list {
472
+ padding-left: 0;
473
+ padding-right: 0;
474
+ }
475
+
476
+ #chatbot .chatbot-chat {
477
+ padding: 32px;
478
+ height: 100%;
479
+ }
480
+
481
+ @media (max-width: 768px) {
482
+ #chatbot .chatbot-chat {
483
+ padding: 0;
484
+ }
485
+ }
486
+
487
+ #chatbot .chatbot-chat .chatbot-chat-messages {
488
+ flex: 1;
489
+ }
490
+
491
+ #chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message .chatbot-chat-message-footer {
492
+ visibility: hidden;
493
+ opacity: 0;
494
+ transition: opacity 0.2s;
495
+ }
496
+
497
+ #chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message:last-child .chatbot-chat-message-footer {
498
+ visibility: visible;
499
+ opacity: 1;
500
+ }
501
+
502
+ #chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message:hover .chatbot-chat-message-footer {
503
+ visibility: visible;
504
+ opacity: 1;
505
+ }
506
+ """
507
+
508
+
509
+ def logo():
510
+ with antd.Typography.Title(level=1,
511
+ elem_style=dict(fontSize=24,
512
+ padding=8,
513
+ margin=0)):
514
+ with antd.Flex(align="center", gap="small", justify="center"):
515
+ antd.Image(hunyuan_logo,
516
+ preview=False,
517
+ alt="logo",
518
+ width=24,
519
+ height=24)
520
+ ms.Span("Hunyuan-T1")
521
+
522
+
523
+ with gr.Blocks(css=css, fill_width=True) as demo:
524
+ state = gr.State({
525
+ "conversations_history": {},
526
+ "conversations": [],
527
+ "conversation_id": "",
528
+ "editing_message_index": -1,
529
+ })
530
+
531
+ with ms.Application(), antdx.XProvider(
532
+ theme=DEFAULT_THEME, locale=DEFAULT_LOCALE), ms.AutoLoading():
533
+ with antd.Row(gutter=[20, 20], wrap=False, elem_id="chatbot"):
534
+ # Left Column
535
+ with antd.Col(md=dict(flex="0 0 260px", span=24, order=0),
536
+ span=0,
537
+ order=1,
538
+ elem_classes="chatbot-conversations"):
539
+ with antd.Flex(vertical=True,
540
+ gap="small",
541
+ elem_style=dict(height="100%")):
542
+ # Logo
543
+ logo()
544
+
545
+ # New Conversation Button
546
+ with antd.Button(value=None,
547
+ color="primary",
548
+ variant="filled",
549
+ block=True) as add_conversation_btn:
550
+ ms.Text(get_text("New Conversation", "新建对话"))
551
+ with ms.Slot("icon"):
552
+ antd.Icon("PlusOutlined")
553
+
554
+ # Conversations List
555
+ with antdx.Conversations(
556
+ elem_classes="chatbot-conversations-list",
557
+ ) as conversations:
558
+ with ms.Slot('menu.items'):
559
+ with antd.Menu.Item(
560
+ label="Delete", key="delete", danger=True
561
+ ) as conversation_delete_menu_item:
562
+ with ms.Slot("icon"):
563
+ antd.Icon("DeleteOutlined")
564
+ # Right Column
565
+ with antd.Col(flex=1, elem_style=dict(height="100%")):
566
+ with antd.Flex(vertical=True,
567
+ gap="middle",
568
+ elem_classes="chatbot-chat"):
569
+ # Chatbot
570
+ with antdx.Bubble.List(
571
+ items=DEFAULT_CONVERSATIONS_HISTORY,
572
+ elem_classes="chatbot-chat-messages") as chatbot:
573
+ # Define Chatbot Roles
574
+ with ms.Slot("roles"):
575
+ # Placeholder Role
576
+ with antdx.Bubble.List.Role(
577
+ role="placeholder",
578
+ styles=dict(content=dict(width="100%")),
579
+ variant="borderless"):
580
+ with ms.Slot("messageRender"):
581
+ with antd.Space(
582
+ direction="vertical",
583
+ size=16,
584
+ elem_style=dict(width="100%")):
585
+ with antdx.Welcome(
586
+ styles=dict(icon=dict(
587
+ flexShrink=0)),
588
+ variant="borderless",
589
+ title=get_text(
590
+ "Hello, I'm Hunyuan-T1",
591
+ "你好,我是 Hunyuan-T1"),
592
+ description=get_text(
593
+ "当前体验demo为非联网Hunyuan-T1 最新推理模型,完整版联网/非联网能力即将在元宝上线,敬请期待!(The current demo is the latest reasoning model of Hunyuan-T1. The full version with browsing will be launched on Tencent Yuanbao soon. Stay tuned.)",
594
+ "你可以输入文本开始对话。"),
595
+ ):
596
+ with ms.Slot("icon"):
597
+ antd.Image(hunyuan_logo,
598
+ preview=False)
599
+ with antdx.Prompts(title=get_text(
600
+ "How can I help you today?",
601
+ "有什么我能帮助你的吗?"),
602
+ styles={
603
+ "list": {
604
+ "width":
605
+ '100%',
606
+ },
607
+ "item": {
608
+ "flex": 1,
609
+ },
610
+ }) as prompts:
611
+ for item in DEFAULT_PROMPTS:
612
+ with antdx.Prompts.Item(
613
+ label=item["category"]
614
+ ):
615
+ for prompt in item[
616
+ "prompts"]:
617
+ antdx.Prompts.Item(
618
+ description=prompt,
619
+ )
620
+
621
+ # User Role
622
+ with antdx.Bubble.List.Role(
623
+ role="user",
624
+ placement="end",
625
+ elem_classes="chatbot-chat-message",
626
+ class_names=dict(
627
+ footer="chatbot-chat-message-footer"),
628
+ styles=dict(content=dict(
629
+ maxWidth="100%",
630
+ overflow='auto',
631
+ ))):
632
+ with ms.Slot(
633
+ "messageRender",
634
+ params_mapping="(content) => content"):
635
+
636
+ ms.Markdown()
637
+ with ms.Slot("footer",
638
+ params_mapping="""(bubble) => {
639
+ return {
640
+ copy_btn: {
641
+ copyable: { text: typeof bubble.content === 'string' ? bubble.content : bubble.content?.text, tooltips: false },
642
+ },
643
+ edit_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
644
+ delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
645
+ };
646
+ }"""):
647
+ with antd.Typography.Text(
648
+ copyable=dict(tooltips=False),
649
+ as_item="copy_btn"):
650
+ with ms.Slot("copyable.icon"):
651
+ with antd.Button(value=None,
652
+ size="small",
653
+ color="default",
654
+ variant="text"):
655
+ with ms.Slot("icon"):
656
+ antd.Icon("CopyOutlined")
657
+ with antd.Button(value=None,
658
+ size="small",
659
+ color="default",
660
+ variant="text"):
661
+ with ms.Slot("icon"):
662
+ antd.Icon("CheckOutlined")
663
+ with antd.Button(value=None,
664
+ size="small",
665
+ color="default",
666
+ variant="text",
667
+ as_item="edit_btn"
668
+ ) as user_edit_btn:
669
+ with ms.Slot("icon"):
670
+ antd.Icon("EditOutlined")
671
+ with antd.Popconfirm(
672
+ title="Delete the message",
673
+ description=
674
+ "Are you sure to delete this message?",
675
+ ok_button_props=dict(danger=True),
676
+ as_item="delete_btn"
677
+ ) as user_delete_popconfirm:
678
+ with antd.Button(value=None,
679
+ size="small",
680
+ color="default",
681
+ variant="text",
682
+ as_item="delete_btn"):
683
+ with ms.Slot("icon"):
684
+ antd.Icon("DeleteOutlined")
685
+
686
+ # Chatbot Role
687
+ with antdx.Bubble.List.Role(
688
+ role="assistant",
689
+ placement="start",
690
+ elem_classes="chatbot-chat-message",
691
+ class_names=dict(
692
+ footer="chatbot-chat-message-footer"),
693
+ styles=dict(content=dict(
694
+ maxWidth="100%", overflow='auto'))):
695
+ with ms.Slot("avatar"):
696
+ antd.Avatar(
697
+ os.path.join(os.path.dirname(__file__),
698
+ "hunyuan.png"))
699
+ with ms.Slot(
700
+ "messageRender",
701
+ params_mapping="""(content, bubble) => {
702
+ const reason_content = bubble?.meta?.reason_content
703
+ const has_error = bubble?.meta?.error
704
+ return {
705
+ reasoning: reason_content || content,
706
+ reasoning_container: has_error ? { style: { display: 'none' } } : undefined,
707
+ answer: {
708
+ value: reason_content || has_error ? content : undefined
709
+ },
710
+ collapse_label: bubble.meta?.thought_end_message,
711
+ collapse_progress: bubble.meta?.thought_end_message ? { style: { display: 'none' } } : undefined,
712
+ canceled: bubble.meta?.canceled ? undefined : { style: { display: 'none' } }
713
+ }
714
+ }"""):
715
+ with antd.Flex(vertical=True,
716
+ gap="middle"):
717
+ with antd.Collapse(
718
+ default_active_key=[
719
+ "reasoning"
720
+ ],
721
+ as_item="reasoning_container"):
722
+ with antd.Collapse.Item(
723
+ key="reasoning"):
724
+ with ms.Slot("label"):
725
+ with antd.Space(
726
+ size="middle"):
727
+ ms.Span(
728
+ get_text(
729
+ "Thinking...",
730
+ "思考中..."),
731
+ as_item=
732
+ "collapse_label")
733
+ antd.Progress(
734
+ percent="100",
735
+ status="active",
736
+ elem_style=dict(
737
+ display="flex",
738
+ alignItems=
739
+ "center",
740
+ ),
741
+ show_info=False,
742
+ size=[110, 5],
743
+ as_item=
744
+ "collapse_progress"
745
+ )
746
+ with antd.Alert(
747
+ type="warning"):
748
+ with ms.Slot(
749
+ "description"):
750
+ ms.Markdown(
751
+ as_item="reasoning"
752
+ )
753
+ ms.Markdown(
754
+ as_item="answer",
755
+ elem_classes="answer-content")
756
+
757
+ antd.Divider(as_item="canceled")
758
+ antd.Typography.Text(get_text(
759
+ "Chat completion paused.", "聊天已暂停。"),
760
+ as_item="canceled",
761
+ type="warning")
762
+
763
+ with ms.Slot("footer",
764
+ params_mapping="""(bubble) => {
765
+ if (bubble?.meta?.end) {
766
+ return {
767
+ copy_btn: {
768
+ copyable: { text: bubble.content, tooltips: false },
769
+ },
770
+ regenerate_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
771
+ delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
772
+ edit_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled },
773
+ };
774
+ }
775
+ return { actions_container: { style: { display: 'none' } } };
776
+ }"""):
777
+ with ms.Div(as_item="actions_container"):
778
+ with antd.Typography.Text(
779
+ copyable=dict(tooltips=False),
780
+ as_item="copy_btn"):
781
+ with ms.Slot("copyable.icon"):
782
+ with antd.Button(
783
+ value=None,
784
+ size="small",
785
+ color="default",
786
+ variant="text"):
787
+ with ms.Slot("icon"):
788
+ antd.Icon(
789
+ "CopyOutlined")
790
+ with antd.Button(
791
+ value=None,
792
+ size="small",
793
+ color="default",
794
+ variant="text"):
795
+ with ms.Slot("icon"):
796
+ antd.Icon(
797
+ "CheckOutlined")
798
+
799
+ with antd.Popconfirm(
800
+ title=get_text(
801
+ "Regenerate the message",
802
+ "重新生成消息"),
803
+ description=get_text(
804
+ "Regenerate the message will also delete all subsequent messages.",
805
+ "重新生成消息将会删除所有的后续消息。"),
806
+ ok_button_props=dict(
807
+ danger=True),
808
+ as_item="regenerate_btn"
809
+ ) as chatbot_regenerate_popconfirm:
810
+ with antd.Button(
811
+ value=None,
812
+ size="small",
813
+ color="default",
814
+ variant="text",
815
+ as_item="regenerate_btn",
816
+ ):
817
+ with ms.Slot("icon"):
818
+ antd.Icon("SyncOutlined")
819
+ with antd.Button(value=None,
820
+ size="small",
821
+ color="default",
822
+ variant="text",
823
+ as_item="edit_btn"
824
+ ) as chatbot_edit_btn:
825
+ with ms.Slot("icon"):
826
+ antd.Icon("EditOutlined")
827
+ with antd.Popconfirm(
828
+ title=get_text("Delete the message", "删除消息"),
829
+ description=get_text(
830
+ "Are you sure to delete this message?",
831
+ "确定要删除这条消息吗?"),
832
+ ok_button_props=dict(
833
+ danger=True),
834
+ as_item="delete_btn"
835
+ ) as chatbot_delete_popconfirm:
836
+ with antd.Button(
837
+ value=None,
838
+ size="small",
839
+ color="default",
840
+ variant="text",
841
+ as_item="delete_btn"):
842
+ with ms.Slot("icon"):
843
+ antd.Icon("DeleteOutlined")
844
+
845
+ # Sender
846
+ with antdx.Suggestion(
847
+ items=DEFAULT_SUGGESTIONS,
848
+ # onKeyDown Handler in Javascript
849
+ should_trigger="""(e, { onTrigger, onKeyDown }) => {
850
+ switch(e.key) {
851
+ case '/':
852
+ onTrigger()
853
+ break
854
+ case 'ArrowRight':
855
+ case 'ArrowLeft':
856
+ case 'ArrowUp':
857
+ case 'ArrowDown':
858
+ break;
859
+ default:
860
+ onTrigger(false)
861
+ }
862
+ onKeyDown(e)
863
+ }""") as suggestion:
864
+ with ms.Slot("children"):
865
+ with antdx.Sender(placeholder=get_text(
866
+ "Enter / to get suggestions",
867
+ "输入 / 获取建议"), ) as sender:
868
+ with ms.Slot("prefix"):
869
+ # Clear Button
870
+ with antd.Tooltip(title=get_text(
871
+ "Clear Conversation History",
872
+ "清空对话历史"), ):
873
+ with antd.Button(
874
+ value=None,
875
+ type="text") as clear_btn:
876
+ with ms.Slot("icon"):
877
+ antd.Icon("ClearOutlined")
878
+
879
+ # Modals
880
+ with antd.Modal(title=get_text("Edit Message", "编辑消息"),
881
+ open=False,
882
+ centered=True,
883
+ width="60%") as edit_modal:
884
+ edit_textarea = antd.Input.Textarea(auto_size=dict(minRows=2,
885
+ maxRows=6),
886
+ elem_style=dict(width="100%"))
887
+ # Events Handler
888
+ if save_history:
889
+ browser_state = gr.BrowserState(
890
+ {
891
+ "conversations_history": {},
892
+ "conversations": [],
893
+ },
894
+ storage_key="hunyuan_qwq_chatbot_storage")
895
+ state.change(fn=Gradio_Events.update_browser_state,
896
+ inputs=[state],
897
+ outputs=[browser_state])
898
+
899
+ demo.load(fn=Gradio_Events.apply_browser_state,
900
+ inputs=[browser_state, state],
901
+ outputs=[conversations, state])
902
+
903
+ add_conversation_btn.click(fn=Gradio_Events.new_chat,
904
+ inputs=[state],
905
+ outputs=[conversations, chatbot, state])
906
+ conversations.active_change(fn=Gradio_Events.select_conversation,
907
+ inputs=[state],
908
+ outputs=[conversations, chatbot, state])
909
+ conversations.menu_click(fn=Gradio_Events.click_conversation_menu,
910
+ inputs=[state],
911
+ outputs=[conversations, chatbot, state])
912
+ prompts.item_click(fn=Gradio_Events.apply_prompt, outputs=[sender])
913
+
914
+ clear_btn.click(fn=Gradio_Events.clear_conversation_history,
915
+ inputs=[state],
916
+ outputs=[chatbot, state])
917
+
918
+ suggestion.select(fn=Gradio_Events.select_suggestion,
919
+ inputs=[sender],
920
+ outputs=[sender])
921
+
922
+ gr.on(triggers=[user_edit_btn.click, chatbot_edit_btn.click],
923
+ fn=Gradio_Events.edit_message,
924
+ inputs=[state],
925
+ outputs=[edit_textarea, state]).then(fn=Gradio_Events.open_modal,
926
+ outputs=[edit_modal])
927
+ edit_modal.ok(fn=Gradio_Events.confirm_edit_message,
928
+ inputs=[edit_textarea, state],
929
+ outputs=[chatbot, state]).then(fn=Gradio_Events.close_modal,
930
+ outputs=[edit_modal])
931
+ edit_modal.cancel(fn=Gradio_Events.close_modal, outputs=[edit_modal])
932
+ gr.on(triggers=[
933
+ chatbot_delete_popconfirm.confirm, user_delete_popconfirm.confirm
934
+ ],
935
+ fn=Gradio_Events.delete_message,
936
+ inputs=[state],
937
+ outputs=[chatbot, state])
938
+
939
+ regenerating_event = chatbot_regenerate_popconfirm.confirm(
940
+ fn=Gradio_Events.regenerate_message,
941
+ inputs=[state],
942
+ outputs=[sender, clear_btn, conversation_delete_menu_item, add_conversation_btn, conversations, chatbot, state])
943
+
944
+ submit_event = sender.submit(fn=Gradio_Events.submit,
945
+ inputs=[sender, state],
946
+ outputs=[sender, clear_btn, conversation_delete_menu_item,
947
+ add_conversation_btn, conversations,chatbot, state])
948
+ sender.cancel(fn=None, cancels=[submit_event, regenerating_event])
949
+ sender.cancel(fn=Gradio_Events.cancel,
950
+ inputs=[state],
951
+ outputs=[
952
+ sender, conversation_delete_menu_item, clear_btn,
953
+ conversations, add_conversation_btn, chatbot, state
954
+ ])
955
 
956
  if __name__ == "__main__":
957
+ demo.queue(default_concurrency_limit=200).launch(ssr_mode=False, max_threads=200)