Spaces:
Running
Running
feat: add layout template `coder_artifacts`
Browse files- app.py +77 -7
- components/antd/table/demos/custom_columns.py +1 -0
- components/antdx/bubble/README-zh_CN.md +12 -0
- components/antdx/bubble/README.md +12 -0
- components/antdx/bubble/app.py +6 -0
- components/antdx/bubble/demos/basic.py +90 -0
- components/antdx/bubble/demos/bubble_list.py +83 -0
- components/antdx/bubble/demos/chatbot.py +149 -0
- components/antdx/bubble/demos/custom_list_content.py +118 -0
- components/antdx/bubble/demos/typing_effect.py +41 -0
- components/antdx/bubble/demos/variant.py +56 -0
- components/antdx/conversations/README-zh_CN.md +9 -0
- components/antdx/conversations/README.md +9 -0
- components/antdx/conversations/app.py +6 -0
- components/antdx/conversations/demos/basic.py +49 -0
- components/antdx/conversations/demos/group.py +30 -0
- components/antdx/conversations/demos/operations.py +46 -0
- components/antdx/overview/README-zh_CN.md +20 -0
- components/antdx/overview/README.md +20 -0
- components/antdx/overview/app.py +6 -0
- components/antdx/overview/demos/quick_start.py +17 -0
- components/antdx/prompts/README-zh_CN.md +8 -0
- components/antdx/prompts/README.md +8 -0
- components/antdx/prompts/app.py +6 -0
- components/antdx/prompts/demos/basic.py +81 -0
- components/antdx/prompts/demos/nest_usage.py +86 -0
- components/antdx/welcome/README-zh_CN.md +7 -0
- components/antdx/welcome/README.md +7 -0
- components/antdx/welcome/app.py +6 -0
- components/antdx/welcome/demos/basic.py +36 -0
- helper/Docs.py +52 -29
- helper/Site.py +6 -1
- helper/parse_markdown.py +2 -0
- layout_templates/coder_artifacts/README-zh_CN.md +7 -0
- layout_templates/coder_artifacts/README.md +7 -0
- layout_templates/coder_artifacts/app.py +6 -0
- layout_templates/coder_artifacts/demos/app.py +446 -0
- requirements.txt +2 -1
- src/pyproject.toml +4 -1
app.py
CHANGED
@@ -15,11 +15,11 @@ def get_text(text: str, cn_text: str):
|
|
15 |
return text
|
16 |
|
17 |
|
18 |
-
def get_docs(
|
19 |
import importlib.util
|
20 |
|
21 |
components = []
|
22 |
-
components_dir = os.path.join(os.path.dirname(
|
23 |
type)
|
24 |
for dir in os.listdir(components_dir):
|
25 |
abs_dir = os.path.join(components_dir, dir)
|
@@ -38,15 +38,49 @@ def get_docs(file_path: str, type: Literal["antd", "base"]):
|
|
38 |
return docs
|
39 |
|
40 |
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
45 |
|
46 |
default_active_tab = "index"
|
47 |
index_menu_items = [{
|
48 |
"label": get_text("ModelScope-Studio", "ModelScope-Studio"),
|
49 |
-
"key": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}]
|
51 |
|
52 |
base_menu_items = [{
|
@@ -350,6 +384,35 @@ antd_menu_items = [{
|
|
350 |
}]
|
351 |
}]
|
352 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
|
354 |
def logo():
|
355 |
with antd.Flex(align='center', gap=8):
|
@@ -386,7 +449,7 @@ tabs = [
|
|
386 |
{
|
387 |
"label": get_text("Overview", "概览"),
|
388 |
"key": "index",
|
389 |
-
"default_active_key": "
|
390 |
"menus": index_menu_items
|
391 |
},
|
392 |
{
|
@@ -402,6 +465,12 @@ tabs = [
|
|
402 |
"menus": antd_menu_items,
|
403 |
"extra_menu_footer": more_components
|
404 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
{
|
406 |
"label": get_text("Version 0.x", "0.x 版本"),
|
407 |
"key": "legacy",
|
@@ -415,6 +484,7 @@ site = Site(
|
|
415 |
# match the key of tabs
|
416 |
"index": index_docs,
|
417 |
"antd": antd_docs,
|
|
|
418 |
"base": base_docs
|
419 |
},
|
420 |
default_active_tab=default_active_tab,
|
|
|
15 |
return text
|
16 |
|
17 |
|
18 |
+
def get_docs(type: Literal["antd", "antdx", "base"]):
|
19 |
import importlib.util
|
20 |
|
21 |
components = []
|
22 |
+
components_dir = os.path.join(os.path.dirname(__file__), "components",
|
23 |
type)
|
24 |
for dir in os.listdir(components_dir):
|
25 |
abs_dir = os.path.join(components_dir, dir)
|
|
|
38 |
return docs
|
39 |
|
40 |
|
41 |
+
def get_layout_templates():
|
42 |
+
import importlib.util
|
43 |
+
|
44 |
+
templates = []
|
45 |
+
templates_dir = os.path.join(os.path.dirname(__file__), "layout_templates")
|
46 |
+
for dir in os.listdir(templates_dir):
|
47 |
+
abs_dir = os.path.join(templates_dir, dir)
|
48 |
+
if os.path.isdir(abs_dir):
|
49 |
+
app_file = os.path.join(abs_dir, "app.py")
|
50 |
+
if os.path.exists(app_file):
|
51 |
+
templates.append(dir)
|
52 |
+
|
53 |
+
docs = {}
|
54 |
+
for template in templates:
|
55 |
+
spec = importlib.util.spec_from_file_location(
|
56 |
+
"doc", os.path.join(templates_dir, template, "app.py"))
|
57 |
+
module = importlib.util.module_from_spec(spec)
|
58 |
+
spec.loader.exec_module(module)
|
59 |
+
docs[template] = module.docs
|
60 |
+
return docs
|
61 |
+
|
62 |
+
|
63 |
+
layout_templates = get_layout_templates()
|
64 |
|
65 |
+
index_docs = {"overview": Docs(__file__), **layout_templates}
|
66 |
+
|
67 |
+
base_docs = get_docs("base")
|
68 |
+
antd_docs = get_docs("antd")
|
69 |
+
# antdx_docs = get_docs("antdx")
|
70 |
|
71 |
default_active_tab = "index"
|
72 |
index_menu_items = [{
|
73 |
"label": get_text("ModelScope-Studio", "ModelScope-Studio"),
|
74 |
+
"key": "overview"
|
75 |
+
}, {
|
76 |
+
"label":
|
77 |
+
get_text("Layout Templates", "布局模板"),
|
78 |
+
"type":
|
79 |
+
"group",
|
80 |
+
"children": [{
|
81 |
+
"label": get_text("Coder-Artifacts", "Coder-Artifacts"),
|
82 |
+
"key": "coder_artifacts"
|
83 |
+
}]
|
84 |
}]
|
85 |
|
86 |
base_menu_items = [{
|
|
|
384 |
}]
|
385 |
}]
|
386 |
|
387 |
+
antdx_menu_items = [{
|
388 |
+
"label": get_text("Overview", "概览"),
|
389 |
+
"key": "overview"
|
390 |
+
}, {
|
391 |
+
"label":
|
392 |
+
get_text("Common", "通用"),
|
393 |
+
"type":
|
394 |
+
"group",
|
395 |
+
"children": [{
|
396 |
+
"label": get_text("Bubble", "Bubble 对话气泡"),
|
397 |
+
"key": "bubble"
|
398 |
+
}, {
|
399 |
+
"label": get_text("Conversations", "Conversations 管理对话"),
|
400 |
+
"key": "conversations"
|
401 |
+
}]
|
402 |
+
}, {
|
403 |
+
"label":
|
404 |
+
get_text("Wake", "唤醒"),
|
405 |
+
"type":
|
406 |
+
"group",
|
407 |
+
"children": [{
|
408 |
+
"label": get_text("Welcome", "Welcome 欢迎"),
|
409 |
+
"key": "welcome"
|
410 |
+
}, {
|
411 |
+
"label": get_text("Prompts", "Prompts 提示集"),
|
412 |
+
"key": "prompts"
|
413 |
+
}]
|
414 |
+
}]
|
415 |
+
|
416 |
|
417 |
def logo():
|
418 |
with antd.Flex(align='center', gap=8):
|
|
|
449 |
{
|
450 |
"label": get_text("Overview", "概览"),
|
451 |
"key": "index",
|
452 |
+
"default_active_key": "overview",
|
453 |
"menus": index_menu_items
|
454 |
},
|
455 |
{
|
|
|
465 |
"menus": antd_menu_items,
|
466 |
"extra_menu_footer": more_components
|
467 |
},
|
468 |
+
# {
|
469 |
+
# "label": get_text("Antdx Components", "Antdx 组件"),
|
470 |
+
# "key": "antdx",
|
471 |
+
# "default_active_key": "overview",
|
472 |
+
# "menus": antdx_menu_items,
|
473 |
+
# },
|
474 |
{
|
475 |
"label": get_text("Version 0.x", "0.x 版本"),
|
476 |
"key": "legacy",
|
|
|
484 |
# match the key of tabs
|
485 |
"index": index_docs,
|
486 |
"antd": antd_docs,
|
487 |
+
# "antdx": antdx_docs,
|
488 |
"base": base_docs
|
489 |
},
|
490 |
default_active_tab=default_active_tab,
|
components/antd/table/demos/custom_columns.py
CHANGED
@@ -69,6 +69,7 @@ with gr.Blocks() as demo:
|
|
69 |
):
|
70 |
with ms.Slot(
|
71 |
"render",
|
|
|
72 |
"(_, record, index) => ({ invite: { value: 'Invite ' + record.name, index }, delete: { index }})"
|
73 |
):
|
74 |
with antd.Space(size="middle"):
|
|
|
69 |
):
|
70 |
with ms.Slot(
|
71 |
"render",
|
72 |
+
params_mapping=
|
73 |
"(_, record, index) => ({ invite: { value: 'Invite ' + record.name, index }, delete: { index }})"
|
74 |
):
|
75 |
with antd.Space(size="middle"):
|
components/antdx/bubble/README-zh_CN.md
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Bubble
|
2 |
+
|
3 |
+
A bubble component for chat. See [Ant Design X](https://x.ant.design/components/bubble/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic" position="bottom" collapsible="true"></demo>
|
8 |
+
<demo name="typing_effect" title="Typing Effect"></demo>
|
9 |
+
<demo name="variant" title="Variant"></demo>
|
10 |
+
<demo name="bubble_list" title="Bubble List"></demo>
|
11 |
+
<demo name="custom_list_content" title="Custom List Content"></demo>
|
12 |
+
<demo name="chatbot" title="Chatbot" position="bottom" collapsible="true"></demo>
|
components/antdx/bubble/README.md
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Bubble
|
2 |
+
|
3 |
+
A bubble component for chat. See [Ant Design X](https://x.ant.design/components/bubble/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic" position="bottom" collapsible="true"></demo>
|
8 |
+
<demo name="typing_effect" title="Typing Effect"></demo>
|
9 |
+
<demo name="variant" title="Variant"></demo>
|
10 |
+
<demo name="bubble_list" title="Bubble List"></demo>
|
11 |
+
<demo name="custom_list_content" title="Custom List Content"></demo>
|
12 |
+
<demo name="chatbot" title="Chatbot" position="bottom" collapsible="true"></demo>
|
components/antdx/bubble/app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helper.Docs import Docs
|
2 |
+
|
3 |
+
docs = Docs(__file__)
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
docs.render().queue().launch()
|
components/antdx/bubble/demos/basic.py
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
fooAvatar = {
|
7 |
+
"color": '#f56a00',
|
8 |
+
"backgroundColor": '#fde3cf',
|
9 |
+
}
|
10 |
+
|
11 |
+
barAvatar = {
|
12 |
+
"color": '#fff',
|
13 |
+
"backgroundColor": '#87d068',
|
14 |
+
}
|
15 |
+
|
16 |
+
hideAvatar = {
|
17 |
+
"visibility": 'hidden',
|
18 |
+
}
|
19 |
+
|
20 |
+
with gr.Blocks() as demo:
|
21 |
+
with ms.Application():
|
22 |
+
with antdx.XProvider():
|
23 |
+
|
24 |
+
antdx.Bubble("Hello World!")
|
25 |
+
|
26 |
+
antd.Divider("Placement and avatar")
|
27 |
+
with antd.Flex(gap="middle", vertical=True):
|
28 |
+
with antdx.Bubble(placement="start",
|
29 |
+
content="Good morning, how are you?"):
|
30 |
+
with ms.Slot("avatar"):
|
31 |
+
with antd.Avatar(elem_style=fooAvatar):
|
32 |
+
with ms.Slot("icon"):
|
33 |
+
antd.Icon("UserOutlined")
|
34 |
+
antdx.Bubble(placement="start",
|
35 |
+
content="What a beautiful day!",
|
36 |
+
avatar=dict(),
|
37 |
+
styles={"avatar": hideAvatar})
|
38 |
+
with antdx.Bubble(placement="end",
|
39 |
+
content="Hi, good morning, I'm fine!"):
|
40 |
+
with ms.Slot("avatar"):
|
41 |
+
with antd.Avatar(elem_style=barAvatar):
|
42 |
+
with ms.Slot("icon"):
|
43 |
+
antd.Icon("UserOutlined")
|
44 |
+
antdx.Bubble(placement="end",
|
45 |
+
content="Thank you!",
|
46 |
+
avatar=dict(),
|
47 |
+
styles={"avatar": hideAvatar})
|
48 |
+
|
49 |
+
antd.Divider("Header and footer")
|
50 |
+
|
51 |
+
with antdx.Bubble(
|
52 |
+
"Hello, welcome to use Ant Design X! Just ask if you have any questions.",
|
53 |
+
header="Ant Design X"):
|
54 |
+
with ms.Slot("avatar.icon"):
|
55 |
+
antd.Icon("UserOutlined")
|
56 |
+
with ms.Slot("footer"):
|
57 |
+
with antd.Space(size="small"):
|
58 |
+
with antd.Button(value=None,
|
59 |
+
color="default",
|
60 |
+
variant="text",
|
61 |
+
size="small"):
|
62 |
+
with ms.Slot("icon"):
|
63 |
+
antd.Icon("SyncOutlined")
|
64 |
+
with antd.Button(value=None,
|
65 |
+
color="default",
|
66 |
+
variant="text",
|
67 |
+
size="small"):
|
68 |
+
with ms.Slot("icon"):
|
69 |
+
antd.Icon("CopyOutlined")
|
70 |
+
|
71 |
+
antd.Divider("Loading")
|
72 |
+
with antd.Space():
|
73 |
+
ms.Span("Loading State")
|
74 |
+
loading_switch = antd.Switch(value=False)
|
75 |
+
with antdx.Bubble("hello world !") as loading_bubble:
|
76 |
+
with ms.Slot("avatar.icon"):
|
77 |
+
antd.Icon("UserOutlined")
|
78 |
+
|
79 |
+
loading_switch.change(fn=lambda x: gr.update(loading=x),
|
80 |
+
inputs=[loading_switch],
|
81 |
+
outputs=[loading_bubble])
|
82 |
+
antd.Divider("Markdown")
|
83 |
+
with antdx.Bubble():
|
84 |
+
with ms.Slot("avatar.icon"):
|
85 |
+
antd.Icon("UserOutlined")
|
86 |
+
with ms.Slot("content"):
|
87 |
+
ms.Markdown("Hello `Markdown`!")
|
88 |
+
|
89 |
+
if __name__ == "__main__":
|
90 |
+
demo.queue().launch()
|
components/antdx/bubble/demos/bubble_list.py
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
|
7 |
+
def get_bubble_items(count):
|
8 |
+
result = []
|
9 |
+
for i in range(count):
|
10 |
+
is_ai = i % 2 != 0
|
11 |
+
content = 'Mock AI content. ' * 20 if is_ai else f'Mock User content `{i}`.'
|
12 |
+
result.append({
|
13 |
+
"role": "ai" if is_ai else "user",
|
14 |
+
"content": content,
|
15 |
+
"key": i - 1
|
16 |
+
})
|
17 |
+
return result
|
18 |
+
|
19 |
+
|
20 |
+
def add_bubble(state_value):
|
21 |
+
state_value["history_count"] = state_value["history_count"] + 1
|
22 |
+
return gr.update(value=state_value), gr.update(
|
23 |
+
items=get_bubble_items(state_value["history_count"]))
|
24 |
+
|
25 |
+
|
26 |
+
with gr.Blocks() as demo:
|
27 |
+
|
28 |
+
with ms.Application():
|
29 |
+
state = gr.State({"history_count": 3})
|
30 |
+
with antdx.XProvider():
|
31 |
+
antd.Typography.Paragraph(
|
32 |
+
"Preset Bubble list. Support auto scroll. Use roles to set default properties of Bubble."
|
33 |
+
)
|
34 |
+
with antd.Flex(gap="small", vertical=True):
|
35 |
+
with antd.Flex(gap="small",
|
36 |
+
elem_style=dict(alignSelf="flex-end")):
|
37 |
+
add_bubble_btn = antd.Button("Add Bubble")
|
38 |
+
scroll_btn = antd.Button("Scroll To First")
|
39 |
+
with antdx.Bubble.List(items=get_bubble_items(3),
|
40 |
+
elem_style=dict(maxHeight=300),
|
41 |
+
elem_id="bubble-list") as bubble_list:
|
42 |
+
# Define Roles
|
43 |
+
with ms.Slot("roles"):
|
44 |
+
with antdx.Bubble.List.Role(
|
45 |
+
role="ai",
|
46 |
+
placement="start",
|
47 |
+
typing=dict(step=5, interval=20),
|
48 |
+
elem_style=dict(maxWidth=600)):
|
49 |
+
with ms.Slot("avatar"):
|
50 |
+
with antd.Avatar(elem_style=dict(
|
51 |
+
backgroundColor="#fde3cf")):
|
52 |
+
with ms.Slot("icon"):
|
53 |
+
antd.Icon("UserOutlined")
|
54 |
+
# use messageRender to render markdown content
|
55 |
+
with ms.Slot(
|
56 |
+
"messageRender",
|
57 |
+
params_mapping="""content => content"""):
|
58 |
+
ms.Markdown()
|
59 |
+
|
60 |
+
with antdx.Bubble.List.Role(
|
61 |
+
role="user",
|
62 |
+
placement="end",
|
63 |
+
):
|
64 |
+
with ms.Slot("avatar"):
|
65 |
+
with antd.Avatar(elem_style=dict(
|
66 |
+
backgroundColor="#87d068")):
|
67 |
+
with ms.Slot("icon"):
|
68 |
+
antd.Icon("UserOutlined")
|
69 |
+
with ms.Slot(
|
70 |
+
"messageRender",
|
71 |
+
params_mapping="(content) => content"):
|
72 |
+
ms.Markdown()
|
73 |
+
add_bubble_btn.click(fn=add_bubble,
|
74 |
+
inputs=[state],
|
75 |
+
outputs=[state, bubble_list])
|
76 |
+
scroll_btn.click(fn=None,
|
77 |
+
js="""() => {
|
78 |
+
const bubbleList = document.getElementById("bubble-list");
|
79 |
+
bubbleList.scrollTo({ top:0, behavior:'smooth' });
|
80 |
+
}""")
|
81 |
+
|
82 |
+
if __name__ == "__main__":
|
83 |
+
demo.queue().launch()
|
components/antdx/bubble/demos/chatbot.py
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
|
7 |
+
def create_bubble_item(i: int):
|
8 |
+
is_ai = i % 2 != 0
|
9 |
+
content = 'Mock AI content. ' * 20 if is_ai else f'Mock User content `{i}`.'
|
10 |
+
return {
|
11 |
+
"role": "ai" if is_ai else "user",
|
12 |
+
"content": content,
|
13 |
+
"key": i - 1
|
14 |
+
}
|
15 |
+
|
16 |
+
|
17 |
+
def add_bubble(state_value):
|
18 |
+
history_len = len(state_value["history"])
|
19 |
+
state_value["history"].append(create_bubble_item(history_len + 1))
|
20 |
+
return gr.update(value=state_value), gr.update(
|
21 |
+
items=state_value["history"])
|
22 |
+
|
23 |
+
|
24 |
+
def refresh(state_value, e: gr.EventData):
|
25 |
+
clicked_key = e._data["component"]["key"]
|
26 |
+
gr.Info(f"You clicked refresh button, item {clicked_key}")
|
27 |
+
state_value["history"][clicked_key]["content"] = "Refreshed"
|
28 |
+
return gr.update(value=state_value), gr.update(
|
29 |
+
items=state_value["history"])
|
30 |
+
|
31 |
+
|
32 |
+
def like(state_value, e: gr.EventData):
|
33 |
+
clicked_key = e._data["component"]["key"]
|
34 |
+
gr.Info(f"You clicked like button, item {clicked_key}")
|
35 |
+
state_value["history"][clicked_key]["meta"] = {
|
36 |
+
"action": "like",
|
37 |
+
}
|
38 |
+
return gr.update(value=state_value), gr.update(
|
39 |
+
items=state_value["history"])
|
40 |
+
|
41 |
+
|
42 |
+
def dislike(state_value, e: gr.EventData):
|
43 |
+
clicked_key = e._data["component"]["key"]
|
44 |
+
gr.Info(f"You clicked dislike button, item {clicked_key}")
|
45 |
+
state_value["history"][clicked_key]["meta"] = {
|
46 |
+
"action": "dislike",
|
47 |
+
}
|
48 |
+
return gr.update(value=state_value), gr.update(
|
49 |
+
items=state_value["history"])
|
50 |
+
|
51 |
+
|
52 |
+
default_history = [
|
53 |
+
create_bubble_item(1),
|
54 |
+
create_bubble_item(2),
|
55 |
+
create_bubble_item(3)
|
56 |
+
]
|
57 |
+
|
58 |
+
with gr.Blocks() as demo:
|
59 |
+
|
60 |
+
with ms.Application():
|
61 |
+
state = gr.State({"history": default_history})
|
62 |
+
with antdx.XProvider():
|
63 |
+
with antd.Flex(gap="small", vertical=True):
|
64 |
+
with antd.Flex(gap="small",
|
65 |
+
elem_style=dict(alignSelf="flex-end")):
|
66 |
+
add_bubble_btn = antd.Button("Add Bubble")
|
67 |
+
scroll_btn = antd.Button("Scroll To First")
|
68 |
+
with antdx.Bubble.List(items=default_history,
|
69 |
+
elem_style=dict(maxHeight=500),
|
70 |
+
elem_id="bubble-list") as bubble_list:
|
71 |
+
# Define Roles
|
72 |
+
with ms.Slot("roles"):
|
73 |
+
with antdx.Bubble.List.Role(
|
74 |
+
role="ai",
|
75 |
+
placement="start",
|
76 |
+
typing=dict(step=5, interval=20),
|
77 |
+
styles=dict(footer=dict(width="100%")),
|
78 |
+
elem_style=dict(maxWidth=600)):
|
79 |
+
with ms.Slot("avatar"):
|
80 |
+
with antd.Avatar(elem_style=dict(
|
81 |
+
backgroundColor="#fde3cf")):
|
82 |
+
with ms.Slot("icon"):
|
83 |
+
antd.Icon("UserOutlined")
|
84 |
+
# use messageRender to render markdown content
|
85 |
+
with ms.Slot(
|
86 |
+
"messageRender",
|
87 |
+
params_mapping="""content => content"""):
|
88 |
+
ms.Markdown()
|
89 |
+
|
90 |
+
# render footer
|
91 |
+
with ms.Slot("footer",
|
92 |
+
params_mapping="""(item) => {
|
93 |
+
return { refresh: { key: item.key }, like: { key: item.key, color: item.meta?.action === "like" ? 'primary' : 'default' }, dislike: { key: item.key, color: item.meta?.action === "dislike" ? 'primary' : 'default' } }
|
94 |
+
}"""):
|
95 |
+
with antd.Button(
|
96 |
+
value=None,
|
97 |
+
size="small",
|
98 |
+
color="default",
|
99 |
+
variant="text",
|
100 |
+
as_item="refresh") as refresh_btn:
|
101 |
+
with ms.Slot("icon"):
|
102 |
+
antd.Icon("SyncOutlined")
|
103 |
+
refresh_btn.click(fn=refresh,
|
104 |
+
inputs=[state],
|
105 |
+
outputs=[state, bubble_list])
|
106 |
+
with antd.Button(value=None,
|
107 |
+
size="small",
|
108 |
+
variant="text",
|
109 |
+
as_item="like") as like_btn:
|
110 |
+
with ms.Slot("icon"):
|
111 |
+
antd.Icon("SmileOutlined")
|
112 |
+
like_btn.click(fn=like,
|
113 |
+
inputs=[state],
|
114 |
+
outputs=[state, bubble_list])
|
115 |
+
with antd.Button(
|
116 |
+
value=None,
|
117 |
+
size="small",
|
118 |
+
variant="text",
|
119 |
+
as_item="dislike") as dislike_btn:
|
120 |
+
with ms.Slot("icon"):
|
121 |
+
antd.Icon("FrownOutlined")
|
122 |
+
dislike_btn.click(fn=dislike,
|
123 |
+
inputs=[state],
|
124 |
+
outputs=[state, bubble_list])
|
125 |
+
|
126 |
+
with antdx.Bubble.List.Role(
|
127 |
+
role="user",
|
128 |
+
placement="end",
|
129 |
+
):
|
130 |
+
with ms.Slot("avatar"):
|
131 |
+
with antd.Avatar(elem_style=dict(
|
132 |
+
backgroundColor="#87d068")):
|
133 |
+
with ms.Slot("icon"):
|
134 |
+
antd.Icon("UserOutlined")
|
135 |
+
with ms.Slot(
|
136 |
+
"messageRender",
|
137 |
+
params_mapping="(content) => content"):
|
138 |
+
ms.Markdown()
|
139 |
+
add_bubble_btn.click(fn=add_bubble,
|
140 |
+
inputs=[state],
|
141 |
+
outputs=[state, bubble_list])
|
142 |
+
scroll_btn.click(fn=None,
|
143 |
+
js="""() => {
|
144 |
+
const bubbleList = document.getElementById("bubble-list");
|
145 |
+
bubbleList.scrollTo({ top:0, behavior:'smooth' });
|
146 |
+
}""")
|
147 |
+
|
148 |
+
if __name__ == "__main__":
|
149 |
+
demo.queue().launch()
|
components/antdx/bubble/demos/custom_list_content.py
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
items = [
|
7 |
+
{
|
8 |
+
"key": '1',
|
9 |
+
"role": "ai-markdown",
|
10 |
+
"content": "`Hello, world!`"
|
11 |
+
},
|
12 |
+
{
|
13 |
+
"key": '2',
|
14 |
+
"role": "ai-error-message",
|
15 |
+
"content": "Error message"
|
16 |
+
},
|
17 |
+
{
|
18 |
+
"key":
|
19 |
+
'3',
|
20 |
+
"role":
|
21 |
+
'ai-suggestion',
|
22 |
+
"content": [
|
23 |
+
{
|
24 |
+
"key": '1',
|
25 |
+
"description":
|
26 |
+
'How to rest effectively after long hours of work?',
|
27 |
+
},
|
28 |
+
{
|
29 |
+
"key":
|
30 |
+
'2',
|
31 |
+
"description":
|
32 |
+
'What are the secrets to maintaining a positive mindset?',
|
33 |
+
},
|
34 |
+
{
|
35 |
+
"key": '3',
|
36 |
+
"description": 'How to stay calm under immense pressure?',
|
37 |
+
},
|
38 |
+
],
|
39 |
+
},
|
40 |
+
{
|
41 |
+
"key":
|
42 |
+
'4',
|
43 |
+
"role":
|
44 |
+
'ai-file',
|
45 |
+
"content": [
|
46 |
+
{
|
47 |
+
"uid": '1',
|
48 |
+
"name": 'excel-file.xlsx',
|
49 |
+
"size": 111111,
|
50 |
+
"description": 'Checking the data',
|
51 |
+
},
|
52 |
+
{
|
53 |
+
"uid": '2',
|
54 |
+
"name": 'word-file.docx',
|
55 |
+
"size": 222222,
|
56 |
+
"status": 'uploading',
|
57 |
+
"percent": 23,
|
58 |
+
},
|
59 |
+
],
|
60 |
+
},
|
61 |
+
]
|
62 |
+
|
63 |
+
with gr.Blocks() as demo:
|
64 |
+
|
65 |
+
with ms.Application():
|
66 |
+
with antdx.XProvider():
|
67 |
+
antd.Typography.Paragraph(
|
68 |
+
"Customize the content of the bubble list, which is very useful for personalized customization scenarios."
|
69 |
+
)
|
70 |
+
with antdx.Bubble.List(items=items) as bubble_list:
|
71 |
+
# Define Roles
|
72 |
+
with ms.Slot("roles"):
|
73 |
+
with antdx.Bubble.List.Role(role="ai-markdown",
|
74 |
+
placement="start"):
|
75 |
+
with ms.Slot("avatar"):
|
76 |
+
with antd.Avatar(elem_style=dict(
|
77 |
+
backgroundColor="#fde3cf")):
|
78 |
+
with ms.Slot("icon"):
|
79 |
+
antd.Icon("UserOutlined")
|
80 |
+
with ms.Slot("messageRender",
|
81 |
+
params_mapping="(content) => content"):
|
82 |
+
ms.Markdown()
|
83 |
+
with antdx.Bubble.List.Role(role="ai-error-message",
|
84 |
+
placement="start"):
|
85 |
+
with ms.Slot("avatar"):
|
86 |
+
with antd.Avatar(elem_style=dict(
|
87 |
+
backgroundColor="#fde3cf")):
|
88 |
+
with ms.Slot("icon"):
|
89 |
+
antd.Icon("UserOutlined")
|
90 |
+
with ms.Slot("messageRender",
|
91 |
+
params_mapping="(content) => content"):
|
92 |
+
antd.Typography.Text(type="danger")
|
93 |
+
with antdx.Bubble.List.Role(
|
94 |
+
role="ai-suggestion",
|
95 |
+
placement="start",
|
96 |
+
variant="borderless",
|
97 |
+
avatar=dict(style=dict(visibility='hidden'))):
|
98 |
+
with ms.Slot("messageRender",
|
99 |
+
params_mapping="(items) => ({ items })"):
|
100 |
+
prompts = antdx.Prompts(vertical=True)
|
101 |
+
|
102 |
+
with antdx.Bubble.List.Role(
|
103 |
+
role="ai-file",
|
104 |
+
placement="start",
|
105 |
+
variant="borderless",
|
106 |
+
avatar=dict(style=dict(visibility='hidden'))):
|
107 |
+
with ms.Slot("messageRender",
|
108 |
+
params_mapping="""(content) => {
|
109 |
+
return {
|
110 |
+
each: content?.map(item => ({ item }))
|
111 |
+
}
|
112 |
+
}"""):
|
113 |
+
with antd.Flex(vertical=True, gap="middle"):
|
114 |
+
with ms.Each(as_item="each"):
|
115 |
+
antdx.Attachments.FileCard()
|
116 |
+
|
117 |
+
if __name__ == "__main__":
|
118 |
+
demo.queue().launch()
|
components/antdx/bubble/demos/typing_effect.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
text = "Ant Design X love you! "
|
7 |
+
|
8 |
+
|
9 |
+
def repeat(state_value):
|
10 |
+
if state_value["repeat"] < 5:
|
11 |
+
state_value["repeat"] = state_value["repeat"] + 1
|
12 |
+
else:
|
13 |
+
state_value["repeat"] = 1
|
14 |
+
return gr.update(value=state_value), gr.update(
|
15 |
+
value=f"Repeat {state_value["repeat"]} Times"), gr.update(
|
16 |
+
content=text * state_value["repeat"]), gr.update(content=text * state_value["repeat"])
|
17 |
+
|
18 |
+
|
19 |
+
with gr.Blocks() as demo:
|
20 |
+
state = gr.State({"repeat": 1})
|
21 |
+
with ms.Application():
|
22 |
+
with antdx.XProvider():
|
23 |
+
antd.Typography.Paragraph("Enable typing output by setting the typing prop. If the updated content is a subset of the previous content, it will continue to output, otherwise it will output again.")
|
24 |
+
with antd.Flex(vertical=True, gap="small"):
|
25 |
+
with antdx.Bubble(content=text,
|
26 |
+
typing=dict(step=2, interval=50)) as bubble1:
|
27 |
+
with ms.Slot("avatar.icon"):
|
28 |
+
antd.Icon("UserOutlined")
|
29 |
+
with antdx.Bubble(content=text,
|
30 |
+
typing=dict(step=2, interval=50,
|
31 |
+
suffix="💗")) as bubble2:
|
32 |
+
with ms.Slot("avatar.icon"):
|
33 |
+
antd.Icon("UserOutlined")
|
34 |
+
btn = antd.Button("Repeat 1 Times",
|
35 |
+
elem_style=dict(alignSelf="flex-end"))
|
36 |
+
btn.click(fn=repeat,
|
37 |
+
inputs=[state],
|
38 |
+
outputs=[state, btn, bubble1, bubble2])
|
39 |
+
|
40 |
+
if __name__ == "__main__":
|
41 |
+
demo.queue().launch()
|
components/antdx/bubble/demos/variant.py
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
with gr.Blocks() as demo:
|
7 |
+
with ms.Application():
|
8 |
+
with antdx.XProvider():
|
9 |
+
antd.Typography.Paragraph(
|
10 |
+
"Set the style variant of the bubble through the variant property."
|
11 |
+
)
|
12 |
+
with antd.Flex(vertical=True, gap="middle"):
|
13 |
+
with antdx.Bubble(variant="filled", content="variant: filled"):
|
14 |
+
with ms.Slot("avatar.icon"):
|
15 |
+
antd.Icon("UserOutlined")
|
16 |
+
with antdx.Bubble(variant="outlined",
|
17 |
+
content="variant: outlined"):
|
18 |
+
with ms.Slot("avatar.icon"):
|
19 |
+
antd.Icon("UserOutlined")
|
20 |
+
with antdx.Bubble(variant="shadow", content="variant: shadow"):
|
21 |
+
with ms.Slot("avatar.icon"):
|
22 |
+
antd.Icon("UserOutlined")
|
23 |
+
with antdx.Bubble(variant="borderless"):
|
24 |
+
with ms.Slot("avatar.icon"):
|
25 |
+
antd.Icon("UserOutlined")
|
26 |
+
with ms.Slot("content"):
|
27 |
+
with antdx.Prompts(
|
28 |
+
vertical=True,
|
29 |
+
title="variant: borderless to customize"):
|
30 |
+
with antdx.Prompts.Item(
|
31 |
+
key='1',
|
32 |
+
description=
|
33 |
+
'How to rest effectively after long hours of work?'
|
34 |
+
):
|
35 |
+
with ms.Slot("icon"):
|
36 |
+
antd.Icon("CoffeeOutlined",
|
37 |
+
elem_style={"color": '#964B00'})
|
38 |
+
with antdx.Prompts.Item(
|
39 |
+
key='2',
|
40 |
+
description=
|
41 |
+
'What are the secrets to maintaining a positive mindset?',
|
42 |
+
):
|
43 |
+
with ms.Slot("icon"):
|
44 |
+
antd.Icon("SmileOutlined",
|
45 |
+
elem_style={"color": '#FAAD14'})
|
46 |
+
with antdx.Prompts.Item(
|
47 |
+
key='3',
|
48 |
+
description=
|
49 |
+
'How to stay calm under immense pressure?',
|
50 |
+
):
|
51 |
+
with ms.Slot("icon"):
|
52 |
+
antd.Icon("FireOutlined",
|
53 |
+
elem_style={"color": '#FF4D4F'})
|
54 |
+
|
55 |
+
if __name__ == "__main__":
|
56 |
+
demo.queue().launch()
|
components/antdx/conversations/README-zh_CN.md
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Conversations
|
2 |
+
|
3 |
+
Used to manage and view the conversation list. See [Ant Design X](https://x.ant.design/components/conversations/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic"></demo>
|
8 |
+
<demo name="operations" title="Operations"></demo>
|
9 |
+
<demo name="group" title="Group"></demo>
|
components/antdx/conversations/README.md
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Conversations
|
2 |
+
|
3 |
+
Used to manage and view the conversation list. See [Ant Design X](https://x.ant.design/components/conversations/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic"></demo>
|
8 |
+
<demo name="operations" title="Operations"></demo>
|
9 |
+
<demo name="group" title="Group"></demo>
|
components/antdx/conversations/app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helper.Docs import Docs
|
2 |
+
|
3 |
+
docs = Docs(__file__)
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
docs.render().queue().launch()
|
components/antdx/conversations/demos/basic.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
|
7 |
+
def active_change(e: gr.EventData):
|
8 |
+
print(e._data["payload"])
|
9 |
+
|
10 |
+
|
11 |
+
with gr.Blocks() as demo:
|
12 |
+
with ms.Application():
|
13 |
+
with antdx.XProvider():
|
14 |
+
conversations1 = antdx.Conversations(default_active_key="item1",
|
15 |
+
items=[{
|
16 |
+
"key": "item1",
|
17 |
+
"label": "Item1"
|
18 |
+
}, {
|
19 |
+
"key": "item2",
|
20 |
+
"label": "Item2",
|
21 |
+
}, {
|
22 |
+
"key": "item3",
|
23 |
+
"label": "Item3",
|
24 |
+
}, {
|
25 |
+
"key": "item4",
|
26 |
+
"label": "Item4",
|
27 |
+
"disabled": True
|
28 |
+
}])
|
29 |
+
|
30 |
+
antd.Divider("Customized Item")
|
31 |
+
|
32 |
+
with antdx.Conversations(
|
33 |
+
default_active_key="item1") as conversations2:
|
34 |
+
with antdx.Conversations.Item(key="item1"):
|
35 |
+
with ms.Slot("label"):
|
36 |
+
antd.Typography.Text("Item1", type="success")
|
37 |
+
with ms.Slot("icon"):
|
38 |
+
antd.Icon()
|
39 |
+
|
40 |
+
with antdx.Conversations.Item(key="item2"):
|
41 |
+
with ms.Slot("label"):
|
42 |
+
antd.Typography.Text("Item2", type="success")
|
43 |
+
with ms.Slot("icon"):
|
44 |
+
antd.Icon()
|
45 |
+
conversations1.active_change(fn=active_change)
|
46 |
+
conversations2.active_change(fn=active_change)
|
47 |
+
|
48 |
+
if __name__ == "__main__":
|
49 |
+
demo.queue().launch()
|
components/antdx/conversations/demos/group.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antdx as antdx
|
3 |
+
import modelscope_studio.components.base as ms
|
4 |
+
|
5 |
+
with gr.Blocks() as demo:
|
6 |
+
with ms.Application():
|
7 |
+
with antdx.XProvider():
|
8 |
+
conversations1 = antdx.Conversations(default_active_key="item1",
|
9 |
+
groupable=True,
|
10 |
+
items=[{
|
11 |
+
"key": "item1",
|
12 |
+
"label": "Item1",
|
13 |
+
"group": "Group1"
|
14 |
+
}, {
|
15 |
+
"key": "item2",
|
16 |
+
"label": "Item2",
|
17 |
+
"group": "Group1"
|
18 |
+
}, {
|
19 |
+
"key": "item3",
|
20 |
+
"label": "Item3",
|
21 |
+
"group": "Group2"
|
22 |
+
}, {
|
23 |
+
"key": "item4",
|
24 |
+
"label": "Item4",
|
25 |
+
"group": "Group2",
|
26 |
+
"disabled": True
|
27 |
+
}])
|
28 |
+
|
29 |
+
if __name__ == "__main__":
|
30 |
+
demo.queue().launch()
|
components/antdx/conversations/demos/operations.py
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
|
7 |
+
def menu_click(e: gr.EventData):
|
8 |
+
print(e._data["payload"])
|
9 |
+
|
10 |
+
|
11 |
+
with gr.Blocks() as demo:
|
12 |
+
with ms.Application():
|
13 |
+
with antdx.XProvider():
|
14 |
+
with antdx.Conversations(default_active_key="item1",
|
15 |
+
items=[{
|
16 |
+
"key": "item1",
|
17 |
+
"label": "Item1"
|
18 |
+
}, {
|
19 |
+
"key": "item2",
|
20 |
+
"label": "Item2",
|
21 |
+
}, {
|
22 |
+
"key": "item3",
|
23 |
+
"label": "Item3",
|
24 |
+
}, {
|
25 |
+
"key": "item4",
|
26 |
+
"label": "Item4",
|
27 |
+
"disabled": True
|
28 |
+
}]) as conversations:
|
29 |
+
with ms.Slot("menu.items"):
|
30 |
+
with antd.Menu.Item(label="Operation 1", key="o1"):
|
31 |
+
with ms.Slot("icon"):
|
32 |
+
antd.Icon("EditOutlined")
|
33 |
+
with antd.Menu.Item(label="Operation 2",
|
34 |
+
key="o2",
|
35 |
+
disabled=True):
|
36 |
+
with ms.Slot("icon"):
|
37 |
+
antd.Icon("StopOutlined")
|
38 |
+
with antd.Menu.Item(label="Operation 3",
|
39 |
+
key="o3",
|
40 |
+
danger=True):
|
41 |
+
with ms.Slot("icon"):
|
42 |
+
antd.Icon("DeleteOutlined")
|
43 |
+
conversations.menu_click(fn=menu_click)
|
44 |
+
|
45 |
+
if __name__ == "__main__":
|
46 |
+
demo.queue().launch()
|
components/antdx/overview/README-zh_CN.md
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 概览
|
2 |
+
|
3 |
+
`modelscope_studio`集成了 [Ant Design X](https://x.ant.design/) 的组件,并支持大部分的组件属性,您只需要引入`antdx`模块即可直接使用。
|
4 |
+
|
5 |
+
```python
|
6 |
+
import modelscope_studio.components.antdx as antdx
|
7 |
+
```
|
8 |
+
|
9 |
+
## 快速开始
|
10 |
+
|
11 |
+
<demo name="quick_start"></demo>
|
12 |
+
|
13 |
+
注意:其中`ms.Application`与`antdx.XProvider`(或者`antd.ConfigProvider`)是必须的。
|
14 |
+
|
15 |
+
- `Application` 包含了`modelscope_studio`中所有的组件依赖,请确保`modelscope_studio`所有导出的组件都被其包裹,否则页面将会无法成功预览。
|
16 |
+
- `XProvider`(`ConfigProvider`) 与 Ant Design X(Ant Design)中的功能一致,除此之外,我们还加了一些额外的适配来兼容 Gradio 的样式。因此,为了保证页面样式正常,所有的`antdx`组件需要包裹在该组件下。
|
17 |
+
|
18 |
+
## 其他
|
19 |
+
|
20 |
+
同`Antd`组件。
|
components/antdx/overview/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Overview
|
2 |
+
|
3 |
+
`modelscope_studio` integrates [Ant Design X](https://x.ant.design/) components and supports most component properties. You can use them directly by importing the `antdx` module.
|
4 |
+
|
5 |
+
```python
|
6 |
+
import modelscope_studio.components.antdx as antdx
|
7 |
+
```
|
8 |
+
|
9 |
+
## Quick Start
|
10 |
+
|
11 |
+
<demo name="quick_start"></demo>
|
12 |
+
|
13 |
+
Note: Both `ms.Application` and `antdx.XProvider`(or `antd.ConfigProvider`) are required.
|
14 |
+
|
15 |
+
- `Application` contains all component dependencies in `modelscope_studio`. Please ensure that all components exported from `modelscope_studio` are wrapped by it, otherwise the page will not be successfully previewed.
|
16 |
+
- `XProvider`(`ConfigProvider`) functions the same as in Ant Design X(Ant Design). Additionally, we have added some extra adaptations to be compatible with Gradio's styles. Therefore, to ensure normal page styling, all `antdx` components need to be wrapped within this component.
|
17 |
+
|
18 |
+
## Others
|
19 |
+
|
20 |
+
Same as `Antd` components.
|
components/antdx/overview/app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helper.Docs import Docs
|
2 |
+
|
3 |
+
docs = Docs(__file__)
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
docs.render().queue().launch()
|
components/antdx/overview/demos/quick_start.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antdx as antdx
|
3 |
+
import modelscope_studio.components.base as ms
|
4 |
+
|
5 |
+
with gr.Blocks() as demo:
|
6 |
+
with ms.Application():
|
7 |
+
with antdx.XProvider(): # or antd.ConfigProvider
|
8 |
+
antdx.Welcome(
|
9 |
+
icon=
|
10 |
+
"https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp",
|
11 |
+
title="Hello, I'm Ant Design X",
|
12 |
+
description=
|
13 |
+
"Base on Ant Design, AGI product interface solution, create a better intelligent vision~"
|
14 |
+
)
|
15 |
+
|
16 |
+
if __name__ == "__main__":
|
17 |
+
demo.queue().launch()
|
components/antdx/prompts/README-zh_CN.md
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Prompts
|
2 |
+
|
3 |
+
Display a predefined set of questions or suggestion. See [Ant Design X](https://x.ant.design/components/prompts/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic"></demo>
|
8 |
+
<demo name="nest_usage" title="Nest Usage"></demo>
|
components/antdx/prompts/README.md
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Prompts
|
2 |
+
|
3 |
+
Display a predefined set of questions or suggestion. See [Ant Design X](https://x.ant.design/components/prompts/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic"></demo>
|
8 |
+
<demo name="nest_usage" title="Nest Usage"></demo>
|
components/antdx/prompts/app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helper.Docs import Docs
|
2 |
+
|
3 |
+
docs = Docs(__file__)
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
docs.render().queue().launch()
|
components/antdx/prompts/demos/basic.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
|
7 |
+
def item_click(e: gr.EventData):
|
8 |
+
payload = e._data["payload"]
|
9 |
+
gr.Info("You clicked on item " + payload[0]["data"]["key"])
|
10 |
+
|
11 |
+
|
12 |
+
default_vertical = False
|
13 |
+
default_wrap = False
|
14 |
+
|
15 |
+
with gr.Blocks() as demo:
|
16 |
+
with ms.Application():
|
17 |
+
with antdx.XProvider():
|
18 |
+
vertical = antd.Switch(value=default_vertical,
|
19 |
+
checked_children="Vertical",
|
20 |
+
un_checked_children="Horizontal")
|
21 |
+
wrap = antd.Switch(value=default_wrap,
|
22 |
+
checked_children="Wrap",
|
23 |
+
un_checked_children="No Wrap")
|
24 |
+
with antdx.Prompts(
|
25 |
+
title="✨ Inspirational Sparks and Marvelous Tips",
|
26 |
+
wrap=default_wrap,
|
27 |
+
vertical=default_vertical) as prompts:
|
28 |
+
with antdx.Prompts.Item(
|
29 |
+
key='1',
|
30 |
+
label='Ignite Your Creativity',
|
31 |
+
description='Got any sparks for a new project?',
|
32 |
+
disabled=True):
|
33 |
+
with ms.Slot("icon"):
|
34 |
+
antd.Icon("BulbOutlined",
|
35 |
+
elem_style={"color": '#FFD700'})
|
36 |
+
with antdx.Prompts.Item(
|
37 |
+
key='2',
|
38 |
+
label='Uncover Background Info',
|
39 |
+
description=
|
40 |
+
'Help me understand the background of this topic.',
|
41 |
+
):
|
42 |
+
with ms.Slot("icon"):
|
43 |
+
antd.Icon("InfoCircleOutlined",
|
44 |
+
elem_style={"color": '#1890FF'})
|
45 |
+
with antdx.Prompts.Item(
|
46 |
+
key='3',
|
47 |
+
label='Efficiency Boost Battle',
|
48 |
+
description='How can I work faster and better?',
|
49 |
+
):
|
50 |
+
with ms.Slot("icon"):
|
51 |
+
antd.Icon("RocketOutlined",
|
52 |
+
elem_style={"color": '#722ED1'})
|
53 |
+
with antdx.Prompts.Item(
|
54 |
+
key='4',
|
55 |
+
label='Tell me a Joke',
|
56 |
+
description=
|
57 |
+
'Why do not ants get sick? Because they have tiny ant-bodies!',
|
58 |
+
):
|
59 |
+
with ms.Slot("icon"):
|
60 |
+
antd.Icon("SmileOutlined",
|
61 |
+
elem_style={"color": '#52C41A'})
|
62 |
+
with antdx.Prompts.Item(
|
63 |
+
key='5',
|
64 |
+
label='Common Issue Solutions',
|
65 |
+
description=
|
66 |
+
'How to solve common issues? Share some tips!',
|
67 |
+
):
|
68 |
+
with ms.Slot("icon"):
|
69 |
+
antd.Icon("WarningOutlined",
|
70 |
+
elem_style={"color": '#FF4D4F'})
|
71 |
+
|
72 |
+
prompts.item_click(fn=item_click)
|
73 |
+
vertical.change(fn=lambda x: gr.update(vertical=x),
|
74 |
+
inputs=[vertical],
|
75 |
+
outputs=[prompts])
|
76 |
+
wrap.change(fn=lambda x: gr.update(wrap=x),
|
77 |
+
inputs=[wrap],
|
78 |
+
outputs=[prompts])
|
79 |
+
|
80 |
+
if __name__ == "__main__":
|
81 |
+
demo.queue().launch()
|
components/antdx/prompts/demos/nest_usage.py
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
|
7 |
+
def item_click(e: gr.EventData):
|
8 |
+
payload = e._data["payload"]
|
9 |
+
gr.Info("You clicked on item " + payload[0]["data"]["key"])
|
10 |
+
|
11 |
+
|
12 |
+
with gr.Blocks() as demo:
|
13 |
+
with ms.Application():
|
14 |
+
with antdx.XProvider(theme=dict(algorithm=dict(dark=False))):
|
15 |
+
with antd.Card(elem_style=dict(borderRadius=0, border=0)):
|
16 |
+
with antdx.Prompts(
|
17 |
+
title="Do you want?",
|
18 |
+
wrap=True,
|
19 |
+
styles=dict(item={
|
20 |
+
"flex": 'none',
|
21 |
+
"width": 'calc(30% - 6px)',
|
22 |
+
"backgroundImage":
|
23 |
+
"linear-gradient(137deg, #e5f4ff 0%, #efe7ff 100%)",
|
24 |
+
"border": 0,
|
25 |
+
},
|
26 |
+
subItem={
|
27 |
+
"background": 'rgba(255,255,255,0.45)',
|
28 |
+
"border": '1px solid #FFF',
|
29 |
+
})) as prompts:
|
30 |
+
with antdx.Prompts.Item(
|
31 |
+
key='1',
|
32 |
+
description='What are you interested in?',
|
33 |
+
):
|
34 |
+
with ms.Slot("label"):
|
35 |
+
with antd.Space():
|
36 |
+
antd.Icon("FireOutlined",
|
37 |
+
elem_style={"color": '#FF4D4F'})
|
38 |
+
ms.Text("Hot Topics")
|
39 |
+
antdx.Prompts.Item(key="1-1",
|
40 |
+
description="What's new in X?")
|
41 |
+
antdx.Prompts.Item(key="1-2",
|
42 |
+
description="What's AGI?")
|
43 |
+
antdx.Prompts.Item(key="1-3",
|
44 |
+
description="Where is the doc?")
|
45 |
+
with antdx.Prompts.Item(
|
46 |
+
key='2',
|
47 |
+
description='How to design a good product?',
|
48 |
+
):
|
49 |
+
with ms.Slot("label"):
|
50 |
+
with antd.Space():
|
51 |
+
antd.Icon("ReadOutlined",
|
52 |
+
elem_style={"color": '#1890FF'})
|
53 |
+
ms.Text("Design Guide")
|
54 |
+
with antdx.Prompts.Item(key="2-1",
|
55 |
+
description="Know the well"):
|
56 |
+
with ms.Slot("icon"):
|
57 |
+
antd.Icon("HeartOutlined")
|
58 |
+
with antdx.Prompts.Item(key="2-2",
|
59 |
+
description="Set the AI role"):
|
60 |
+
with ms.Slot("icon"):
|
61 |
+
antd.Icon("SmileOutlined")
|
62 |
+
with antdx.Prompts.Item(
|
63 |
+
key="2-3", description="Express the feeling"):
|
64 |
+
with ms.Slot("icon"):
|
65 |
+
antd.Icon("CommentOutlined")
|
66 |
+
with antdx.Prompts.Item(
|
67 |
+
key='3',
|
68 |
+
description='How to start a new project?',
|
69 |
+
):
|
70 |
+
with ms.Slot("label"):
|
71 |
+
with antd.Space():
|
72 |
+
antd.Icon("RocketOutlined",
|
73 |
+
elem_style={"color": '#722ED1'})
|
74 |
+
ms.Text("Start Creating")
|
75 |
+
antdx.Prompts.Item(key="3-1",
|
76 |
+
label='Fast Start',
|
77 |
+
description="Install Ant Design X")
|
78 |
+
antdx.Prompts.Item(
|
79 |
+
key="3-2",
|
80 |
+
label='Online Playground',
|
81 |
+
description="Play on the web without installing")
|
82 |
+
|
83 |
+
prompts.item_click(fn=item_click)
|
84 |
+
|
85 |
+
if __name__ == "__main__":
|
86 |
+
demo.queue().launch()
|
components/antdx/welcome/README-zh_CN.md
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Welcome
|
2 |
+
|
3 |
+
Clearly convey the scope of intent and expected functionality to the user. See [Ant Design X](https://x.ant.design/components/welcome/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic"></demo>
|
components/antdx/welcome/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Welcome
|
2 |
+
|
3 |
+
Clearly convey the scope of intent and expected functionality to the user. See [Ant Design X](https://x.ant.design/components/welcome/) for more information.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="basic"></demo>
|
components/antdx/welcome/app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helper.Docs import Docs
|
2 |
+
|
3 |
+
docs = Docs(__file__)
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
docs.render().queue().launch()
|
components/antdx/welcome/demos/basic.py
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import modelscope_studio.components.antd as antd
|
3 |
+
import modelscope_studio.components.antdx as antdx
|
4 |
+
import modelscope_studio.components.base as ms
|
5 |
+
|
6 |
+
with gr.Blocks() as demo:
|
7 |
+
with ms.Application():
|
8 |
+
with antdx.XProvider():
|
9 |
+
antdx.Welcome(
|
10 |
+
icon=
|
11 |
+
"https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp",
|
12 |
+
title="Hello, I'm Ant Design X",
|
13 |
+
description=
|
14 |
+
"Base on Ant Design, AGI product interface solution, create a better intelligent vision~"
|
15 |
+
)
|
16 |
+
|
17 |
+
antd.Divider("Borderless")
|
18 |
+
|
19 |
+
with antdx.Welcome(
|
20 |
+
icon=
|
21 |
+
"https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp",
|
22 |
+
title="Hello, I'm Ant Design X",
|
23 |
+
description=
|
24 |
+
"Base on Ant Design, AGI product interface solution, create a better intelligent vision~",
|
25 |
+
variant="borderless"):
|
26 |
+
with ms.Slot("extra"):
|
27 |
+
with antd.Space():
|
28 |
+
with antd.Button(None):
|
29 |
+
with ms.Slot("icon"):
|
30 |
+
antd.Icon("ShareAltOutlined")
|
31 |
+
with antd.Button(None):
|
32 |
+
with ms.Slot("icon"):
|
33 |
+
antd.Icon("EllipsisOutlined")
|
34 |
+
|
35 |
+
if __name__ == "__main__":
|
36 |
+
demo.queue().launch()
|
helper/Docs.py
CHANGED
@@ -78,6 +78,8 @@ class Docs:
|
|
78 |
demo_name,
|
79 |
prefix='',
|
80 |
suffix='',
|
|
|
|
|
81 |
fixed=False,
|
82 |
title=''):
|
83 |
content = self._read_file(f"./demos/{demo_name}.py")
|
@@ -87,38 +89,49 @@ class Docs:
|
|
87 |
if title:
|
88 |
with ms.Slot("title"):
|
89 |
ms.Text(title)
|
90 |
-
with antd.Row(align="stretch", wrap=True, gutter=8):
|
91 |
-
with antd.Col(sm=dict(span=10,
|
|
|
92 |
xs=dict(span=24, order=2)):
|
93 |
-
|
94 |
-
|
95 |
-
with antd.
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
margin='8px 0 0'))
|
100 |
-
with antd.Col(sm=23, xs=24):
|
101 |
-
prefix = prefix + "\n" if prefix else ""
|
102 |
-
suffix = "\n" + suffix if suffix else ""
|
103 |
-
ms.Markdown(f"""{prefix}```python
|
104 |
-
{content}
|
105 |
-
```{suffix}""",
|
106 |
-
header_links=True)
|
107 |
-
|
108 |
-
with antd.Col(sm=1,
|
109 |
-
xs=0,
|
110 |
-
elem_style=dict(height="100%")):
|
111 |
-
with ms.Div(
|
112 |
-
elem_style=dict(display="flex",
|
113 |
-
justifyContent="center",
|
114 |
-
width="100%",
|
115 |
-
height="100%")):
|
116 |
-
antd.Divider(type="vertical",
|
117 |
variant="dashed",
|
118 |
-
elem_style=dict(
|
119 |
-
margin=0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
with antd.Col(
|
121 |
-
sm=dict(span=14,
|
|
|
122 |
xs=dict(span=24, order=1),
|
123 |
elem_style=dict(
|
124 |
width='100%',
|
@@ -136,9 +149,19 @@ class Docs:
|
|
136 |
self._render_demo(item["name"],
|
137 |
prefix=item["prefix"],
|
138 |
suffix=item["suffix"],
|
|
|
|
|
139 |
fixed=item["fixed"],
|
140 |
title=item["title"])
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
def render(self):
|
143 |
with gr.Blocks() as demo:
|
144 |
self._render_markdown(self.markdown_files[0])
|
|
|
78 |
demo_name,
|
79 |
prefix='',
|
80 |
suffix='',
|
81 |
+
position="left",
|
82 |
+
collapsible=False,
|
83 |
fixed=False,
|
84 |
title=''):
|
85 |
content = self._read_file(f"./demos/{demo_name}.py")
|
|
|
89 |
if title:
|
90 |
with ms.Slot("title"):
|
91 |
ms.Text(title)
|
92 |
+
with antd.Row(align="stretch", wrap=True, gutter=[8, 8]):
|
93 |
+
with antd.Col(sm=dict(span=24 if position == "bottom" else 10,
|
94 |
+
order=2 if position == "bottom" else 1),
|
95 |
xs=dict(span=24, order=2)):
|
96 |
+
|
97 |
+
def render_code():
|
98 |
+
with antd.Row(elem_style=dict(height='100%'),
|
99 |
+
gutter=[8, 8]):
|
100 |
+
with antd.Col(sm=0, xs=24):
|
101 |
+
antd.Divider(type="horizontal",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
variant="dashed",
|
103 |
+
elem_style=dict(width='100%',
|
104 |
+
margin='8px 0 0'))
|
105 |
+
with antd.Col(sm=23, xs=24):
|
106 |
+
ms.Markdown(
|
107 |
+
f"""{prefix + "\n" if prefix else ""}```python
|
108 |
+
{content}
|
109 |
+
```{"\n" + suffix if suffix else ""}""",
|
110 |
+
header_links=True)
|
111 |
+
|
112 |
+
with antd.Col(sm=1,
|
113 |
+
xs=0,
|
114 |
+
elem_style=dict(height="100%")):
|
115 |
+
with ms.Div(elem_style=dict(
|
116 |
+
display="flex",
|
117 |
+
justifyContent="center",
|
118 |
+
width="100%",
|
119 |
+
height="100%")):
|
120 |
+
antd.Divider(type="vertical",
|
121 |
+
variant="dashed",
|
122 |
+
elem_style=dict(height='100%',
|
123 |
+
margin=0))
|
124 |
+
|
125 |
+
if collapsible:
|
126 |
+
with antd.Collapse():
|
127 |
+
with antd.Collapse.Item(label="Show Code",
|
128 |
+
key="code"):
|
129 |
+
render_code()
|
130 |
+
else:
|
131 |
+
render_code()
|
132 |
with antd.Col(
|
133 |
+
sm=dict(span=24 if position == "bottom" else 14,
|
134 |
+
order=1 if position == "bottom" else 2),
|
135 |
xs=dict(span=24, order=1),
|
136 |
elem_style=dict(
|
137 |
width='100%',
|
|
|
149 |
self._render_demo(item["name"],
|
150 |
prefix=item["prefix"],
|
151 |
suffix=item["suffix"],
|
152 |
+
position=item["position"],
|
153 |
+
collapsible=item["collapsible"],
|
154 |
fixed=item["fixed"],
|
155 |
title=item["title"])
|
156 |
|
157 |
+
def get_css(self):
|
158 |
+
css = ""
|
159 |
+
for demo_name in self.demo_modules:
|
160 |
+
module = self.demo_modules[demo_name]
|
161 |
+
if hasattr(module, "css"):
|
162 |
+
css += module.css
|
163 |
+
return css
|
164 |
+
|
165 |
def render(self):
|
166 |
with gr.Blocks() as demo:
|
167 |
self._render_markdown(self.markdown_files[0])
|
helper/Site.py
CHANGED
@@ -52,7 +52,12 @@ class Site:
|
|
52 |
item: gr.update(visible=True)
|
53 |
}
|
54 |
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
56 |
.gradio-container {
|
57 |
max-width: 100% !important;
|
58 |
padding: 0 !important;
|
|
|
52 |
item: gr.update(visible=True)
|
53 |
}
|
54 |
|
55 |
+
# Css is not working in demo if there are multiple Blocks, so we need to add css from demos
|
56 |
+
css = ""
|
57 |
+
for category in self.docs:
|
58 |
+
for component in self.docs[category]:
|
59 |
+
css += self.docs[category][component].get_css()
|
60 |
+
with gr.Blocks(css=css + """
|
61 |
.gradio-container {
|
62 |
max-width: 100% !important;
|
63 |
padding: 0 !important;
|
helper/parse_markdown.py
CHANGED
@@ -47,6 +47,8 @@ class MarkdownParser(HTMLParser):
|
|
47 |
"fixed": "fixed" in dict(attrs),
|
48 |
"prefix": "",
|
49 |
"suffix": "",
|
|
|
|
|
50 |
"title": dict(attrs).get("title", "")
|
51 |
})
|
52 |
elif tag == "file":
|
|
|
47 |
"fixed": "fixed" in dict(attrs),
|
48 |
"prefix": "",
|
49 |
"suffix": "",
|
50 |
+
"position": dict(attrs).get("position", "left"),
|
51 |
+
"collapsible": "collapsible" in dict(attrs),
|
52 |
"title": dict(attrs).get("title", "")
|
53 |
})
|
54 |
elif tag == "file":
|
layout_templates/coder_artifacts/README-zh_CN.md
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Coder Artifacts
|
2 |
+
|
3 |
+
用于构建代码生成界面的应用模板。
|
4 |
+
|
5 |
+
## 示例
|
6 |
+
|
7 |
+
<demo name="app" position="bottom" collapsible="true"></demo>
|
layout_templates/coder_artifacts/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Coder Artifacts
|
2 |
+
|
3 |
+
Application template for building code generation interfaces.
|
4 |
+
|
5 |
+
## Examples
|
6 |
+
|
7 |
+
<demo name="app" position="bottom" collapsible="true"></demo>
|
layout_templates/coder_artifacts/app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helper.Docs import Docs
|
2 |
+
|
3 |
+
docs = Docs(__file__)
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
docs.render().queue().launch()
|
layout_templates/coder_artifacts/demos/app.py
ADDED
@@ -0,0 +1,446 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import base64
|
2 |
+
import os
|
3 |
+
import re
|
4 |
+
|
5 |
+
import gradio as gr
|
6 |
+
import modelscope_studio.components.antd as antd
|
7 |
+
import modelscope_studio.components.base as ms
|
8 |
+
from openai import OpenAI
|
9 |
+
|
10 |
+
# =========== Configuration
|
11 |
+
|
12 |
+
# API KEY
|
13 |
+
MODELSCOPE_ACCESS_TOKEN = os.getenv('MODELSCOPE_ACCESS_TOKEN')
|
14 |
+
|
15 |
+
client = OpenAI(api_key=MODELSCOPE_ACCESS_TOKEN,
|
16 |
+
base_url="https://api-inference.modelscope.cn/v1")
|
17 |
+
|
18 |
+
# =========== Configuration
|
19 |
+
|
20 |
+
DEFAULT_SYSTEM_PROMPT = """You are a web development engineer, writing web pages according to the instructions below. You are a powerful code editing assistant capable of writing code and creating artifacts in conversations with users, or modifying and updating existing artifacts as requested by users.
|
21 |
+
All code is written in a single code block to form a complete code file for display, without separating HTML and JavaScript code. An artifact refers to a runnable complete code snippet, you prefer to integrate and output such complete runnable code rather than breaking it down into several code blocks. For certain types of code, they can render graphical interfaces in a UI window. After generation, please check the code execution again to ensure there are no errors in the output.
|
22 |
+
Output only the HTML, without any additional descriptive text."""
|
23 |
+
|
24 |
+
EXAMPLES = [
|
25 |
+
{
|
26 |
+
"title":
|
27 |
+
"Qwen,Start!",
|
28 |
+
"description":
|
29 |
+
"Help me design an interface with a purple button that says 'Qwen, Start!'. When the button is clicked, display a countdown from 5 in a very large font for 5 seconds.",
|
30 |
+
},
|
31 |
+
{
|
32 |
+
"title":
|
33 |
+
"Spam with emojis!",
|
34 |
+
"description":
|
35 |
+
"Write code in a single HTML file: Capture the click event, place a random number of emojis at the click position, and add gravity and collision effects to each emoji."
|
36 |
+
},
|
37 |
+
{
|
38 |
+
"title":
|
39 |
+
"TODO list",
|
40 |
+
"description":
|
41 |
+
"I want a TODO list that allows me to add tasks, delete tasks, and I would like the overall color theme to be purple."
|
42 |
+
},
|
43 |
+
]
|
44 |
+
|
45 |
+
DEFAULT_LOCALE = 'en_US'
|
46 |
+
|
47 |
+
DEFAULT_THEME = {
|
48 |
+
"token": {
|
49 |
+
"colorPrimary": "#6A57FF",
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
|
54 |
+
class GradioEvents:
|
55 |
+
|
56 |
+
@staticmethod
|
57 |
+
def generate_code(input_value, system_prompt_input_value, state_value):
|
58 |
+
# Define your code here
|
59 |
+
|
60 |
+
def remove_code_block(text):
|
61 |
+
pattern = r'```html\n(.+?)\n```'
|
62 |
+
match = re.search(pattern, text, re.DOTALL)
|
63 |
+
if match:
|
64 |
+
return match.group(1).strip()
|
65 |
+
else:
|
66 |
+
return text.strip()
|
67 |
+
|
68 |
+
def send_to_sandbox(code):
|
69 |
+
encoded_html = base64.b64encode(
|
70 |
+
code.encode('utf-8')).decode('utf-8')
|
71 |
+
data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
|
72 |
+
return f"<iframe src=\"{data_uri}\" width=\"100%\" height=\"100%\"></iframe>"
|
73 |
+
|
74 |
+
yield {
|
75 |
+
output_loading: gr.update(spinning=True),
|
76 |
+
state_tab: gr.update(active_key="loading"),
|
77 |
+
output: gr.update(value=None)
|
78 |
+
}
|
79 |
+
|
80 |
+
if input_value is None:
|
81 |
+
input_value = ''
|
82 |
+
|
83 |
+
messages = [{
|
84 |
+
'role': "system",
|
85 |
+
'content': system_prompt_input_value
|
86 |
+
}] + state_value["history"]
|
87 |
+
|
88 |
+
messages.append({'role': "user", 'content': input_value})
|
89 |
+
|
90 |
+
generator = client.chat.completions.create(
|
91 |
+
model="Qwen/Qwen2.5-Coder-32B-Instruct",
|
92 |
+
messages=messages,
|
93 |
+
stream=True)
|
94 |
+
response = ""
|
95 |
+
for chunk in generator:
|
96 |
+
content = chunk.choices[0].delta.content
|
97 |
+
response += content
|
98 |
+
if chunk.choices[0].finish_reason == 'stop':
|
99 |
+
state_value["history"] = messages + [{
|
100 |
+
'role': "assistant",
|
101 |
+
'content': response
|
102 |
+
}]
|
103 |
+
# Completed
|
104 |
+
yield {
|
105 |
+
output:
|
106 |
+
gr.update(value=response),
|
107 |
+
download_content:
|
108 |
+
gr.update(value=remove_code_block(response)),
|
109 |
+
state_tab:
|
110 |
+
gr.update(active_key="render"),
|
111 |
+
output_loading:
|
112 |
+
gr.update(spinning=False),
|
113 |
+
sandbox:
|
114 |
+
gr.update(
|
115 |
+
value=send_to_sandbox(remove_code_block(response))),
|
116 |
+
state:
|
117 |
+
gr.update(value=state_value)
|
118 |
+
}
|
119 |
+
|
120 |
+
else:
|
121 |
+
# Generating
|
122 |
+
yield {
|
123 |
+
output: gr.update(value=response),
|
124 |
+
output_loading: gr.update(spinning=False),
|
125 |
+
}
|
126 |
+
|
127 |
+
@staticmethod
|
128 |
+
def select_example(example: dict):
|
129 |
+
return lambda: gr.update(value=example["description"])
|
130 |
+
|
131 |
+
@staticmethod
|
132 |
+
def close_modal():
|
133 |
+
return gr.update(open=False)
|
134 |
+
|
135 |
+
@staticmethod
|
136 |
+
def open_modal():
|
137 |
+
return gr.update(open=True)
|
138 |
+
|
139 |
+
@staticmethod
|
140 |
+
def disable_btns(btns: list):
|
141 |
+
return lambda: [gr.update(disabled=True) for _ in btns]
|
142 |
+
|
143 |
+
@staticmethod
|
144 |
+
def enable_btns(btns: list):
|
145 |
+
return lambda: [gr.update(disabled=False) for _ in btns]
|
146 |
+
|
147 |
+
@staticmethod
|
148 |
+
def update_system_prompt(system_prompt_input_value, state_value):
|
149 |
+
state_value["system_prompt"] = system_prompt_input_value
|
150 |
+
return gr.update(value=state_value)
|
151 |
+
|
152 |
+
@staticmethod
|
153 |
+
def reset_system_prompt(state_value):
|
154 |
+
return gr.update(value=state_value["system_prompt"])
|
155 |
+
|
156 |
+
@staticmethod
|
157 |
+
def render_history(state):
|
158 |
+
return gr.update(value=state["history"])
|
159 |
+
|
160 |
+
@staticmethod
|
161 |
+
def clear_history(e: gr.EventData, state_value):
|
162 |
+
item = e._data["payload"][0]["key"]
|
163 |
+
if item == "clear":
|
164 |
+
gr.Success("History Cleared.")
|
165 |
+
state_value["history"] = []
|
166 |
+
return gr.update(value=state_value)
|
167 |
+
return gr.skip()
|
168 |
+
|
169 |
+
|
170 |
+
css = """
|
171 |
+
#coder-artifacts .output-empty,.output-loading {
|
172 |
+
display: flex;
|
173 |
+
flex-direction: column;
|
174 |
+
align-items: center;
|
175 |
+
justify-content: center;
|
176 |
+
width: 100%;
|
177 |
+
min-height: 680px;
|
178 |
+
}
|
179 |
+
|
180 |
+
#coder-artifacts .output-html {
|
181 |
+
display: flex;
|
182 |
+
flex-direction: column;
|
183 |
+
width: 100%;
|
184 |
+
min-height: 680px;
|
185 |
+
}
|
186 |
+
|
187 |
+
#coder-artifacts .output-html > iframe {
|
188 |
+
flex: 1;
|
189 |
+
}
|
190 |
+
|
191 |
+
#code-artifacts-code-drawer .output-code {
|
192 |
+
flex:1;
|
193 |
+
}
|
194 |
+
#code-artifacts-code-drawer .output-code .ms-gr-ant-spin-nested-loading {
|
195 |
+
min-height: 100%;
|
196 |
+
}
|
197 |
+
"""
|
198 |
+
|
199 |
+
with gr.Blocks(css=css) as demo:
|
200 |
+
# Global State
|
201 |
+
state = gr.State({"system_prompt": DEFAULT_SYSTEM_PROMPT, "history": []})
|
202 |
+
with ms.Application(elem_id="coder-artifacts") as app:
|
203 |
+
with antd.ConfigProvider(theme=DEFAULT_THEME, locale=DEFAULT_LOCALE):
|
204 |
+
# Header
|
205 |
+
with antd.Flex(justify="center", align="center", gap="middle"):
|
206 |
+
antd.Typography.Title("Coder-Artifacts",
|
207 |
+
level=1,
|
208 |
+
elem_style=dict(fontSize=24))
|
209 |
+
with ms.AutoLoading():
|
210 |
+
with antd.Row(gutter=[32, 12],
|
211 |
+
elem_style=dict(marginTop=20),
|
212 |
+
align="stretch"):
|
213 |
+
# Left Column
|
214 |
+
with antd.Col(span=24, md=8):
|
215 |
+
with antd.Flex(vertical=True, gap="middle", wrap=True):
|
216 |
+
# Input
|
217 |
+
input = antd.Input.Textarea(
|
218 |
+
size="large",
|
219 |
+
allow_clear=True,
|
220 |
+
auto_size=dict(minRows=2, maxRows=6),
|
221 |
+
placeholder=
|
222 |
+
"Describe the web application you want to create",
|
223 |
+
elem_id="input-container")
|
224 |
+
# Input Notes
|
225 |
+
with antd.Flex(align="center",
|
226 |
+
justify="space-between"):
|
227 |
+
antd.Typography.Text(
|
228 |
+
"Note: The model supports multi-round dialogue.",
|
229 |
+
strong=True,
|
230 |
+
type="warning")
|
231 |
+
|
232 |
+
tour_btn = antd.Button("Usage Tour",
|
233 |
+
variant="filled",
|
234 |
+
color="default")
|
235 |
+
# Submit Button
|
236 |
+
submit_btn = antd.Button("Submit",
|
237 |
+
type="primary",
|
238 |
+
block=True,
|
239 |
+
size="large",
|
240 |
+
elem_id="submit-btn")
|
241 |
+
|
242 |
+
antd.Divider("Settings")
|
243 |
+
|
244 |
+
# Settings Area
|
245 |
+
with antd.Space(size="small",
|
246 |
+
wrap=True,
|
247 |
+
elem_id="settings-area"):
|
248 |
+
system_prompt_btn = antd.Button(
|
249 |
+
"⚙️ Set System Prompt", type="default")
|
250 |
+
history_btn = antd.Dropdown.Button(
|
251 |
+
"📜 History",
|
252 |
+
type="default",
|
253 |
+
elem_id="history-btn",
|
254 |
+
menu=dict(items=[{
|
255 |
+
"key": "clear",
|
256 |
+
"label": "Clear History",
|
257 |
+
"danger": True
|
258 |
+
}]))
|
259 |
+
|
260 |
+
antd.Divider("Examples")
|
261 |
+
|
262 |
+
# Examples
|
263 |
+
with antd.Flex(gap="small", wrap=True):
|
264 |
+
for example in EXAMPLES:
|
265 |
+
with antd.Card(
|
266 |
+
hoverable=True) as example_card:
|
267 |
+
antd.Card.Meta(
|
268 |
+
title=example['title'],
|
269 |
+
description=example['description'])
|
270 |
+
|
271 |
+
example_card.click(
|
272 |
+
fn=GradioEvents.select_example(
|
273 |
+
example),
|
274 |
+
outputs=[input])
|
275 |
+
|
276 |
+
# Right Column
|
277 |
+
with antd.Col(span=24, md=16):
|
278 |
+
with antd.Card(title="Output",
|
279 |
+
elem_style=dict(height="100%"),
|
280 |
+
styles=dict(body=dict(height="100%")),
|
281 |
+
elem_id="output-container"):
|
282 |
+
# Output Container Extra
|
283 |
+
with ms.Slot("extra"):
|
284 |
+
with ms.Div(elem_id="output-container-extra"):
|
285 |
+
with antd.Button(
|
286 |
+
"Download HTML",
|
287 |
+
type="link",
|
288 |
+
href_target="_blank",
|
289 |
+
disabled=True,
|
290 |
+
) as download_btn:
|
291 |
+
with ms.Slot("icon"):
|
292 |
+
antd.Icon("DownloadOutlined")
|
293 |
+
download_content = gr.Text(visible=False)
|
294 |
+
|
295 |
+
view_code_btn = antd.Button(
|
296 |
+
"🧑💻 View Code", type="primary")
|
297 |
+
# Output Content
|
298 |
+
with antd.Tabs(
|
299 |
+
active_key="empty",
|
300 |
+
render_tab_bar="() => null") as state_tab:
|
301 |
+
with antd.Tabs.Item(key="empty"):
|
302 |
+
antd.Empty(
|
303 |
+
description=
|
304 |
+
"Enter your request to generate code",
|
305 |
+
elem_classes="output-empty")
|
306 |
+
with antd.Tabs.Item(key="loading"):
|
307 |
+
with antd.Spin(
|
308 |
+
tip="Generating code...",
|
309 |
+
size="large",
|
310 |
+
elem_classes="output-loading"):
|
311 |
+
# placeholder
|
312 |
+
ms.Div()
|
313 |
+
with antd.Tabs.Item(key="render"):
|
314 |
+
sandbox = gr.HTML(
|
315 |
+
elem_classes="output-html")
|
316 |
+
|
317 |
+
# Modals and Drawers
|
318 |
+
with antd.Modal(open=False,
|
319 |
+
title="System Prompt",
|
320 |
+
width="800px") as system_prompt_modal:
|
321 |
+
system_prompt_input = antd.Input.Textarea(
|
322 |
+
DEFAULT_SYSTEM_PROMPT,
|
323 |
+
size="large",
|
324 |
+
placeholder="Enter your system prompt here",
|
325 |
+
allow_clear=True,
|
326 |
+
auto_size=dict(minRows=4, maxRows=14))
|
327 |
+
|
328 |
+
with antd.Drawer(
|
329 |
+
open=False,
|
330 |
+
title="Output Code",
|
331 |
+
placement="right",
|
332 |
+
get_container=
|
333 |
+
"() => document.querySelector('.gradio-container')",
|
334 |
+
elem_id="code-artifacts-code-drawer",
|
335 |
+
styles=dict(
|
336 |
+
body=dict(display="flex",
|
337 |
+
flexDirection="column-reverse")),
|
338 |
+
width="750px") as output_code_drawer:
|
339 |
+
with ms.Div(elem_classes="output-code"):
|
340 |
+
with antd.Spin(spinning=False) as output_loading:
|
341 |
+
output = ms.Markdown()
|
342 |
+
|
343 |
+
with antd.Drawer(
|
344 |
+
open=False,
|
345 |
+
title="Chat History",
|
346 |
+
placement="left",
|
347 |
+
get_container=
|
348 |
+
"() => document.querySelector('.gradio-container')",
|
349 |
+
width="750px") as history_drawer:
|
350 |
+
history_output = gr.Chatbot(
|
351 |
+
show_label=False,
|
352 |
+
type="messages",
|
353 |
+
height='100%',
|
354 |
+
elem_classes="history_chatbot")
|
355 |
+
# Tour
|
356 |
+
with antd.Tour(open=False) as usage_tour:
|
357 |
+
antd.Tour.Step(
|
358 |
+
title="Step 1",
|
359 |
+
description=
|
360 |
+
"Describe the web application you want to create.",
|
361 |
+
get_target=
|
362 |
+
"() => document.querySelector('#input-container')")
|
363 |
+
antd.Tour.Step(
|
364 |
+
title="Step 2",
|
365 |
+
description="Click the submit button.",
|
366 |
+
get_target=
|
367 |
+
"() => document.querySelector('#submit-btn')")
|
368 |
+
antd.Tour.Step(
|
369 |
+
title="Step 3",
|
370 |
+
description="Wait for the result.",
|
371 |
+
get_target=
|
372 |
+
"() => document.querySelector('#output-container')"
|
373 |
+
)
|
374 |
+
antd.Tour.Step(
|
375 |
+
title="Step 4",
|
376 |
+
description=
|
377 |
+
"Download the generated HTML here or view the code.",
|
378 |
+
get_target=
|
379 |
+
"() => document.querySelector('#output-container-extra')"
|
380 |
+
)
|
381 |
+
antd.Tour.Step(
|
382 |
+
title="Additional Settings",
|
383 |
+
description=
|
384 |
+
"You can change the system prompt or chat history here.",
|
385 |
+
get_target=
|
386 |
+
"() => document.querySelector('#settings-area')")
|
387 |
+
# Event Handler
|
388 |
+
gr.on(fn=GradioEvents.close_modal,
|
389 |
+
triggers=[usage_tour.close, usage_tour.finish],
|
390 |
+
outputs=[usage_tour])
|
391 |
+
tour_btn.click(fn=GradioEvents.open_modal, outputs=[usage_tour])
|
392 |
+
|
393 |
+
system_prompt_btn.click(fn=GradioEvents.open_modal,
|
394 |
+
outputs=[system_prompt_modal])
|
395 |
+
|
396 |
+
system_prompt_modal.ok(GradioEvents.update_system_prompt,
|
397 |
+
inputs=[system_prompt_input, state],
|
398 |
+
outputs=[state]).then(fn=GradioEvents.close_modal,
|
399 |
+
outputs=[system_prompt_modal])
|
400 |
+
|
401 |
+
system_prompt_modal.cancel(GradioEvents.close_modal,
|
402 |
+
outputs=[system_prompt_modal]).then(
|
403 |
+
fn=GradioEvents.reset_system_prompt,
|
404 |
+
inputs=[state],
|
405 |
+
outputs=[system_prompt_input])
|
406 |
+
output_code_drawer.close(fn=GradioEvents.close_modal,
|
407 |
+
outputs=[output_code_drawer])
|
408 |
+
history_btn.menu_click(fn=GradioEvents.clear_history,
|
409 |
+
inputs=[state],
|
410 |
+
outputs=[state])
|
411 |
+
history_btn.click(fn=GradioEvents.open_modal,
|
412 |
+
outputs=[history_drawer
|
413 |
+
]).then(fn=GradioEvents.render_history,
|
414 |
+
inputs=[state],
|
415 |
+
outputs=[history_output])
|
416 |
+
history_drawer.close(fn=GradioEvents.close_modal, outputs=[history_drawer])
|
417 |
+
|
418 |
+
download_btn.click(fn=None,
|
419 |
+
inputs=[download_content],
|
420 |
+
js="""(content) => {
|
421 |
+
const blob = new Blob([content], { type: 'text/html' })
|
422 |
+
const url = URL.createObjectURL(blob)
|
423 |
+
const a = document.createElement('a')
|
424 |
+
a.href = url
|
425 |
+
a.download = 'output.html'
|
426 |
+
a.click()
|
427 |
+
}""")
|
428 |
+
view_code_btn.click(fn=GradioEvents.open_modal,
|
429 |
+
outputs=[output_code_drawer])
|
430 |
+
submit_btn.click(
|
431 |
+
fn=GradioEvents.open_modal,
|
432 |
+
outputs=[output_code_drawer],
|
433 |
+
).then(fn=GradioEvents.disable_btns([submit_btn, download_btn]),
|
434 |
+
outputs=[submit_btn, download_btn]).then(
|
435 |
+
fn=GradioEvents.generate_code,
|
436 |
+
inputs=[input, system_prompt_input, state],
|
437 |
+
outputs=[
|
438 |
+
output, state_tab, sandbox, download_content,
|
439 |
+
output_loading, state
|
440 |
+
]).then(fn=GradioEvents.enable_btns([submit_btn, download_btn]),
|
441 |
+
outputs=[submit_btn, download_btn
|
442 |
+
]).then(fn=GradioEvents.close_modal,
|
443 |
+
outputs=[output_code_drawer])
|
444 |
+
|
445 |
+
if __name__ == "__main__":
|
446 |
+
demo.queue().launch(ssr_mode=False)
|
requirements.txt
CHANGED
@@ -1 +1,2 @@
|
|
1 |
-
modelscope_studio==1.1.
|
|
|
|
1 |
+
modelscope_studio==1.1.1
|
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.
|
12 |
description = "A third-party component library based on Gradio."
|
13 |
readme = "README.md"
|
14 |
license = "Apache-2.0"
|
@@ -226,6 +226,9 @@ artifacts = [
|
|
226 |
"/backend/modelscope_studio/components/antdx/x_provider/templates",
|
227 |
]
|
228 |
|
|
|
|
|
|
|
229 |
[tool.hatch.build.targets.sdist]
|
230 |
exclude = ["__pycache__"]
|
231 |
include = ["/backend/modelscope_studio"]
|
|
|
8 |
|
9 |
[project]
|
10 |
name = "modelscope_studio"
|
11 |
+
version = "1.1.1"
|
12 |
description = "A third-party component library based on Gradio."
|
13 |
readme = "README.md"
|
14 |
license = "Apache-2.0"
|
|
|
226 |
"/backend/modelscope_studio/components/antdx/x_provider/templates",
|
227 |
]
|
228 |
|
229 |
+
[tool.yapfignore]
|
230 |
+
ignore_patterns = ["node_modules/**", "__pycache__/**", "**/*.pyi"]
|
231 |
+
|
232 |
[tool.hatch.build.targets.sdist]
|
233 |
exclude = ["__pycache__"]
|
234 |
include = ["/backend/modelscope_studio"]
|