Spaces:
Running
Running
Cherrytest
commited on
Commit
·
fa891b1
1
Parent(s):
8411a7d
Update app.py
Browse files
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(
|
|
|
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(
|
|
|
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':
|
135 |
-
'
|
136 |
-
'
|
|
|
|
|
|
|
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(
|
237 |
-
|
|
|
|
|
238 |
else:
|
239 |
reasoning_duration = 0.0
|
240 |
thought_cost_time = "0.00"
|
241 |
-
message_content[-2]["options"] = {
|
|
|
|
|
|
|
|
|
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(
|
|
|
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(
|
257 |
-
|
|
|
|
|
258 |
else:
|
259 |
reasoning_duration = 0.0
|
260 |
thought_cost_time = "0.00"
|
261 |
else:
|
262 |
-
thought_cost_time = "{:.2f}".format(
|
263 |
-
|
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() -
|
|
|
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(
|
|
|
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(
|
|
|
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(
|
|
|
|
|
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,
|
|
|
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:
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
438 |
}
|
439 |
else:
|
440 |
yield {
|
441 |
-
code_output:
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
}
|
448 |
elif 'message' in choice:
|
449 |
message_data = choice['message']
|
450 |
content = message_data.get('content', '')
|
451 |
-
reasoning_content = message_data.get(
|
|
|
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:
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
463 |
}
|
464 |
-
|
465 |
# If successful, break out of retry loop
|
466 |
break
|
467 |
-
|
468 |
-
except (requests.exceptions.Timeout,
|
|
|
469 |
retry_count += 1
|
470 |
if retry_count == max_retries:
|
471 |
print(f"Failed after {max_retries} attempts:", str(e))
|
472 |
-
raise gr.Error(
|
|
|
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:
|
500 |
-
|
501 |
}
|
502 |
|
503 |
.output-html {
|
504 |
display: flex;
|
505 |
flex-direction: column;
|
506 |
width: 100%;
|
507 |
-
height:
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
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.
|
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 |
-
|
|
|
|
|
730 |
with antd.Tabs() as tabs:
|
731 |
with antd.Tabs.Item(key="chat", label="Chatbot"):
|
732 |
-
with antd.Flex(vertical=True,
|
|
|
|
|
733 |
chatbot = pro.Chatbot(
|
734 |
-
|
735 |
-
markdown_config=ChatbotMarkdownConfig(
|
|
|
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,
|
|
|
|
|
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 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
chatbot.
|
782 |
-
|
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],
|
790 |
-
|
|
|
791 |
with antd.Flex(vertical=True, gap="middle"):
|
792 |
-
code_input = antd.
|
793 |
size="large",
|
794 |
allow_clear=True,
|
795 |
-
|
|
|
|
|
796 |
)
|
797 |
-
code_btn = antd.Button("Generate Code",
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
|
|
|
|
|
|
|
|
|
|
806 |
antd.Divider("Examples")
|
807 |
|
808 |
# Examples with categories
|
809 |
-
with antd.Tabs(
|
|
|
810 |
for category, examples in EXAMPLES.items():
|
811 |
-
with antd.Tabs.Item(key=category,
|
|
|
812 |
with antd.Flex(gap="small", wrap=True):
|
813 |
for example in examples:
|
814 |
with antd.Card(
|
815 |
-
|
816 |
-
|
817 |
) as example_card:
|
818 |
antd.Card.Meta(
|
819 |
title=example['title'],
|
820 |
-
description=example[
|
821 |
-
|
822 |
|
823 |
example_card.click(
|
824 |
fn=select_example,
|
825 |
inputs=[gr.State(example)],
|
826 |
-
outputs=[code_input]
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
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(
|
|
|
|
|
|
|
842 |
with antd.Tabs.Item(key="loading"):
|
843 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
844 |
with antd.Tabs.Item(key="render"):
|
845 |
sandbox = gr.HTML(elem_classes="output-html")
|
846 |
|
847 |
-
code_btn.click(
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
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(
|
|
|
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)
|