This view is limited to 50 files because it contains too many changes. See the raw diff here.
Files changed (50) hide show
  1. .gitattributes +4 -2
  2. DOCS.md +15 -0
  3. Dockerfile +16 -0
  4. FAQ-zh_CN.md +0 -19
  5. FAQ.md +0 -19
  6. README-zh_CN.md +6 -39
  7. README.md +15 -50
  8. app.py +19 -615
  9. components/Chatbot/README-zh_CN.md +129 -0
  10. components/Chatbot/README.md +128 -0
  11. components/{antd/affix → Chatbot}/app.py +1 -1
  12. components/Chatbot/demos/.DS_Store +0 -0
  13. components/Chatbot/demos/accordion.py +47 -0
  14. components/Chatbot/demos/basic.py +54 -0
  15. components/Chatbot/demos/message_config.py +34 -0
  16. components/Chatbot/demos/multi_bots.py +86 -0
  17. components/Chatbot/demos/multimodal.py +42 -0
  18. components/Chatbot/demos/select-box.py +47 -0
  19. components/Chatbot/resources/audio.wav +0 -0
  20. components/Chatbot/resources/bot.jpeg +0 -0
  21. components/Chatbot/resources/custom_components/custom_select.js +26 -0
  22. components/Chatbot/resources/dog.mp4 +3 -0
  23. components/Chatbot/resources/image-bot.jpeg +0 -0
  24. components/Chatbot/resources/music-bot.jpeg +0 -0
  25. components/{pro/chatbot/resources/scenery.jpeg → Chatbot/resources/screen.jpeg} +0 -0
  26. components/Chatbot/resources/user.jpeg +0 -0
  27. components/Docs.py +160 -0
  28. components/Markdown/README-zh_CN.md +87 -0
  29. components/Markdown/README.md +83 -0
  30. components/Markdown/app.py +20 -0
  31. components/Markdown/custom_tags/accordion-zh_CN.md +23 -0
  32. components/Markdown/custom_tags/accordion.md +22 -0
  33. components/{pro/web_sandbox/README-zh_CN.md → Markdown/custom_tags/select-box-zh_CN.md} +30 -54
  34. components/Markdown/custom_tags/select-box.md +45 -0
  35. components/Markdown/demos/accordion.py +27 -0
  36. components/{base/markdown → Markdown}/demos/basic.py +4 -3
  37. components/Markdown/demos/custom-tag.py +20 -0
  38. components/Markdown/demos/custom-tag2.py +37 -0
  39. components/Markdown/demos/custom-tag3.py +30 -0
  40. components/Markdown/demos/custom-tag4.py +37 -0
  41. components/Markdown/demos/custom_tags/accordion/__pycache__/accordion-title.cpython-39.pyc +0 -0
  42. components/Markdown/demos/custom_tags/accordion/__pycache__/basic.cpython-39.pyc +0 -0
  43. components/{base/div/demos/basic.py → Markdown/demos/custom_tags/accordion/accordion-title.py} +12 -4
  44. components/{base/span/demos → Markdown/demos/custom_tags/accordion}/basic.py +10 -4
  45. components/Markdown/demos/custom_tags/select-box/__pycache__/basic.cpython-39.pyc +0 -0
  46. components/Markdown/demos/custom_tags/select-box/__pycache__/card_shape.cpython-39.pyc +0 -0
  47. components/Markdown/demos/custom_tags/select-box/__pycache__/card_shape_width_auto.cpython-39.pyc +0 -0
  48. components/Markdown/demos/custom_tags/select-box/__pycache__/python_events.cpython-39.pyc +0 -0
  49. components/Markdown/demos/custom_tags/select-box/basic.py +20 -0
  50. components/Markdown/demos/custom_tags/select-box/card_shape.py +31 -0
.gitattributes CHANGED
@@ -31,5 +31,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
31
  **/*ckpt*.meta filter=lfs diff=lfs merge=lfs -text
32
  **/*ckpt*.index filter=lfs diff=lfs merge=lfs -text
33
  *.safetensors filter=lfs diff=lfs merge=lfs -text
34
- *.ckpt filter=lfs diff=lfs merge=lfs -text
35
- *.whl filter=lfs diff=lfs merge=lfs -text
 
 
 
31
  **/*ckpt*.meta filter=lfs diff=lfs merge=lfs -text
32
  **/*ckpt*.index filter=lfs diff=lfs merge=lfs -text
33
  *.safetensors filter=lfs diff=lfs merge=lfs -text
34
+ *.ckpt filter=lfs diff=lfs merge=lfs -textcomponents/Chatbot/resources/dog.mp4 filter=lfs diff=lfs merge=lfs -text
35
+ components/Markdown/resources/dog.mp4 filter=lfs diff=lfs merge=lfs -text
36
+ modelscope_gradio_components-0.0.1b8-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
37
+ components/Chatbot/resources/dog.mp4 filter=lfs diff=lfs merge=lfs -text
DOCS.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ModelScope Gradio Components
2
+
3
+ ModelScope_Gradio_Components is a set of extension component libraries based on gradio 4.x, dedicated to serving the various extension needs of gradio applications within the ModelScope Studio. It mainly focuses on enhancing conversational scenarios, supporting multimodal contexts, and providing assistance for various other specialized scenarios.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pip install modelscope_gradio_components
9
+ ```
10
+
11
+ ## Components
12
+
13
+ - <tab-link component-tab="Chatbot">Chatbot</tab-link>
14
+ - <tab-link component-tab="MultimodalInput">MultimodalInput</tab-link>
15
+ - <tab-link component-tab="Markdown">Markdown</tab-link>
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.9
3
+
4
+ WORKDIR /code
5
+
6
+ COPY --link --chown=1000 . .
7
+
8
+ RUN mkdir -p /tmp/cache/
9
+ RUN chmod a+rwx -R /tmp/cache/
10
+ ENV TRANSFORMERS_CACHE=/tmp/cache/
11
+
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
+
14
+ ENV PYTHONUNBUFFERED=1 GRADIO_ALLOW_FLAGGING=never GRADIO_NUM_PORTS=1 GRADIO_SERVER_NAME=0.0.0.0 GRADIO_SERVER_PORT=7860 SYSTEM=spaces
15
+
16
+ CMD ["python", "app.py"]
FAQ-zh_CN.md DELETED
@@ -1,19 +0,0 @@
1
- # FAQ
2
-
3
- ## 为什么我的应用在本地可以正常运行,在 Hugging Face Space 中界面无法正常显示?
4
-
5
- 在 Hugging Face Space 中,默认开启了 Gradio 的 ssr 模式,但是此功能目前还无法很好的兼容自定义组件,需要我们手动关闭。请在`demo.launch()`方法中添加`ssr_mode=False`参数:`demo.launch(ssr_mode=False)`。
6
-
7
- ## 为什么我的应用每次操作都需要等待一小段时间才会有响应?
8
-
9
- `modelscope_studio`将组件的加载反馈进行了单独抽离。由于 Gradio 的交互操作涉及到前后端通信,需要有一段加载中的等待时间,当没有`AutoLoading`组件时,页面将不会显示 Gradio 的加载状态。因此,建议您至少在全局使用一次`AutoLoading`组件,以显示兜底的加载反馈。
10
-
11
- ```python
12
- import gradio as gr
13
- import modelscope_studio.components.antd as antd
14
- import modelscope_studio.components.base as ms
15
-
16
- with gr.Blocks() as demo:
17
- with ms.Application(), antd.ConfigProvider(), ms.AutoLoading():
18
- antd.Button()
19
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
FAQ.md DELETED
@@ -1,19 +0,0 @@
1
- # FAQ
2
-
3
- ## Why does my application run normally locally but the interface doesn't display properly in Hugging Face Space?
4
-
5
- In Hugging Face Space, Gradio's SSR mode is enabled by default, but this feature currently doesn't work well with custom components and needs to be manually disabled. Please add the `ssr_mode=False` parameter to the `demo.launch()`: `demo.launch(ssr_mode=False)`.
6
-
7
- ## Why does my application need to wait for a short time before responding to each operation?
8
-
9
- `modelscope_studio` has separately extracted the loading feedback for components. Since Gradio's interactive operations involve frontend-backend communication, there needs to be a loading wait time. When there is no `AutoLoading` component, the page will not display Gradio's loading status. Therefore, it is recommended that you use the `AutoLoading` component at least once globally to display fallback loading feedback.
10
-
11
- ```python
12
- import gradio as gr
13
- import modelscope_studio.components.antd as antd
14
- import modelscope_studio.components.base as ms
15
-
16
- with gr.Blocks() as demo:
17
- with ms.Application(), antd.ConfigProvider(), ms.AutoLoading():
18
- antd.Button()
19
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README-zh_CN.md CHANGED
@@ -1,48 +1,15 @@
1
  # ModelScope Studio
2
 
3
- <p align="center">
4
- <img src="https://modelscope.oss-cn-beijing.aliyuncs.com/modelscope.gif" height="60" style="vertical-align: middle;"/>
5
- <span style="font-size: 30px; vertical-align: middle;">
6
- ✖️
7
- </span>
8
- <img src="https://img.alicdn.com/imgextra/i1/O1CN01OmXst929933KJd7og_!!6000000008024-55-tps-2016-703.svg" height="60" style="vertical-align: middle;">
9
- <p>
10
 
11
- <p align="center">
12
- <a href="https://github.com/modelscope/modelscope-studio">GitHub</a> | 🤖 <a href="https://modelscope.cn/studios/modelscope/modelscope-studio">ModelScope Studio</a> | 🤗 <a href="https://huggingface.co/spaces/modelscope/modelscope-studio">Hugging Face Space</a>
13
-
14
- `modelscope_studio`是一个基于 Gradio 的三方组件库,为开发者提供更定制化的界面搭建能力和更丰富的组件使用形式。
15
-
16
- 目前支持的 UI 库:
17
-
18
- - [Ant Design](https://ant.design/)
19
-
20
- ## 何时使用
21
-
22
- 比起 Gradio 自身的组件,`modelscope_studio`更加注重页面布局和组件的灵活性,如果您想要构建更漂亮的用户界面,我们非常推荐您使用`modelscope_studio`。
23
-
24
- 然而,当您的应用需要 Gradio 在 Python 端更多地处理内置数据时,`modelscope_studio`的组件可能不是最好的选择,但是不用担心,它可以很好地与已有的 Gradio 组件相结合,您仍然可以使用`modelscope_studio`来优化您的应用。
25
-
26
- > 如果您正在 Hugging Face Space 中使用`modelscope_studio`,请在`demo.launch()`方法中添加`ssr_mode=False`参数:`demo.launch(ssr_mode=False)`,否则页面可能无法正常显示。
27
-
28
- ## 依赖
29
-
30
- - Gradio >= 6.0.0
31
-
32
- > 注意:您的 Gradio 版本必须`<=6.8.0`,[为什么?](https://github.com/gradio-app/gradio/issues/13131)
33
-
34
- ## 安装
35
 
36
  ```sh
37
  pip install modelscope_studio
38
  ```
39
 
40
- 如果您需要使用`4.43.0 <= Gradio < 6.0.0`,请使用 1.x 版本:
41
-
42
- ```sh
43
- pip install modelscope_studio~=1.0
44
- ```
45
-
46
- ## 示例
47
 
48
- <demo name="example"></demo>
 
 
 
1
  # ModelScope Studio
2
 
3
+ `modelscope_studio` 是一套基于 gradio 4.x 的扩展组件库,致力于服务于 ModelScope 创空间中对于 gradio 应用的各类扩展需求,目前主要聚集在对话场景增强、多模态场景以及一些其他垂直场景支持。
 
 
 
 
 
 
4
 
5
+ ## Install
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  ```sh
8
  pip install modelscope_studio
9
  ```
10
 
11
+ ## Components
 
 
 
 
 
 
12
 
13
+ - <tab-link component-tab="Chatbot">Chatbot</tab-link>
14
+ - <tab-link component-tab="MultimodalInput">MultimodalInput</tab-link>
15
+ - <tab-link component-tab="Markdown">Markdown</tab-link>
README.md CHANGED
@@ -1,66 +1,31 @@
1
  ---
2
  tags:
3
  - gradio-custom-component
4
- - component library
5
- - Ant Design
6
- - modelscope-studio
7
- title: modelscope-studio
8
- colorFrom: blue
9
- colorTo: gray
10
- short_description: A third-party component library based on Gradio.
11
- sdk: gradio
12
- sdk_version: 6.8.0
13
  pinned: false
14
- header: mini
15
- app_file: app.py
16
  license: apache-2.0
17
  ---
18
 
19
  # ModelScope Studio
20
 
21
- <p align="center">
22
- <img src="https://modelscope.oss-cn-beijing.aliyuncs.com/modelscope.gif" height="60" style="vertical-align: middle;"/>
23
- <span style="font-size: 30px; vertical-align: middle;">
24
- ✖️
25
- </span>
26
- <img src="https://github.com/gradio-app/gradio/raw/main/readme_files/gradio.svg" height="60" style="vertical-align: middle;">
27
- <p>
28
 
29
- <p align="center">
30
- <a href="https://github.com/modelscope/modelscope-studio">GitHub</a> | 🤖 <a href="https://modelscope.cn/studios/modelscope/modelscope-studio">ModelScope Studio</a> | 🤗 <a href="https://huggingface.co/spaces/modelscope/modelscope-studio">Hugging Face Space</a>
31
-
32
- `modelscope_studio` is a third-party component library based on Gradio, offers developers more customized interface building capabilities and a richer variety of component usage forms.
33
-
34
- Currently supported UI libraries:
35
-
36
- - [Ant Design](https://ant.design/)
37
-
38
- ## When to Use
39
-
40
- Compared to the original components of Gradio, `modelscope_studio` focuses more on page layout and component flexibility. If you want to build a more beautiful user interface, we highly recommend using `modelscope_studio`.
41
-
42
- However, when your application needs Gradio to handle more built-in data on the Python side, the components of `modelscope_studio` may not be the best choice, but don't worry, it integrates well with existing Gradio components, you can still use `modelscope_studio` to optimize your application.
43
-
44
- > If you are using `modelscope_studio` in Hugging Face Space, please add the `ssr_mode=False` parameter to the `demo.launch()`: `demo.launch(ssr_mode=False)`, otherwise the page may not display properly.
45
-
46
- ## Dependencies
47
-
48
- - Gradio >= 6.0.0
49
-
50
- > Note: Your Gradio version must`<=6.8.0`, [why?](https://github.com/gradio-app/gradio/issues/13131)
51
-
52
- ## Installation
53
 
54
  ```sh
55
  pip install modelscope_studio
56
  ```
57
 
58
- If you need to use `4.43.0 <= Gradio < 6.0.0`, please use 1.x version:
59
-
60
- ```sh
61
- pip install modelscope_studio~=1.0
62
- ```
63
-
64
- ## Examples
65
 
66
- <demo name="example"></demo>
 
 
 
1
  ---
2
  tags:
3
  - gradio-custom-component
4
+ - Chatbot
5
+ - MutilmodalInput
6
+ - Markdown
7
+ - gradio-template-Chatbot
8
+ - gradio-template-Markdown
9
+ title: modelscope_gradio_components V0.0.1b8
10
+ colorFrom: red
11
+ colorTo: red
12
+ sdk: docker
13
  pinned: false
 
 
14
  license: apache-2.0
15
  ---
16
 
17
  # ModelScope Studio
18
 
19
+ `modelscope_studio` is a set of extension component libraries based on gradio 4.x, dedicated to serving the various extension needs of gradio applications within the ModelScope Studio. It mainly focuses on enhancing conversational scenarios, supporting multimodal contexts, and providing assistance for various other specialized scenarios.
 
 
 
 
 
 
20
 
21
+ ## Install
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  ```sh
24
  pip install modelscope_studio
25
  ```
26
 
27
+ ## Components
 
 
 
 
 
 
28
 
29
+ - <tab-link component-tab="Chatbot">Chatbot</tab-link>
30
+ - <tab-link component-tab="MultimodalInput">MultimodalInput</tab-link>
31
+ - <tab-link component-tab="Markdown">Markdown</tab-link>
app.py CHANGED
@@ -1,618 +1,22 @@
1
- import os
2
- from typing import Literal
3
-
4
- import modelscope_studio.components.antd as antd
5
- import modelscope_studio.components.base as ms
6
- from helper.Docs import Docs
7
- from helper.env import is_modelscope_studio
8
- from helper.Site import Site
9
-
10
- is_dev = os.environ.get("GRADIO_WATCH_MODULE_NAME") == 'docs.app'
11
-
12
-
13
- def get_text(text: str, cn_text: str):
14
- if is_modelscope_studio:
15
- return cn_text
16
- return text
17
-
18
-
19
- def get_docs(type: Literal["antd", "antdx", "pro", "base"]):
20
- import importlib.util
21
-
22
- components = []
23
- components_dir = os.path.join(os.path.dirname(__file__), "components",
24
- type)
25
- for dir in os.listdir(components_dir):
26
- abs_dir = os.path.join(components_dir, dir)
27
- if os.path.isdir(abs_dir):
28
- app_file = os.path.join(abs_dir, "app.py")
29
- if os.path.exists(app_file):
30
- components.append(dir)
31
-
32
- docs = {}
33
- for component in components:
34
- spec = importlib.util.spec_from_file_location(
35
- "doc", os.path.join(components_dir, component, "app.py"))
36
- module = importlib.util.module_from_spec(spec)
37
- spec.loader.exec_module(module)
38
- docs[component] = module.docs
39
- return docs
40
-
41
-
42
- def get_layout_templates():
43
- import importlib.util
44
-
45
- templates = []
46
- templates_dir = os.path.join(os.path.dirname(__file__), "layout_templates")
47
- for dir in os.listdir(templates_dir):
48
- abs_dir = os.path.join(templates_dir, dir)
49
- if os.path.isdir(abs_dir):
50
- app_file = os.path.join(abs_dir, "app.py")
51
- if os.path.exists(app_file):
52
- templates.append(dir)
53
-
54
- docs = {}
55
- for template in templates:
56
- spec = importlib.util.spec_from_file_location(
57
- "doc", os.path.join(templates_dir, template, "app.py"))
58
- module = importlib.util.module_from_spec(spec)
59
- spec.loader.exec_module(module)
60
- docs[template] = module.docs
61
- return docs
62
-
63
-
64
- layout_templates = get_layout_templates()
65
-
66
- misc_docs = Docs(__file__)
67
-
68
-
69
- class IndexDocsItem:
70
-
71
- def __init__(self, module_name):
72
- self.module_name = module_name
73
-
74
- def get_css(self):
75
- return misc_docs.get_css()
76
-
77
- def render(self):
78
- return misc_docs.render(module_name=self.module_name)
79
-
80
-
81
- index_docs = {
82
- "overview": IndexDocsItem("README"),
83
- "faq": IndexDocsItem("FAQ"),
84
- **layout_templates
85
- }
86
-
87
- base_docs = get_docs("base")
88
- antd_docs = get_docs("antd")
89
- antdx_docs = get_docs("antdx")
90
- pro_docs = get_docs("pro")
91
-
92
- default_active_tab = "index"
93
- index_menu_items = [{
94
- "label": get_text("ModelScope-Studio", "ModelScope-Studio"),
95
- "key": "overview"
96
- }, {
97
- "label": get_text("FAQ", "FAQ"),
98
- "key": "faq"
99
- }, {
100
- "label":
101
- get_text("Layout Templates", "布局模板"),
102
- "type":
103
- "group",
104
- "children": [{
105
- "label": get_text("Coder-Artifacts", "Coder-Artifacts"),
106
- "key": "coder_artifacts"
107
- }, {
108
- "label": get_text("Chatbot", "Chatbot"),
109
- "key": "chatbot"
110
- }]
111
- }]
112
-
113
- base_menu_items = [{
114
- "label":
115
- get_text("Core", "核心"),
116
- "type":
117
- "group",
118
- "children": [{
119
- "label": get_text("Application", "Application 应用"),
120
- "key": "application"
121
- }, {
122
- "label": get_text("AutoLoading", "AutoLoading 自动加载"),
123
- "key": "auto_loading"
124
- }, {
125
- "label": get_text("Slot", "Slot 插槽"),
126
- "key": "slot"
127
- }, {
128
- "label": get_text("Fragment", "Fragment 片段"),
129
- "key": "fragment"
130
- }]
131
- }, {
132
- "label":
133
- get_text("Layout", "布局"),
134
- "type":
135
- "group",
136
- "children": [{
137
- "label": "Div",
138
- "key": "div"
139
- }, {
140
- "label": "Span",
141
- "key": "span"
142
- }, {
143
- "label": "Text",
144
- "key": "text"
145
- }, {
146
- "label": "Markdown",
147
- "key": "markdown"
148
- }]
149
- }, {
150
- "label":
151
- get_text("Render", "渲染"),
152
- "type":
153
- "group",
154
- "children": [{
155
- "label": get_text("Each", "Each 循环"),
156
- "key": "each"
157
- }, {
158
- "label": get_text("Filter", "Filter 过滤"),
159
- "key": "filter"
160
- }]
161
- }]
162
-
163
- pro_menu_items = [{
164
- "label":
165
- get_text("Chat", "对话"),
166
- "type":
167
- "group",
168
- "children": [{
169
- "label": get_text("Chatbot", "Chatbot 聊天机器人"),
170
- "key": "chatbot"
171
- }, {
172
- "label": get_text("MultimodalInput", "MultimodalInput 多模态输入框"),
173
- "key": "multimodal_input"
174
- }]
175
- }, {
176
- "label":
177
- get_text("Interactive Preview", "交互式预览"),
178
- "type":
179
- "group",
180
- "children": [{
181
- "label": get_text("WebSandbox", "WebSandbox 网页沙盒"),
182
- "key": "web_sandbox"
183
- }, {
184
- "label": get_text("MonacoEditor", "MonacoEditor 代码编辑器"),
185
- "key": "monaco_editor"
186
- }]
187
- }]
188
-
189
- antd_menu_items = [{
190
- "label": get_text("Overview", "概览"),
191
- "key": "overview"
192
- }, {
193
- "label":
194
- get_text("General", "通用"),
195
- "type":
196
- "group",
197
- "children": [{
198
- "label": get_text("Button", "Button 按钮"),
199
- "key": "button"
200
- }, {
201
- "label": get_text("FloatButton", "FloatButton 悬浮按钮"),
202
- "key": "float_button"
203
- }, {
204
- "label": get_text("Icon", "Icon 图标"),
205
- "key": "icon"
206
- }, {
207
- "label": get_text("Typography", "Typography 排版"),
208
- "key": "typography"
209
- }]
210
- }, {
211
- "label":
212
- get_text("Layout", "布局"),
213
- "type":
214
- "group",
215
- "children": [{
216
- "label": get_text("Divider", "Divider 分割线"),
217
- "key": "divider"
218
- }, {
219
- "label": get_text("Flex", "Flex 弹性布局"),
220
- "key": "flex"
221
- }, {
222
- "label": get_text("Grid", "Grid 栅格"),
223
- "key": "grid"
224
- }, {
225
- "label": get_text("Layout", "Layout 布局"),
226
- "key": "layout"
227
- }, {
228
- "label": get_text("Masonry", "Masonry 瀑布流"),
229
- "key": "masonry"
230
- }, {
231
- "label": get_text("Space", "Space 间距"),
232
- "key": "space"
233
- }, {
234
- "label": get_text("Splitter", "Splitter 分割面板"),
235
- "key": "splitter"
236
- }]
237
- }, {
238
- "label":
239
- get_text("Navigation", "导航"),
240
- "type":
241
- "group",
242
- "children": [{
243
- "label": get_text("Anchor", "Anchor 锚点"),
244
- "key": "anchor"
245
- }, {
246
- "label": get_text("Breadcrumb", "Breadcrumb 面包屑"),
247
- "key": "breadcrumb"
248
- }, {
249
- "label": get_text("Dropdown", "Dropdown 下拉菜单"),
250
- "key": "dropdown"
251
- }, {
252
- "label": get_text("Menu", "Menu 导航菜单"),
253
- "key": "menu"
254
- }, {
255
- "label": get_text("Pagination", "Pagination 分页"),
256
- "key": "pagination"
257
- }, {
258
- "label": get_text("Steps", "Steps 步骤条"),
259
- "key": "steps"
260
- }]
261
- }, {
262
- "label":
263
- get_text("Data Entry", "数据录入"),
264
- "type":
265
- "group",
266
- "children": [{
267
- "label": get_text("AutoComplete", "AutoComplete 自动完成"),
268
- "key": "auto_complete"
269
- }, {
270
- "label": get_text("Cascader", "Cascader 级联选择"),
271
- "key": "cascader"
272
- }, {
273
- "label": get_text("Checkbox", "Checkbox 多选框"),
274
- "key": "checkbox"
275
- }, {
276
- "label": get_text("ColorPicker", "ColorPicker 颜色选择器"),
277
- "key": "color_picker"
278
- }, {
279
- "label": get_text("DatePicker", "DatePicker 日期选择框"),
280
- "key": "date_picker"
281
- }, {
282
- "label": get_text("Form", "Form 表单"),
283
- "key": "form"
284
- }, {
285
- "label": get_text("Input", "Input 输入框"),
286
- "key": "input"
287
- }, {
288
- "label": get_text("InputNumber", "InputNumber 数字输入框"),
289
- "key": "input_number"
290
- }, {
291
- "label": get_text("Mentions", "Mentions 提及"),
292
- "key": "mentions"
293
- }, {
294
- "label": get_text("Radio", "Radio 单选框"),
295
- "key": "radio"
296
- }, {
297
- "label": get_text("Rate", "Rate 评分"),
298
- "key": "rate"
299
- }, {
300
- "label": get_text("Select", "Select 选择器"),
301
- "key": "select"
302
- }, {
303
- "label": get_text("Slider", "Slider 滑动输入条"),
304
- "key": "slider"
305
- }, {
306
- "label": get_text("Switch", "Switch 开关"),
307
- "key": "switch"
308
- }, {
309
- "label": get_text("TimePicker", "TimePicker 时间选择器"),
310
- "key": "time_picker"
311
- }, {
312
- "label": get_text("Transfer", "Transfer 穿梭框"),
313
- "key": "transfer"
314
- }, {
315
- "label": get_text("TreeSelect", "TreeSelect 树选择"),
316
- "key": "tree_select"
317
- }, {
318
- "label": get_text("Upload", "Upload 上传"),
319
- "key": "upload"
320
- }]
321
- }, {
322
- "label":
323
- get_text("Data Display", "数据展示"),
324
- "type":
325
- "group",
326
- "children": [{
327
- "label": get_text("Avatar", "Avatar 头像"),
328
- "key": "avatar"
329
- }, {
330
- "label": get_text("Badge", "Badge 徽标数"),
331
- "key": "badge"
332
- }, {
333
- "label": get_text("Calendar", "Calendar 日历"),
334
- "key": "calendar"
335
- }, {
336
- "label": get_text("Card", "Card 卡片"),
337
- "key": "card"
338
- }, {
339
- "label": get_text("Carousel", "Carousel 走马灯"),
340
- "key": "carousel"
341
- }, {
342
- "label": get_text("Collapse", "Collapse 折叠面板"),
343
- "key": "collapse"
344
- }, {
345
- "label": get_text("Descriptions", "Descriptions 描述列表"),
346
- "key": "descriptions"
347
- }, {
348
- "label": get_text("Empty", "Empty 空状态"),
349
- "key": "empty"
350
- }, {
351
- "label": get_text("Image", "Image 图片"),
352
- "key": "image"
353
- }, {
354
- "label": get_text("List", "List 列表"),
355
- "key": "list"
356
- }, {
357
- "label": get_text("Popover", "Popover 气泡卡片"),
358
- "key": "popover"
359
- }, {
360
- "label": get_text("QRCode", "QRCode 二维码"),
361
- "key": "qr_code"
362
- }, {
363
- "label": get_text("Segmented", "Segmented 分段控制器"),
364
- "key": "segmented"
365
- }, {
366
- "label": get_text("Statistic", "Statistic 统计数值"),
367
- "key": "statistic"
368
- }, {
369
- "label": get_text("Table", "Table 表格"),
370
- "key": "table"
371
- }, {
372
- "label": get_text("Tabs", "Tabs 标签页"),
373
- "key": "tabs"
374
- }, {
375
- "label": get_text("Tag", "Tag 标签"),
376
- "key": "tag"
377
- }, {
378
- "label": get_text("Timeline", "Timeline 时间轴"),
379
- "key": "timeline"
380
- }, {
381
- "label": get_text("Tooltip", "Tooltip 文字提示"),
382
- "key": "tooltip"
383
- }, {
384
- "label": get_text("Tour", "Tour 漫游式引导"),
385
- "key": "tour"
386
- }, {
387
- "label": get_text("Tree", "Tree 树形控件"),
388
- "key": "tree"
389
- }]
390
- }, {
391
- "label":
392
- get_text("Feedback", "反馈"),
393
- "type":
394
- "group",
395
- "children": [{
396
- "label": get_text("Alert", "Alert 警告提示"),
397
- "key": "alert"
398
- }, {
399
- "label": get_text("Drawer", "Drawer 抽屉"),
400
- "key": "drawer"
401
- }, {
402
- "label": get_text("Message", "Message 全局提示"),
403
- "key": "message"
404
- }, {
405
- "label": get_text("Modal", "Modal 对话框"),
406
- "key": "modal"
407
- }, {
408
- "label": get_text("Notification", "Notification 通知提醒框"),
409
- "key": "notification"
410
- }, {
411
- "label": get_text("Popconfirm", "Popconfirm 气泡确认框"),
412
- "key": "popconfirm"
413
- }, {
414
- "label": get_text("Progress", "Progress 进度条"),
415
- "key": "progress"
416
- }, {
417
- "label": get_text("Result", "Result 结果"),
418
- "key": "result"
419
- }, {
420
- "label": get_text("Skeleton", "Skeleton 骨架屏"),
421
- "key": "skeleton"
422
- }, {
423
- "label": get_text("Spin", "Spin 加载中"),
424
- "key": "spin"
425
- }, {
426
- "label": get_text("Watermark", "Watermark 水印"),
427
- "key": "watermark"
428
- }]
429
- }, {
430
- "label":
431
- get_text("Other", "其他"),
432
- "type":
433
- "group",
434
- "children": [{
435
- "label": get_text("Affix", "Affix 固钉"),
436
- "key": "affix"
437
- }, {
438
- "label": get_text("ConfigProvider", "ConfigProvider 全局化配置"),
439
- "key": "config_provider"
440
- }]
441
- }]
442
-
443
- antdx_menu_items = [{
444
- "label": get_text("Overview", "概览"),
445
- "key": "overview"
446
- }, {
447
- "label":
448
- get_text("Common", "通用"),
449
- "type":
450
- "group",
451
- "children": [{
452
- "label": get_text("Bubble", "Bubble 对话气泡"),
453
- "key": "bubble"
454
- }, {
455
- "label": get_text("Conversations", "Conversations 管理对话"),
456
- "key": "conversations"
457
- }, {
458
- "label": get_text("Notification", "Notification 系统通知"),
459
- "key": "notification"
460
- }]
461
- }, {
462
- "label":
463
- get_text("Wake", "唤醒"),
464
- "type":
465
- "group",
466
- "children": [{
467
- "label": get_text("Welcome", "Welcome 欢迎"),
468
- "key": "welcome"
469
- }, {
470
- "label": get_text("Prompts", "Prompts 提示集"),
471
- "key": "prompts"
472
- }]
473
- }, {
474
- "label":
475
- get_text("Express", "表达"),
476
- "type":
477
- "group",
478
- "children": [{
479
- "label": get_text("Attachments", "Attachments 输入附件"),
480
- "key": "attachments"
481
- }, {
482
- "label": get_text("Sender", "Sender 输入框"),
483
- "key": "sender"
484
- }, {
485
- "label": get_text("Suggestion", "Suggestion 快捷指令"),
486
- "key": "suggestion"
487
- }]
488
- }, {
489
- "label":
490
- get_text("Confirm", "确认"),
491
- "type":
492
- "group",
493
- "children": [{
494
- "label": get_text("Think", "Think 思考过程"),
495
- "key": "think"
496
- }, {
497
- "label": get_text("ThoughtChain", "ThoughtChain 思考链"),
498
- "key": "thought_chain"
499
- }]
500
- }, {
501
- "label":
502
- get_text("Feedback", "反馈"),
503
- "type":
504
- "group",
505
- "children": [{
506
- "label": get_text("Actions", "Actions 操作列表"),
507
- "key": "actions"
508
- }, {
509
- "label": get_text("CodeHighlighter", "CodeHighlighter 代码高亮"),
510
- "key": "code_highlighter"
511
- }, {
512
- "label": get_text("FileCard", "FileCard 文件卡片"),
513
- "key": "file_card"
514
- }, {
515
- "label": get_text("Folder", "Folder 文件夹"),
516
- "key": "folder"
517
- }, {
518
- "label": get_text("Mermaid", "Mermaid 图表工具"),
519
- "key": "mermaid"
520
- }, {
521
- "label": get_text("Sources", "Sources 来源引用"),
522
- "key": "sources"
523
- }]
524
- }, {
525
- "label":
526
- get_text("Tools", "工具"),
527
- "type":
528
- "group",
529
- "children": [{
530
- "label": get_text("XProvider", "XProvider 全局化配置"),
531
- "key": "x_provider"
532
- }]
533
- }]
534
-
535
-
536
- def logo():
537
- with antd.Flex(align='center', gap=8):
538
- antd.Image(os.path.join(os.path.dirname(__file__),
539
- "./resources/modelscope.png"),
540
- preview=False,
541
- height=20,
542
- elem_style=dict(width="auto"))
543
- ms.Span('✖️')
544
- antd.Image(os.path.join(os.path.dirname(__file__),
545
- "./resources/gradio.png"),
546
- preview=False,
547
- height=40,
548
- elem_style=dict(width="auto"))
549
-
550
-
551
- def more_components():
552
- with antd.Button(type="link",
553
- block=True,
554
- href="https://ant.design/components/overview/",
555
- href_target="_blank",
556
- elem_style=dict(display="block",
557
- textAlign="left",
558
- whiteSpace="nowrap",
559
- textOverflow="ellipsis",
560
- overflow="hidden")):
561
- ms.Text(get_text("More Components", "更多组件"))
562
-
563
- with ms.Slot("icon"):
564
- antd.Icon("ExportOutlined", elem_style=dict(marginRight=4))
565
-
566
-
567
- tabs = [
568
- {
569
- "label": get_text("Overview", "概览"),
570
- "key": "index",
571
- "default_active_key": "overview",
572
- "menus": index_menu_items
573
- },
574
- {
575
- "label": get_text("Base Components", "基础组件"),
576
- "key": "base",
577
- "default_active_key": "application",
578
- "menus": base_menu_items
579
- },
580
- {
581
- "label": get_text("Pro Components", "高级组件"),
582
- "key": "pro",
583
- "default_active_key": "chatbot",
584
- "menus": pro_menu_items
585
- },
586
- {
587
- "label": get_text("Antd Components", "Antd 组件"),
588
- "key": "antd",
589
- "default_active_key": "overview",
590
- "menus": antd_menu_items,
591
- "extra_menu_footer": more_components
592
- },
593
- {
594
- "label": get_text("Antdx Components", "Antdx 组件"),
595
- "key": "antdx",
596
- "default_active_key": "overview",
597
- "menus": antdx_menu_items,
598
- },
599
  ]
600
 
601
- site = Site(
602
- tabs=tabs,
603
- docs={
604
- # match the key of tabs
605
- "index": index_docs,
606
- "antd": antd_docs,
607
- "antdx": antdx_docs,
608
- "base": base_docs,
609
- "pro": pro_docs
610
- },
611
- default_active_tab=default_active_tab,
612
- logo=logo)
613
-
614
- demo, css = site.render()
615
 
616
- if __name__ == "__main__":
617
- demo.queue(default_concurrency_limit=100,
618
- max_size=100).launch(css=css, ssr_mode=False, max_threads=100)
 
1
+ import gradio as gr
2
+ from components.Chatbot.app import docs as chatbot_docs
3
+ from components.Docs import Docs
4
+ from components.Markdown.app import docs as markdown_docs
5
+ from components.MultimodalInput.app import docs as multimodel_input_docs
6
+
7
+ readme_docs = Docs(__file__)
8
+
9
+ docs = [
10
+ ["Quick Start", readme_docs],
11
+ ["Chatbot", chatbot_docs],
12
+ ["Markdown", markdown_docs],
13
+ ["MultimodalInput", multimodel_input_docs],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  ]
15
 
16
+ with gr.Blocks() as demo:
17
+ with gr.Tabs() as components_tabs:
18
+ for doc in docs:
19
+ with gr.TabItem(doc[0], id=doc[0]):
20
+ doc[1].render(components_tabs)
 
 
 
 
 
 
 
 
 
21
 
22
+ demo.queue().launch()
 
 
components/Chatbot/README-zh_CN.md ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Chatbot
2
+
3
+ 升级版的 gradio Chatbot。
4
+
5
+ - 支持前端匀速流式输出 message
6
+ - 支持输出多模态内容(音频、视频、语音、文件、文本)
7
+ - 支持多 agent 场景
8
+ - 支持自定义渲染组件,并与 Python 侧事件交互
9
+
10
+ ## 如何使用
11
+
12
+ ### 基本使用
13
+
14
+ <demo name="basic"></demo>
15
+
16
+ ### 多模态 & 支持本地文件的展示
17
+
18
+ <demo name="multimodal"></demo>
19
+
20
+ ### 控制打字机单句 message 开关
21
+
22
+ <demo name="message_config"></demo>
23
+
24
+ ### 支持手风琴内容展示
25
+
26
+ 在返回的内容中加入 `accordion` 标签,可以在内容中加入手风琴,更多用法详见 <tab-link component-tab="Markdown">Markdown 内置自定义标签</tab-link>
27
+
28
+ 同时为了适配大模型的工具调用链路,额外对某些大模型的格式做了预设配置,支持下述格式的预设处理(会将下面的格式转换成上方`accordion`标签包裹形式)
29
+
30
+ ```python
31
+ import modelscope_studio as mgr
32
+ from modelscope_studio.components.Chatbot.llm_thinking_presets import qwen
33
+
34
+ # 添加 qwen 解析预设
35
+ mgr.Chatbot(llm_thinking_presets=[qwen()])
36
+ ```
37
+
38
+ ```text
39
+ Action: image_gen
40
+ Action Input: {"text": "glorious weather", "resolution": "1024*1024"}
41
+ Observation: <result>![IMAGEGEN](https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/a2/20231213/723609ee/1926736d-7c6e-4d2f-b438-b7746b3d89f5-1.png?Expires=1702537773&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=H%2B0rIn6BMfE%2BOr1uPb7%2Br9G3%2B5w%3D)</result> 根据您的描述"glorious weather",我生成了一张图片。![](https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/a2/20231213/723609ee/1926736d-7c6e-4d2f-b438-b7746b3d89f5-1.png?Expires=1702537773&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=H%2B0rIn6BMfE%2BOr1uPb7%2Br9G3%2B5w%3D)
42
+
43
+ Action: 「任意文本表示,将展示为思考链调用的名称」
44
+ Action Input: 「任意json or md 内容,将展示到调用过程的下拉框」
45
+ Observation: <result>「任意 md 内容,将作为完成调用的展示的下拉框内」</result>
46
+ ```
47
+
48
+ <demo name="accordion"></demo>
49
+
50
+ ### 支持用户选择交互
51
+
52
+ 在返回的内容中加入 `select-box` 标签,更多用法详见 <tab-link component-tab="Markdown">Markdown 内置自定义标签</tab-link>
53
+
54
+ <demo name="select-box"></demo>
55
+
56
+ ### 多 bot 场景
57
+
58
+ <demo name="multi_bots"></demo>
59
+
60
+ ### 自定义标签(高阶用法,需要了解前端知识)
61
+
62
+ 详见 <tab-link component-tab="Markdown">Markdown</tab-link> 组件
63
+
64
+ ## API 及参数列表
65
+
66
+ 以下 API 均为在原有 gradio Chatbot 外的额外拓展参数。
67
+
68
+ ### value
69
+
70
+ 接口定义:
71
+
72
+ ```python
73
+
74
+ class FileMessage(GradioModel):
75
+ file: FileData
76
+ alt_text: Optional[str] = None
77
+
78
+
79
+ class MultimodalMessage(GradioModel):
80
+ name: Optional[str] = None
81
+ text: Optional[str] = None
82
+ flushing: Optional[bool] = None
83
+ avatar: Optional[Union[str, FileData]] = ''
84
+ files: Optional[List[Union[FileMessage, dict, FileData, str]]] = None
85
+
86
+ # 支持多 bot 场景
87
+ MultimodalMessageItem = Optional[Union[MultimodalMessage, MultimodalInputData,
88
+ dict, str]]
89
+
90
+
91
+ class ChatbotData(GradioRootModel):
92
+ root: List[Tuple[Union[MultimodalMessageItem, List[MultimodalMessageItem]],
93
+ Union[MultimodalMessageItem,
94
+ List[MultimodalMessageItem]]]]
95
+ ```
96
+
97
+ ### props
98
+
99
+ | 属性 | 类型 | 默认值 | 描述 |
100
+ | -------------------- | -------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
101
+ | flushing | bool | True | 是否开启打字机效果。默认只有 bot 的 message 会开启,可以通过单独修改 message 的 flushing 属性精确控制每一条 message 的显示效果 |
102
+ | enable_base64 | bool | False | 是否支持渲染的内容为 base64,因为直接渲染 base64 有安全问题,默认为 False。 |
103
+ | preview | bool | True | 是否开启图片预览功能 |
104
+ | avatar_images | tuple\[str \| Path \| None \| dict \| list, str \| Path \| None \| dict\| list\] | None | 拓展gr.Chatbot的参数值,除了接收 url 外还可以接收 dict 和 list,dict 可以传入avatar和name字段,name字段在渲染时会显示在头像下方。 <br/> - 当传入 dict 时,必须包含有avatar字段。<br/> - 当传入 list 时,一般对应多 bot 模式,每一项可以接收前面所有的值,每个 bot 的头像与 message 中 bot 的位置一一对应 |
105
+ | avatar_image_align | Literal['top', 'middle', 'bottom'] | 'bottom' | 控制头像与 message 的对齐方式,默认为下对齐 |
106
+ | avatar_image_width | int | 45 | 头像与名称的宽度 |
107
+ | flushing_speed | int | 3 | 打字机速度,值为 1 - 10,值越大速度越快 |
108
+ | llm_thinking_presets | list\[dict\] | \[\] | llm 思考链路解析预设,可以将 llm 调用工具的输出格式转为固定的前端展示格式,需要从modelscope_studio.Chatbot.llm_thinking_presets引入,目前支持:qwen |
109
+ | custom_components | dict\[str, CustomComponentDict\] CustomComponentDict 定义见下方 | None | 支持用户定义自定义标签,并通过 js 控制标签渲染样式与触发 python 事件。 |
110
+
111
+ **CustomComponent 定义如下**
112
+
113
+ ```python
114
+ class CustomComponentDict(TypedDict):
115
+ props: Optional[List[str]]
116
+ template: Optional[str]
117
+ js: Optional[str]
118
+ ```
119
+
120
+ ### 内置的自定义标签
121
+
122
+ 见 <tab-link component-tab="Markdown">Markdown 内置自定义标签</tab-link>
123
+
124
+ ### event listeners
125
+
126
+ | 事件 | 描述 |
127
+ | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
128
+ | `mgr.Chatbot.flushed(fn, ···)` | 当打字机效果结束时触发。EventData 为:<br/> - index:当前 message 的 index tuple。<br/> - value:当前 message value。 |
129
+ | `mgr.Chatbot.custom(fn, ···)` | 自定义标签触发事件时触发,EventData 为:<br/> - index:前 message 的 index tuple。<br/> - tag:当前触发的标签。<br/> - tag_index:当前触发标签的 index,此 index 在 mesage 的 index tuple 基础上重新计算。<br/> - value:自定义传入的值。 |
components/Chatbot/README.md ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Chatbot
2
+
3
+ Upgraded gradio Chatbot.
4
+
5
+ - Supports uniform frontend streaming output of messages
6
+ - Supports output of multimodal content (audio, video, voice, files, text)
7
+ - Supports multi-agent scenarios
8
+ - Supports custom rendering components and interaction with events on the Python side
9
+
10
+ ## How to Use
11
+
12
+ ### Basic Usage
13
+
14
+ <demo name="basic"></demo>
15
+
16
+ ### Multimodal & Support for Local File Display
17
+
18
+ <demo name="multimodal"></demo>
19
+
20
+ ### Control for Typewriter Single Sentence Message
21
+
22
+ <demo name="message_config"></demo>
23
+
24
+ ### Support for Accordion Content Display
25
+
26
+ Include the `accordion` tag in the returned content to add an accordion within the content. For more usage details, see <tab-link component-tab="Markdown">Markdown Built-in Custom Tags</tab-link>.
27
+ Additionally, to adapt to the toolchain usage of large models, some preset configurations for certain large models have been made. Support for the following preset formats (which will be converted into the form wrapped by the above `accordion` tag).
28
+
29
+ ```python
30
+ import modelscope_studio as mgr
31
+ from modelscope_studio.components.Chatbot.llm_thinking_presets import qwen
32
+
33
+ # Add qwen preset
34
+ mgr.Chatbot(llm_thinking_presets=[qwen()])
35
+ ```
36
+
37
+ ```text
38
+ Action: image_gen
39
+ Action Input: {"text": "glorious weather", "resolution": "1024*1024"}
40
+ Observation: <result>![IMAGEGEN](https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/a2/20231213/723609ee/1926736d-7c6e-4d2f-b438-b7746b3d89f5-1.png?Expires=1702537773&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=H%2B0rIn6BMfE%2BOr1uPb7%2Br9G3%2B5w%3D)</result> Based on your description: glorious weather,I generated a picture.[](https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/a2/20231213/723609ee/1926736d-7c6e-4d2f-b438-b7746b3d89f5-1.png?Expires=1702537773&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=H%2B0rIn6BMfE%2BOr1uPb7%2Br9G3%2B5w%3D)
41
+
42
+ Action: 「An arbitrary text representation that will be displayed as the name of the thought chain call」
43
+ Action Input: 「Any json or md content will be displayed in the drop-down box of the calling process」
44
+ Observation: <result>「Any md content will be displayed in the drop-down box when the call is completed」</result>
45
+ ```
46
+
47
+ <demo name="accordion"></demo>
48
+
49
+ ### Support for User Selection Interaction
50
+
51
+ Include the `select-box` tag in the returned content for more usage details, see <tab-link component-tab="Markdown">Markdown Built-in Custom Tags <tab-link component-tab="Markdown">.
52
+
53
+ <demo name="select-box"></demo>
54
+
55
+ ### Multi-bot Scenarios
56
+
57
+ <demo name="multi_bots"></demo>
58
+
59
+ ### Custom Tags (Advanced Usage, Requires Frontend Knowledge)
60
+
61
+ See the <tab-link component-tab="Markdown">Markdown component</tab-link> for details.
62
+
63
+ ## API and Parameter List
64
+
65
+ The following APIs are additional extended parameters beyond the original gradio Chatbot.
66
+
67
+ ### value
68
+
69
+ Interface definition:
70
+
71
+ ```python
72
+
73
+ class FileMessage(GradioModel):
74
+ file: FileData
75
+ alt_text: Optional[str] = None
76
+
77
+
78
+ class MultimodalMessage(GradioModel):
79
+ name: Optional[str] = None
80
+ text: Optional[str] = None
81
+ flushing: Optional[bool] = None
82
+ avatar: Optional[Union[str, FileData]] = ''
83
+ files: Optional[List[Union[FileMessage, dict, FileData, str]]] = None
84
+
85
+ # Support multi-bot scenarios
86
+ MultimodalMessageItem = Optional[Union[MultimodalMessage, MultimodalInputData,
87
+ dict, str]]
88
+
89
+
90
+ class ChatbotData(GradioRootModel):
91
+ root: List[Tuple[Union[MultimodalMessageItem, List[MultimodalMessageItem]],
92
+ Union[MultimodalMessageItem,
93
+ List[MultimodalMessageItem]]]]
94
+ ```
95
+
96
+ ### props
97
+
98
+ | Attribute | Type | Default Value | Description |
99
+ | -------------------- | -------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
100
+ | flushing | bool | True | Whether to enable the typewriter effect. By default, only the bot's messages will have this effect, but you can control the display effect of each message precisely by modifying the flushing attribute of a message individually. |
101
+ | enable_base64 | bool | False | Whether to support rendering content as base64, since rendering base64 is not safe, the default is False. |
102
+ | preview | bool | True | Whether to enable image preview functionality. |
103
+ | avatar_images | tuple\[str \| Path \| None \| dict \| list, str \| Path \| None \| dict\| list\] | None | An extended parameter value for gr.Chatbot, in addition to accepting a URL, it can also accept a dict and list. The dict can include the fields avatar and name, where the name field will be displayed under the avatar when rendered. <br/> - When passing a dict, it must include an avatar field.<br/> - When passing a list, it generally corresponds to the multi-bot mode, where each item can receive all the aforementioned values, and each bot’s avatar matches with the position of the bot in the messages. |
104
+ | avatar_image_align | Literal['top', 'middle', 'bottom'] | 'bottom' | Controls the alignment of the avatar with the messages, default is bottom-aligned. |
105
+ | avatar_image_width | int | 45 | The width of the avatar and name. |
106
+ | flushing_speed | int | 3 | Typewriter speed, values range from 1 - 10, with larger values indicating faster speeds. |
107
+ | llm_thinking_presets | list\[dict\] | \[\] | llm thinking link presets, which can convert the output format of llm calling tools into a fixed front-end display format. It needs to be imported from modelscope_studio.Chatbot.llm_thinking_presets, and currently supports: qwen. |
108
+ | custom_components | dict\[str, CustomComponentDict\] CustomComponentDict is defined below | None | Allows users to define custom tags and control tag rendering styles and trigger Python events through JS. |
109
+
110
+ **Definition of CustomComponent is as follows:**
111
+
112
+ ```python
113
+ class CustomComponentDict(TypedDict):
114
+ props: Optional[List[str]]
115
+ template: Optional[str]
116
+ js: Optional[str]
117
+ ```
118
+
119
+ ### Built-in Custom Tags
120
+
121
+ See <tab-link component-tab="Markdown">Markdown Built-in Custom Tags</tab-link>
122
+
123
+ ### event listeners
124
+
125
+ | Event | Description |
126
+ | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
127
+ | `mgr.Chatbot.flushed(fn, ···)` | Triggered when the typewriter effect ends. EventData is: <br/> - index: The index tuple of the current message.<br/> - value: The current message value. |
128
+ | `mgr.Chatbot.custom(fn, ···)` | Triggered when a custom tag event occurs. EventData is: <br/> - index: The index tuple of the previous message.<br/> - tag: The current tag that triggered the event.<br/> - tag_index: The index of the current triggered tag, re-calculated based on the index tuple of the message.<br/> - value: The custom value passed in. |
components/{antd/affix → Chatbot}/app.py RENAMED
@@ -1,4 +1,4 @@
1
- from helper.Docs import Docs
2
 
3
  docs = Docs(__file__)
4
 
 
1
+ from components.Docs import Docs
2
 
3
  docs = Docs(__file__)
4
 
components/Chatbot/demos/.DS_Store ADDED
Binary file (6.15 kB). View file
 
components/Chatbot/demos/accordion.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import gradio as gr
4
+ import modelscope_studio as mgr
5
+ from modelscope_studio.components.Chatbot.llm_thinking_presets import qwen
6
+
7
+
8
+ def resolve_assets(relative_path):
9
+ return os.path.join(os.path.dirname(__file__), "../resources",
10
+ relative_path)
11
+
12
+
13
+ conversation = [
14
+ [
15
+ None, {
16
+ "text": f"""
17
+ Use accordion tag:
18
+ <accordion title="Using tool">
19
+
20
+ ```json
21
+ {{"text": "glorious weather", "resolution": "1024*1024"}}
22
+ ```
23
+ </accordion>
24
+
25
+ Qwen preset:
26
+ Action: image_gen
27
+ Action Input: {{"text": "glorious weather", "resolution": "1024*1024"}}
28
+ Observation: <result>![IMAGEGEN]({resolve_assets("screen.jpeg")})</result> Based on your description"glorious weather",I generated a picture.![]({resolve_assets("screen.jpeg")})
29
+
30
+ Action: 「An arbitrary text representation that will be displayed as the name of the thought chain call」
31
+ Action Input: 「Any json or md content will be displayed in the drop-down box of the calling process」
32
+ Observation: <result>「Any md content will be displayed in the drop-down box when the call is completed」</result>
33
+ """,
34
+ "flushing": False
35
+ }
36
+ ],
37
+ ]
38
+
39
+ with gr.Blocks() as demo:
40
+ mgr.Chatbot(
41
+ value=conversation,
42
+ llm_thinking_presets=[qwen()],
43
+ height=600,
44
+ )
45
+
46
+ if __name__ == "__main__":
47
+ demo.queue().launch()
components/Chatbot/demos/basic.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+
4
+ import gradio as gr
5
+ import modelscope_studio as mgr
6
+
7
+ conversation = [
8
+ [
9
+ None,
10
+ {
11
+ # The first message of bot closes the typewriter.
12
+ "text": "Hello I'm a chatbot",
13
+ "flushing": False
14
+ }
15
+ ],
16
+ ]
17
+
18
+
19
+ def submit(_input, _chatbot):
20
+ _chatbot.append([_input, None])
21
+ yield gr.update(interactive=False, value=None), _chatbot
22
+ time.sleep(2)
23
+ _chatbot[-1][1] = {"text": _input.text + '!'}
24
+ yield {
25
+ chatbot: _chatbot,
26
+ }
27
+
28
+
29
+ def flushed():
30
+ return gr.update(interactive=True)
31
+
32
+
33
+ with gr.Blocks() as demo:
34
+ chatbot = mgr.Chatbot(
35
+ value=conversation,
36
+ avatar_images=[
37
+ os.path.join(os.path.dirname(__file__), "../resources/user.jpeg"),
38
+ {
39
+ "name":
40
+ "bot",
41
+ "avatar":
42
+ os.path.join(os.path.dirname(__file__),
43
+ "../resources/bot.jpeg")
44
+ }
45
+ ],
46
+ height=600,
47
+ )
48
+
49
+ input = mgr.MultimodalInput()
50
+ input.submit(fn=submit, inputs=[input, chatbot], outputs=[input, chatbot])
51
+ chatbot.flushed(fn=flushed, outputs=[input])
52
+
53
+ if __name__ == "__main__":
54
+ demo.queue().launch()
components/Chatbot/demos/message_config.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+
3
+ import gradio as gr
4
+ import modelscope_studio as mgr
5
+
6
+
7
+ def submit(_chatbot):
8
+ _chatbot.append(["test user",
9
+ "test bot"]) # bot starts the typewriter by default
10
+ yield _chatbot
11
+ time.sleep(2)
12
+ _chatbot.append(["test user", {
13
+ "text": "test bot",
14
+ "flushing": False
15
+ }]) # both start the typewriter
16
+ yield _chatbot
17
+ time.sleep(2)
18
+ _chatbot.append([{
19
+ "text": "test user",
20
+ "flushing": True
21
+ }, {
22
+ "text": "test bot",
23
+ "flushing": False
24
+ }]) # user starts the typewriter
25
+ yield _chatbot
26
+
27
+
28
+ with gr.Blocks() as demo:
29
+ chatbot = mgr.Chatbot(height=600, )
30
+ button = gr.Button("Submit")
31
+ button.click(fn=submit, inputs=[chatbot], outputs=[chatbot])
32
+
33
+ if __name__ == "__main__":
34
+ demo.queue().launch()
components/Chatbot/demos/multi_bots.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+
4
+ import gradio as gr
5
+ import modelscope_studio as mgr
6
+
7
+
8
+ def resolve_assets(relative_path):
9
+ return os.path.join(os.path.dirname(__file__), "../resources",
10
+ relative_path)
11
+
12
+
13
+ conversation = [
14
+ [None, {
15
+ "text": "Hello I'm a chatbot",
16
+ "flushing": False
17
+ }],
18
+ ]
19
+
20
+
21
+ def get_last_bot_message(chatbot):
22
+ return chatbot[-1][1]
23
+
24
+
25
+ def create_music_bot_message(text: str):
26
+ return {
27
+ "text": text,
28
+ }
29
+
30
+
31
+ def create_image_bot_message(text: str):
32
+ return {
33
+ "text": text,
34
+ }
35
+
36
+
37
+ def submit(_input, _chatbot):
38
+ _chatbot.append([_input, None])
39
+ yield gr.update(interactive=False, value=None), _chatbot
40
+ _chatbot[-1][1] = [
41
+ "Hello",
42
+ create_image_bot_message("Hello"),
43
+ create_music_bot_message("Hello")
44
+ ]
45
+
46
+ time.sleep(2)
47
+ get_last_bot_message(_chatbot)[1][
48
+ "text"] = f"""Hello, I\'m a image bot\n![image]({resolve_assets("user.jpeg")})"""
49
+ get_last_bot_message(_chatbot)[2][
50
+ "text"] = f"""Hello, I\'m a music bot <audio src="{resolve_assets("audio.wav")}"></audio>"""
51
+ yield {
52
+ chatbot: _chatbot,
53
+ }
54
+
55
+
56
+ def flushed():
57
+ return gr.update(interactive=True)
58
+
59
+
60
+ with gr.Blocks() as demo:
61
+ chatbot = mgr.Chatbot(
62
+ value=conversation,
63
+ avatar_image_width=40,
64
+ avatar_images=[
65
+ resolve_assets('user.jpeg'),
66
+ # default bot avatar and name
67
+ [{
68
+ "name": "bot",
69
+ "avatar": resolve_assets('bot.jpeg')
70
+ }, {
71
+ "name": "image bot",
72
+ "avatar": resolve_assets('image-bot.jpeg')
73
+ }, {
74
+ "name": "music bot",
75
+ "avatar": resolve_assets('music-bot.jpeg')
76
+ }]
77
+ ],
78
+ height=600,
79
+ )
80
+
81
+ input = mgr.MultimodalInput()
82
+ input.submit(fn=submit, inputs=[input, chatbot], outputs=[input, chatbot])
83
+ chatbot.flushed(fn=flushed, outputs=[input])
84
+
85
+ if __name__ == "__main__":
86
+ demo.queue().launch()
components/Chatbot/demos/multimodal.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import gradio as gr
4
+ import modelscope_studio as mgr
5
+
6
+
7
+ def resolve_assets(relative_path):
8
+ return os.path.join(os.path.dirname(__file__), "../resources",
9
+ relative_path)
10
+
11
+
12
+ conversation = [
13
+ [
14
+ None, {
15
+ "text": f"""
16
+ Image
17
+
18
+ ![image]({resolve_assets("bot.jpeg")})
19
+
20
+ <img src="{resolve_assets("user.jpeg")}" />
21
+
22
+ Video
23
+
24
+ <video src="{resolve_assets("dog.mp4")}"></video>
25
+
26
+ Audio
27
+
28
+ <audio src="{resolve_assets("audio.wav")}"></audio>
29
+ """,
30
+ "flushing": False
31
+ }
32
+ ],
33
+ ]
34
+
35
+ with gr.Blocks() as demo:
36
+ mgr.Chatbot(
37
+ value=conversation,
38
+ height=600,
39
+ )
40
+
41
+ if __name__ == "__main__":
42
+ demo.queue().launch()
components/Chatbot/demos/select-box.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ import gradio as gr
4
+ import modelscope_studio as mgr
5
+
6
+ # `label` will display on the page, and `value` is the actual selected value.
7
+ options = [{"label": "A", "value": "a"}, "b", "c"]
8
+
9
+ conversation = [[
10
+ None, f"""
11
+ Single Select: <select-box options='{json.dumps(options)}' select-once></select-box>
12
+
13
+ Multiple Select:<select-box type="checkbox" options='{json.dumps(options)}' select-once submit-text="Submit"></select-box>
14
+
15
+ Vertical Direction:
16
+
17
+ <select-box direction="vertical" type="checkbox" options='{json.dumps(options)}' select-once submit-text="Submit"></select-box>
18
+
19
+ Card Shape:
20
+
21
+ <select-box shape="card" options='{json.dumps(options)}' select-once equal-height></select-box>
22
+
23
+
24
+ <select-box shape="card" columns="2" options='{json.dumps(options)}' select-once equal-height></select-box>
25
+
26
+
27
+ <select-box shape="card" direction="vertical" options='{json.dumps(options)}' select-once equal-height></select-box>
28
+ """
29
+ ]]
30
+
31
+
32
+ # The custom data must be marked by `gr.EventData`
33
+ def fn(data: gr.EventData):
34
+ print(data._data)
35
+
36
+
37
+ with gr.Blocks() as demo:
38
+ chatbot = mgr.Chatbot(
39
+ value=conversation,
40
+ flushing=False,
41
+ height=600,
42
+ )
43
+ # All custom tags will trigger the custom event
44
+ chatbot.custom(fn=fn)
45
+
46
+ if __name__ == "__main__":
47
+ demo.queue().launch()
components/Chatbot/resources/audio.wav ADDED
Binary file (44.8 kB). View file
 
components/Chatbot/resources/bot.jpeg ADDED
components/Chatbot/resources/custom_components/custom_select.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (props, cc, { el, onMount }) => {
2
+ const options = JSON.parse(props.options);
3
+ el.innerHTML = `
4
+ ${options
5
+ .map((option) => {
6
+ return `<div>
7
+ <label>${option} <input type="radio"/></label>
8
+ <div>`;
9
+ })
10
+ .join('')}
11
+ `;
12
+ onMount(() => {
13
+ const inputs = Array.from(el.getElementsByTagName('input'));
14
+ Array.from(el.getElementsByTagName('label')).forEach((label, i) => {
15
+ label.addEventListener('click', () => {
16
+ inputs.forEach((input) => {
17
+ input.checked = false;
18
+ });
19
+ const input = label.getElementsByTagName('input')[0];
20
+ input.checked = true;
21
+ // Use cc.dispatch to trigger events.
22
+ cc.dispatch(options[i]);
23
+ });
24
+ });
25
+ });
26
+ };
components/Chatbot/resources/dog.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:39d086ce29e48cf76e5042d2f3f0611ee46575f70fa3dc0c40dd4cfffde3d933
3
+ size 8626383
components/Chatbot/resources/image-bot.jpeg ADDED
components/Chatbot/resources/music-bot.jpeg ADDED
components/{pro/chatbot/resources/scenery.jpeg → Chatbot/resources/screen.jpeg} RENAMED
File without changes
components/Chatbot/resources/user.jpeg ADDED
components/Docs.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ from typing import Callable
4
+
5
+ import gradio as gr
6
+ import modelscope_studio as mgr
7
+
8
+ from .parse_markdown import parse_markdown
9
+
10
+ with open(os.path.join(os.path.dirname(__file__), "tab-link.js")) as f:
11
+ tab_link_js = f.read()
12
+
13
+ custom_components = {
14
+ "tab-link": {
15
+ "props": ["tab", "component-tab"],
16
+ "js": tab_link_js
17
+ }
18
+ }
19
+
20
+
21
+ def remove_formatter(markdown_text):
22
+ pattern = r"^ *---[\s\S]*?---"
23
+
24
+ replaced_text = re.sub(pattern, "", markdown_text)
25
+
26
+ return replaced_text
27
+
28
+
29
+ def list_demos(dir_path: str, prefix=''):
30
+ result = []
31
+ if (not os.path.isdir(dir_path)):
32
+ return result
33
+ for name in os.listdir(dir_path):
34
+ path = os.path.join(dir_path, name)
35
+
36
+ if os.path.isfile(path):
37
+ result.append(prefix + name)
38
+ elif os.path.isdir(path):
39
+ sub_prefix = prefix + name + '/'
40
+ result.extend(list_demos(path, sub_prefix))
41
+
42
+ return result
43
+
44
+
45
+ def get_demo_modules(file_path: str):
46
+ import importlib.util
47
+
48
+ demos = [
49
+ demo for demo in list_demos(
50
+ os.path.join(os.path.dirname(file_path), "demos"))
51
+ if demo.endswith(".py")
52
+ ]
53
+ demo_modules = {}
54
+ for demo in demos:
55
+ demo_name = demo.split(".")[0]
56
+ spec = importlib.util.spec_from_file_location(
57
+ "demo", os.path.join(os.path.dirname(file_path), "demos", demo))
58
+ module = importlib.util.module_from_spec(spec)
59
+ spec.loader.exec_module(module)
60
+ demo_modules[demo_name] = module
61
+ return demo_modules
62
+
63
+
64
+ is_modelscope_studio = os.getenv('MODELSCOPE_ENVIRONMENT') == 'studio'
65
+
66
+
67
+ class Docs:
68
+
69
+ def __init__(self, file_path: str, markdown_files: list = None):
70
+ self.file_path = file_path
71
+ self.demo_modules = get_demo_modules(file_path)
72
+ # default current directory
73
+ self.markdown_files = markdown_files if markdown_files else [
74
+ filename for filename in os.listdir(os.path.dirname(file_path))
75
+ if filename.endswith(".md")
76
+ ]
77
+ if is_modelscope_studio:
78
+ self.markdown_files = list(
79
+ filter(
80
+ lambda x: x.endswith("-zh_CN.md") or
81
+ (f"{'.'.join(x.split('.')[:-1])}-zh_CN.md" not in self.
82
+ markdown_files), self.markdown_files))
83
+ else:
84
+ self.markdown_files = list(
85
+ filter(lambda x: not x.endswith("-zh_CN.md"),
86
+ self.markdown_files))
87
+
88
+ self.tabs = None
89
+
90
+ def read_file(self, relative_path: str):
91
+ with open(os.path.join(os.path.dirname(self.file_path), relative_path),
92
+ "r") as f:
93
+ return f.read()
94
+
95
+ def render_demo(self, demo_name, prefix='', suffix=''):
96
+ content = self.read_file(f"./demos/{demo_name}.py")
97
+ module = self.demo_modules[demo_name]
98
+ with gr.Accordion("Show Demo", open=False):
99
+ with gr.Row():
100
+ with gr.Column():
101
+ mgr.Markdown(f"""
102
+ {prefix}
103
+ ````python
104
+ {content}
105
+ ````
106
+ {suffix}
107
+ """,
108
+ header_links=True,
109
+ custom_components=custom_components)
110
+ with gr.Column():
111
+ module.demo.render()
112
+
113
+ def render_markdown(self,
114
+ markdown_file,
115
+ on_tab_link_click: Callable = None,
116
+ components_tabs=None):
117
+ items = parse_markdown(remove_formatter(self.read_file(markdown_file)),
118
+ read_file=self.read_file)
119
+ for item in items:
120
+ if item["type"] == "text":
121
+ md = mgr.Markdown(item["value"],
122
+ header_links=True,
123
+ custom_components=custom_components)
124
+ deps = [dep for dep in [components_tabs, self.tabs] if dep]
125
+ if len(deps) > 0:
126
+ md.custom(fn=on_tab_link_click, outputs=deps)
127
+ elif item["type"] == "demo":
128
+ self.render_demo(item["name"],
129
+ prefix=item["prefix"],
130
+ suffix=item["suffix"])
131
+
132
+ def render(self, components_tabs=None):
133
+
134
+ def tab_link_click(data: gr.EventData):
135
+ tab: str = data._data["value"].get("tab", '')
136
+ component_tab: str = data._data["value"].get("component_tab", '')
137
+ if tab and tabs:
138
+ return {tabs: gr.update(selected=tab)}
139
+ elif components_tabs and component_tab:
140
+ return {components_tabs: gr.update(selected=component_tab)}
141
+
142
+ with gr.Blocks() as demo:
143
+
144
+ if len(self.markdown_files) > 1:
145
+ with gr.Tabs() as tabs:
146
+ self.tabs = tabs
147
+
148
+ for markdown_file in self.markdown_files:
149
+ tab_name = ".".join(markdown_file.split(".")[:-1])
150
+ tab_name = tab_name.split("-zh_CN")[0]
151
+ with gr.TabItem(tab_name, id=tab_name):
152
+ self.render_markdown(
153
+ markdown_file,
154
+ on_tab_link_click=tab_link_click,
155
+ components_tabs=components_tabs)
156
+ elif (len(self.markdown_files) == 1):
157
+ self.render_markdown(self.markdown_files[0],
158
+ on_tab_link_click=tab_link_click,
159
+ components_tabs=components_tabs)
160
+ return demo
components/Markdown/README-zh_CN.md ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Markdown
2
+
3
+ 升级版的 gradio Markdown。
4
+
5
+ - 支持输出多模态内容(音频、视频、语音、文件、文本)
6
+ - 支持自定义渲染组件,并与 Python 侧事件交互
7
+
8
+ ## 如何使用
9
+
10
+ ### 基本使用
11
+
12
+ <demo name="basic"></demo>
13
+
14
+ ### 多模态 & 支持本地文件的展示
15
+
16
+ <demo name="multimodal"></demo>
17
+
18
+ ### 支持手风琴内容展示
19
+
20
+ 在返回的内容中加入 `accordion` 标签,更多用法详见 <tab-link tab="custom_tags/accordion">accordion</tab-link>
21
+
22
+ <demo name="accordion"></demo>
23
+
24
+ ### 支持用户选择交互
25
+
26
+ 在返回的内容中加入 `select-box` 标签,更多用法详见 <tab-link tab="custom_tags/select-box">select-box</tab-link>
27
+
28
+ <demo name="select-box"></demo>
29
+
30
+ ### 自定义标签(高阶用法,需要了解前端知识)
31
+
32
+ <demo name="custom-tag"></demo>
33
+
34
+ #### 引入 js
35
+
36
+ <demo name="custom-tag2"></demo>
37
+
38
+ template只能做简单的变量替换,如果想要引入更多自定义的行为,如条件判断、循环渲染等,请使用 js 控制 el 自行处理,下面是简单的示例:
39
+
40
+ <demo name="custom-tag3">
41
+ <demo-suffix>
42
+ custom_select.js
43
+
44
+ ```js
45
+ <file src="./resources/custom_components/custom_select.js"></file>
46
+ ```
47
+
48
+ </demo-suffix>
49
+ </demo>
50
+
51
+ #### 与 Python 侧交互
52
+
53
+ 在 js 中可以使用`cc.dispatch`触发 Python 侧监听的`custom`事件,以前面的custom_select.js为例,我们在前端调用了`cc.dispatch(options[i])`,则会向 Python 侧同时发送通知。
54
+
55
+ <demo name="custom-tag4"></demo>
56
+
57
+ ## API 及参数列表
58
+
59
+ 以下 API 均为在原有 gradio Markdown 外的额外拓展参数。
60
+
61
+ ### props
62
+
63
+ | 属性 | 类型 | 默认值 | 描述 |
64
+ | ----------------- | --------------------------------------------------------------- | ------ | --------------------------------------------------------------------------- |
65
+ | enable_base64 | bool | False | 是否支持渲染的内容为 base64,因为直接渲染 base64 有安全问题,默认为 False。 |
66
+ | preview | bool | True | 是否开启图片预览功能 |
67
+ | custom_components | dict\[str, CustomComponentDict\] CustomComponentDict 定义见下方 | None | 支持用户定义自定义标签,并通过 js 控制标签渲染样式与触发 python 事件。 |
68
+
69
+ **CustomComponent 定义如下**
70
+
71
+ ```python
72
+ class CustomComponentDict(TypedDict):
73
+ props: Optional[List[str]]
74
+ template: Optional[str]
75
+ js: Optional[str]
76
+ ```
77
+
78
+ ### 内置的自定义标签
79
+
80
+ - <tab-link tab="custom_tags/select-box">select-box</tab-link>
81
+ - <tab-link tab="custom_tags/accordion">accordion</tab-link>
82
+
83
+ ### event listeners
84
+
85
+ | 事件 | 描述 |
86
+ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
87
+ | `mgr.Markdown.custom(fn, ···)` | 自定义标签触发事件时触发,EventData 为:<br/> - index:当前 message 的 index tuple ([message index, user group(index 0) or bot group(index 1), user/bot group index])。<br/> - tag:当前触发的标签。<br/> - tag_index:当前触发标签的 index,此 index 在 mesage 的 index tuple 基础上重新计算。<br/> - value:自定义传入的值。 |
components/Markdown/README.md ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Markdown
2
+
3
+ Upgraded gradio Markdown.
4
+
5
+ - Supports output of multimodal content (audio, video, voice, files, text)
6
+ - Supports custom rendering components and interaction with Python-side events
7
+
8
+ ## How to Use
9
+
10
+ ### Basic Usage
11
+
12
+ <demo name="basic"></demo>
13
+
14
+ ### Multimodal & Support for Local File Display
15
+
16
+ <demo name="multimodal"></demo>
17
+
18
+ ### Support for Accordion Content Display
19
+
20
+ Include the `accordion` tag in the returned content for more usage details, see <tab-link tab="custom_tags/accordion">accordion</tab-link>
21
+ <demo name="accordion"></demo>
22
+
23
+ ### Support for User Selection Interaction
24
+
25
+ Include the `select-box` tag in the returned content for more usage details, see <tab-link tab="custom_tags/select-box">select-box</tab-link>
26
+ <demo name="select-box"></demo>
27
+
28
+ ### Custom Tags (Advanced Usage, Requires Frontend Knowledge)
29
+
30
+ <demo name="custom-tag"></demo>
31
+
32
+ #### Importing js
33
+
34
+ <demo name="custom-tag2"></demo>
35
+ The template can only perform simple variable replacements. If you want to introduce more custom behaviors, such as conditional judgments, loop rendering, etc., please use js to control the element for processing. Here is a simple example:
36
+ <demo name="custom-tag3">
37
+ <demo-suffix>
38
+ custom_select.js
39
+
40
+ ```js
41
+ <file src="./resources/custom_components/custom_select.js"></file>
42
+ ```
43
+
44
+ </demo-suffix>
45
+ </demo>
46
+
47
+ #### Interaction with Python Side
48
+
49
+ In js, you can use `cc.dispatch` to trigger the `custom` event listened to on the Python side. Taking the previous custom_select.js as an example, when we call `cc.dispatch(options[i])` on the frontend, a notification will be sent to the Python side simultaneously.
50
+ <demo name="custom-tag4"></demo>
51
+
52
+ ## API and Parameter List
53
+
54
+ The following APIs are additional extended parameters beyond the original gradio Markdown.
55
+
56
+ ### props
57
+
58
+ | Attribute | Type | Default Value | Description |
59
+ | ----------------- | ------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------- |
60
+ | enable_base64 | bool | False | Whether to support rendering content as base64, since rendering base64 directly can pose security issues, the default is False. |
61
+ | preview | bool | True | Whether to enable image preview functionality. |
62
+ | custom_components | dict[str, CustomComponentDict] CustomComponentDict definition below | None | Supports user-defined custom tags and controls tag rendering styles and triggers Python events through js. |
63
+ | |
64
+
65
+ **CustomComponent definition is as follows:**
66
+
67
+ ```python
68
+ class CustomComponentDict(TypedDict):
69
+ props: Optional[List[str]]
70
+ template: Optional[str]
71
+ js: Optional[str]
72
+ ```
73
+
74
+ ### Built-in Custom Tags
75
+
76
+ - <tab-link tab="custom_tags/select-box">select-box</tab-link>
77
+ - <tab-link tab="custom_tags/accordion">accordion</tab-link>
78
+
79
+ ### Event Listeners
80
+
81
+ | Event | Description |
82
+ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
83
+ | `mgr.Markdown.custom(fn, ···)` | Triggered when a custom tag event occurs. EventData is: <br/> - index: The index tuple of the current message ([message index, user group(index 0) or bot group(index 1), user/bot group index]).<br/> - tag: The current tag that triggered the event.<br/> - tag_index: The index of the current triggered tag, re-calculated based on the message’s index tuple.<br/> - value: The custom value passed in. |
components/Markdown/app.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from components.Docs import Docs
4
+
5
+
6
+ def resolve(relative_path: str):
7
+ return os.path.join(os.path.dirname(__file__), relative_path)
8
+
9
+
10
+ docs = Docs(
11
+ __file__,
12
+ markdown_files=(["README.md", "README-zh_CN.md"] + [
13
+ f"custom_tags/{filename}"
14
+ for filename in os.listdir(resolve('custom_tags'))
15
+ if filename.endswith(".md")
16
+ ]),
17
+ )
18
+
19
+ if __name__ == "__main__":
20
+ docs.render().queue().launch()
components/Markdown/custom_tags/accordion-zh_CN.md ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # accordion
2
+
3
+ 在 markdown 文本中添加手风琴效果。
4
+
5
+ ## 如何使用
6
+
7
+ ### 基本使用
8
+
9
+ <demo name="custom_tags/accordion/basic"></demo>
10
+
11
+ ### 使用 accordion-title 标记
12
+
13
+ 使用`::accordion-title[content]`的形式可以在标题输入 markdown 文本。
14
+
15
+ <demo name="custom_tags/accordion/accordion-title"></demo>
16
+
17
+ ## API 及参数列表
18
+
19
+ ### props
20
+
21
+ | 属性 | 类型 | 默认值 | 描述 |
22
+ | ----- | ------ | ------ | ------------ |
23
+ | title | string | | 手风琴的标题 |
components/Markdown/custom_tags/accordion.md ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # accordion
2
+
3
+ Add an accordion effect to markdown text.
4
+
5
+ ## How to Use
6
+
7
+ ### Basic Usage
8
+
9
+ <demo name="custom_tags/accordion/basic"></demo>
10
+
11
+ ### Using the accordion-title Marker
12
+
13
+ Using the form `::accordion-title[content]`, you can input markdown text into the title.
14
+ <demo name="custom_tags/accordion/accordion-title"></demo>
15
+
16
+ ## API and Parameter List
17
+
18
+ ### props
19
+
20
+ | Attribute | Type | Default Value | Description |
21
+ | --------- | ------ | ------------- | -------------------------- |
22
+ | title | string | | The title of the accordion |
components/{pro/web_sandbox/README-zh_CN.md → Markdown/custom_tags/select-box-zh_CN.md} RENAMED
@@ -1,69 +1,45 @@
1
- # WebSandbox
2
 
3
- 前端代码沙箱组件,能够将`React`或`HTML`类型的前端代码页面编译并预览
4
 
5
- ## 示例
6
 
7
- ### 预览 React 代码
8
 
9
- 当`template`为`react`时,会自动在`imports`参数中添加以下依赖,当需要特定的某个 React 版本时,可以通过覆盖对应的 key 进行修改:
10
 
11
- ```json
12
- {
13
- "react": "https://esm.sh/react",
14
- "react/": "https://esm.sh/react/",
15
- "react-dom": "https://esm.sh/react-dom",
16
- "react-dom/": "https://esm.sh/react-dom/"
17
- }
18
- ```
19
 
20
- <demo name="react"></demo>
21
 
22
- ### 预览 HTML 代码
23
 
24
- <demo name="html"></demo>
25
 
26
- ### 自定义 Sandbox 事件
27
 
28
- <demo name="custom_sandbox_event"></demo>
29
 
30
- ### 处理错误
31
 
32
- <demo name="error_handling"></demo>
33
 
34
- ## API 
35
 
36
- ### 属性
37
 
38
- | 属性 | 类型 | 默认值 | 描述 |
39
- | -------------------- | ---------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
- | value | `Dict[str, Union[str, SandboxFileData]]` | None | 传入 Sandbox 的文件集合。当`template`为`react`时,`['index.tsx', 'index.jsx', 'index.ts', 'index.js']` 默认的入口文件,当`template`为`html`时,`['index.html']` 默认的入口文件你也可以通过对象的形式填写`is_entry`属性手动指定入口文件。 |
41
- | template | `Literal['react', 'html']` | 'react' | Sandbox 渲染的模板类型 |
42
- | show_render_error | `bool` | True | 是否抛出渲染错误提示 |
43
- | show_compile_error | `bool` | True | 是否展示编译失败样式。 |
44
- | compile_error_render | `str \| None` | None | 自定义编译失败样式,传入类型为 Javascript 的函数字符串。 |
45
- | imports | `Dict[str, str]` | None | 对应 importmap 中的 imports 字段,见 [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap),可于添加在线前端依赖模块。 `template` 为 `react` 时会自动添加以下依赖,需要特定的某个 React 版本可以通过覆盖对应的 key 进行修改: `{ "react": "https://esm.sh/react", "react/": "https://esm.sh/react/", "react-dom": "https://esm.sh/react-dom", "react-dom/": "https://esm.sh/react-dom/" }` |
46
- | height | `str \| float \| int` | 400 | 组件的高度,如果值为数字,则以像素为单位指定,如果传递的字符串,则以 CSS 单位指定。 |
47
-
48
- ### 事件
49
-
50
- | 事件 | 描述 |
51
- | ----------------------------------------- | ------------------------------------------------------------------------------------------- |
52
- | `pro.WebSandbox.compile_success(fn, ···)` | Sandbox 编译成功触发 |
53
- | `pro.WebSandbox.compile_error(fn, ···)` | 当 Sandbox 编译失败时触发。 |
54
- | `pro.WebSandbox.render_error(fn, ···)` | 当 Sandbox 渲染抛错时触发。 |
55
- | `pro.WebSandbox.custom(fn, ···)` | 在 Sandbox 内触发的自定义事件,在 Sandbox 内通过 JavaScript 调用 `window.dispatch` 时触发。 |
56
-
57
- ### 插槽
58
-
59
- ```python
60
- SLOTS=['compileErrorRender']
61
- ```
62
-
63
- ### 类型
64
-
65
- ```python
66
- class SandboxFileData(TypedDict):
67
- code: str
68
- is_entry: Optional[bool]
69
- ```
 
1
+ # select-box
2
 
3
+ markdown 文本中添加选择交互框
4
 
5
+ ## 如何使用
6
 
7
+ ### 基本使用
8
 
9
+ <demo name="custom_tags/select-box/basic"></demo>
10
 
11
+ ### Card 样式
 
 
 
 
 
 
 
12
 
13
+ <demo name="custom_tags/select-box/card_shape"></demo>
14
 
15
+ ### Card 自适应内部元素宽度
16
 
17
+ <demo name="custom_tags/select-box/card_shape_width_auto"></demo>
18
 
19
+ ### 监听 Python 事件
20
 
21
+ <demo name="custom_tags/select-box/python_events"></demo>
22
 
23
+ ## API 及参数列表
24
 
25
+ ### value
26
 
27
+ custom 事件中 custom_data value 对应值, 返回值为用户 options 传入的对应 value ,如果type="checkbox",则返回一个 list。
28
 
29
+ ### props
30
 
31
+ | 属性 | 类型 | 默认值 | 描述 |
32
+ | ------------ | ------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
33
+ | type | 'checkbox' \| 'radio' | 'radio' | 选择框类型,'radio' 单选框、'checkbox'为多选框 |
34
+ | disabled | boolean | | 禁用选择,通常在需要读取历史信息二次渲染时会用到 |
35
+ | value | string | | 默认选中值,通常适用于`type="checkbox"`时提前为用户选择部分选项和设置`disabled`后的默认值渲染。 |
36
+ | direction |  'horizontal' \| 'vertical' | 'horizontal' | 横向或竖向排列选择框 |
37
+ | shape | 'card' \| 'default' | 'default' | 选择框样式 |
38
+ | options | (string\{ label?: string, value?: string, imgSrc?: string})\[\] | | 为户提供选项值,每一项可以为 string 或 object。 值为 object 时可以接收更多自定义值,其中imgSrc只有当shape="card"时才生效 |
39
+ | select-once | boolean | false | 是否只允许用户选择一次 |
40
+ | submit-text | string | | 提交按钮的展示值,当该属性有值时,会展示提交按钮,此时用户只有点击提交按钮后才会触发选择事件。 |
41
+ | columns | number \| { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } | { xs: 1, sm:  2, md: 2, lg:  4} | 当shape="card"时才生效。每一行选项占用列数,值的范围为1 - 24,建议此项取值可以被 24 整除,否则可能列数会不符合预期。 当此项传入值为对象时,可以响应式控制每一行渲染列数,响应阈值如下:<br/> - xs:屏幕 < 576px <br/> - sm:屏幕 ≥ 576px <br/> - md:屏幕 ≥ 768px <br/> - lg:屏幕 ≥ 992px <br/> - xl:屏幕 ≥ 1200px <br/> - xxl:屏幕 ≥ 1600px 当direction为vertical时此配置不生效。 |
42
+ | item-width | string | | 当shape="card"时才生效。每个选项的宽度,如:'auto'、'100px',默认使用 columns 自动分配的宽度。 |
43
+ | item-height | string | | 当shape="card"时才生效。每个选项的高度,默认自适应元素高度。 |
44
+ | img-height | string | '160px' | 当shape="card"时才生效。每个选项中图片的高度。 |
45
+ | equal-height | boolean | false | 当shape="card"才生效是否每一行的选项高度都相等,会使用高度最高的选项。 |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/Markdown/custom_tags/select-box.md ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # select-box
2
+
3
+ Add a selection interaction box to markdown text.
4
+
5
+ ## How to Use
6
+
7
+ ### Basic Usage
8
+
9
+ <demo name="custom_tags/select-box/basic"></demo>
10
+
11
+ ### Card Style
12
+
13
+ <demo name="custom_tags/select-box/card_shape"></demo>
14
+
15
+ ### Card Adapts to Width of Inner Elements
16
+
17
+ <demo name="custom_tags/select-box/card_shape_width_auto"></demo>
18
+
19
+ ### Listening to Python Events
20
+
21
+ <demo name="custom_tags/select-box/python_events"></demo>
22
+
23
+ ## API and Parameter List
24
+
25
+ ### value
26
+
27
+ The corresponding value of custom_data value in the custom event; returns the user's inputted value for options. If type="checkbox", it returns a list.
28
+
29
+ ### props
30
+
31
+ | Attribute | Type | Default Value | Description |
32
+ | ------------ | ------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
33
+ | type | 'checkbox' \| 'radio' | 'radio' | The type of selection box: 'radio' for radio buttons, 'checkbox' for checkboxes. |
34
+ | disabled | boolean | | Disable the selection, usually used when reading historical information for re-rendering. |
35
+ | value | string | | The default selected value, usually used to pre-select some options for the user when `type="checkbox"` and to set the default value for rendering after setting `disabled`. |
36
+ | direction | 'horizontal' \| 'vertical' | 'horizontal' | Arrange selection boxes horizontally or vertically. |
37
+ | shape | 'card' \| 'default' | 'default' | The style of the selection box. |
38
+ | options | (string \| { label?: string, value?: string, imgSrc?: string })[] | | The options provided to the user, each item can be a string or an object. When the value is an object, it can accept more custom values, where imgSrc only takes effect when shape="card". |
39
+ | select-once | boolean | false | Whether to allow the user to make a selection only once. |
40
+ | submit-text | string | | The display value of the submit button. When this attribute has a value, the submit button will be displayed, and the selection event will only be triggered after the user clicks the submit button. |
41
+ | columns | number \| { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } | { xs: 1, sm: 2, md: 2, lg: 4 } | Effective only when shape="card". The number of columns each row of options occupies, the value range is 1 - 24, it is recommended that this value is divisible by 24, otherwise, the number of columns may not meet expectations. When this item is passed as an object, it can responsively control the number of rendered columns per row, responsive thresholds are as follows: <br/> - xs: screen < 576px <br/> - sm: screen ≥ 576px <br/> - md: screen ≥ 768px <br/> - lg: screen ≥ 992px <br/> - xl: screen ≥ 1200px <br/> - xxl: screen ≥ 1600px This configuration does not take effect when direction is vertical. |
42
+ | item-width | string | | Effective only when shape="card". The width of each option, such as: 'auto', '100px', the default uses the width automatically allocated by columns. |
43
+ | item-height | string | | Effective only when shape="card". The height of each option, defaults to adapt to the height of the element. |
44
+ | img-height | string | '160px' | Effective only when shape="card". The height of the images within each option. |
45
+ | equal-height | boolean | false | Effective only when shape="card". Whether the height of the options in each row should be equal, using the height of the tallest option. |
components/Markdown/demos/accordion.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import modelscope_studio as mgr
3
+
4
+ with gr.Blocks() as demo:
5
+ mgr.Markdown(f"""
6
+ <accordion title="Using tool">
7
+
8
+ ```json
9
+ {{"text": "glorious weather", "resolution": "1024*1024"}}
10
+ ```
11
+
12
+ </accordion>
13
+
14
+ Use `::accordion-title` to support markdown:
15
+
16
+ <accordion>
17
+
18
+ ::accordion-title[Using `tool`]
19
+
20
+ ```json
21
+ {{"text": "glorious weather", "resolution": "1024*1024"}}
22
+ ```
23
+ </accordion>
24
+ """)
25
+
26
+ if __name__ == "__main__":
27
+ demo.queue().launch()
components/{base/markdown → Markdown}/demos/basic.py RENAMED
@@ -1,9 +1,10 @@
1
  import gradio as gr
2
- import modelscope_studio.components.base as ms
3
 
4
  with gr.Blocks() as demo:
5
- with ms.Application():
6
- ms.Markdown("`Hello Markdown`")
 
7
 
8
  if __name__ == "__main__":
9
  demo.queue().launch()
 
1
  import gradio as gr
2
+ import modelscope_studio as mgr
3
 
4
  with gr.Blocks() as demo:
5
+ mgr.Markdown(
6
+ "This _example_ was **written** in [Markdown](https://en.wikipedia.org/wiki/Markdown)\n"
7
+ )
8
 
9
  if __name__ == "__main__":
10
  demo.queue().launch()
components/Markdown/demos/custom-tag.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import modelscope_studio as mgr
3
+
4
+ with gr.Blocks() as demo:
5
+ mgr.Markdown(
6
+ f"""
7
+ custom tag:<custom-tag value="aaa"></custom-tag>
8
+ """,
9
+ custom_components={
10
+ # Key is the tag name
11
+ "custom-tag": {
12
+ # The tag props.
13
+ "props": ["value"],
14
+ # The tag template, use `{prop}` as placeholder。
15
+ "template": "<div>{value}</div>"
16
+ }
17
+ })
18
+
19
+ if __name__ == "__main__":
20
+ demo.queue().launch()
components/Markdown/demos/custom-tag2.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import modelscope_studio as mgr
3
+
4
+ with gr.Blocks() as demo:
5
+ mgr.Markdown(
6
+ f"""
7
+ custom tag:<custom-tag value="aaa"></custom-tag>
8
+ """,
9
+ custom_components={
10
+ "custom-tag": {
11
+ "props": ["value"],
12
+ "template":
13
+ "<button onclick='{onClick}'>{value}</button>",
14
+ # The `js` property should be a string containing a JavaScript Function.
15
+ "js":
16
+ """
17
+ (props, cc, { el, onMount }) => {
18
+ // `onMount` will be called after the template rendered
19
+ onMount(() => {
20
+ // `el` is the container element
21
+ console.log(el)
22
+ })
23
+ console.log(props.children) // By default, `props` will be passed a property named `children`, which can get the content in the tag, such as 'xx' in '<tag>xx</tag>'.
24
+
25
+ // The return value will be merged with `props` and passed to the template.
26
+ return {
27
+ value: 'Click Me: ' + props.value,
28
+ onClick: () => {
29
+ alert('hello')
30
+ }
31
+ }
32
+ }"""
33
+ }
34
+ })
35
+
36
+ if __name__ == "__main__":
37
+ demo.queue().launch()
components/Markdown/demos/custom-tag3.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+
4
+ import gradio as gr
5
+ import modelscope_studio as mgr
6
+
7
+ options = ["a", "b", "c"]
8
+
9
+
10
+ def resolve_assets(relative_path):
11
+ return os.path.join(os.path.dirname(__file__), "../resources",
12
+ relative_path)
13
+
14
+
15
+ with open(resolve_assets("./custom_components/custom_select.js"), 'r') as f:
16
+ custom_select_js = f.read()
17
+
18
+ with gr.Blocks() as demo:
19
+ mgr.Markdown(value=f"""
20
+ custom tag: <custom-select options='{json.dumps(options)}'></custom-select>
21
+ """,
22
+ custom_components={
23
+ "custom-select": {
24
+ "props": ["options"],
25
+ "js": custom_select_js,
26
+ }
27
+ })
28
+
29
+ if __name__ == "__main__":
30
+ demo.queue().launch()
components/Markdown/demos/custom-tag4.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+
4
+ import gradio as gr
5
+ import modelscope_studio as mgr
6
+
7
+ options = ["a", "b", "c"]
8
+
9
+
10
+ def resolve_assets(relative_path):
11
+ return os.path.join(os.path.dirname(__file__), "../resources",
12
+ relative_path)
13
+
14
+
15
+ with open(resolve_assets("./custom_components/custom_select.js"), 'r') as f:
16
+ custom_select_js = f.read()
17
+
18
+
19
+ def fn(data: gr.EventData):
20
+ # custom {'index': [0, 1, 0], 'tag': 'custom-select', 'tag_index': 0, 'value': 'option A'}
21
+ print("custom value", data._data)
22
+
23
+
24
+ with gr.Blocks() as demo:
25
+ md = mgr.Markdown(value=f"""
26
+ custom tag: <custom-select options='{json.dumps(options)}'></custom-select>
27
+ """,
28
+ custom_components={
29
+ "custom-select": {
30
+ "props": ["options"],
31
+ "js": custom_select_js,
32
+ }
33
+ })
34
+ md.custom(fn=fn)
35
+
36
+ if __name__ == "__main__":
37
+ demo.queue().launch()
components/Markdown/demos/custom_tags/accordion/__pycache__/accordion-title.cpython-39.pyc ADDED
Binary file (549 Bytes). View file
 
components/Markdown/demos/custom_tags/accordion/__pycache__/basic.cpython-39.pyc ADDED
Binary file (525 Bytes). View file
 
components/{base/div/demos/basic.py → Markdown/demos/custom_tags/accordion/accordion-title.py} RENAMED
@@ -1,10 +1,18 @@
1
  import gradio as gr
2
- import modelscope_studio.components.base as ms
3
 
4
  with gr.Blocks() as demo:
5
- with ms.Application():
6
- with ms.Div(elem_style=dict(color="red", fontSize=22)):
7
- ms.Text("Hello Div")
 
 
 
 
 
 
 
 
8
 
9
  if __name__ == "__main__":
10
  demo.queue().launch()
 
1
  import gradio as gr
2
+ import modelscope_studio as mgr
3
 
4
  with gr.Blocks() as demo:
5
+ mgr.Markdown(f"""
6
+ <accordion>
7
+
8
+ ::accordion-title[Using `tool`]
9
+
10
+ ```json
11
+ {{"text": "glorious weather", "resolution": "1024*1024"}}
12
+ ```
13
+
14
+ </accordion>
15
+ """)
16
 
17
  if __name__ == "__main__":
18
  demo.queue().launch()
components/{base/span/demos → Markdown/demos/custom_tags/accordion}/basic.py RENAMED
@@ -1,10 +1,16 @@
1
  import gradio as gr
2
- import modelscope_studio.components.base as ms
3
 
4
  with gr.Blocks() as demo:
5
- with ms.Application():
6
- with ms.Span(elem_style=dict(color="red", fontSize=22)):
7
- ms.Text("Hello Span")
 
 
 
 
 
 
8
 
9
  if __name__ == "__main__":
10
  demo.queue().launch()
 
1
  import gradio as gr
2
+ import modelscope_studio as mgr
3
 
4
  with gr.Blocks() as demo:
5
+ mgr.Markdown(f"""
6
+ <accordion title="Using tool">
7
+
8
+ ```json
9
+ {{"text": "glorious weather", "resolution": "1024*1024"}}
10
+ ```
11
+
12
+ </accordion>
13
+ """)
14
 
15
  if __name__ == "__main__":
16
  demo.queue().launch()
components/Markdown/demos/custom_tags/select-box/__pycache__/basic.cpython-39.pyc ADDED
Binary file (851 Bytes). View file
 
components/Markdown/demos/custom_tags/select-box/__pycache__/card_shape.cpython-39.pyc ADDED
Binary file (980 Bytes). View file
 
components/Markdown/demos/custom_tags/select-box/__pycache__/card_shape_width_auto.cpython-39.pyc ADDED
Binary file (751 Bytes). View file
 
components/Markdown/demos/custom_tags/select-box/__pycache__/python_events.cpython-39.pyc ADDED
Binary file (804 Bytes). View file
 
components/Markdown/demos/custom_tags/select-box/basic.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ import gradio as gr
4
+ import modelscope_studio as mgr
5
+
6
+ options = [{"label": "A", "value": "a"}, "b", "c"]
7
+
8
+ with gr.Blocks() as demo:
9
+ mgr.Markdown(
10
+ f"""Single Select: <select-box options='{json.dumps(options)}' select-once></select-box>
11
+
12
+ Multiple Select:<select-box type="checkbox" options='{json.dumps(options)}' select-once submit-text="Submit"></select-box>
13
+
14
+ Vertical Direction:
15
+
16
+ <select-box direction="vertical" type="checkbox" options='{json.dumps(options)}' select-once submit-text="Submit"></select-box>
17
+ """, )
18
+
19
+ if __name__ == "__main__":
20
+ demo.queue().launch()
components/Markdown/demos/custom_tags/select-box/card_shape.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+
4
+ import gradio as gr
5
+ import modelscope_studio as mgr
6
+
7
+ # Card shape supports setting `imgSrc` as the cover.
8
+ options = [{
9
+ "label":
10
+ "A",
11
+ "imgSrc":
12
+ os.path.join(os.path.dirname(__file__), '../../../resources/screen.jpeg'),
13
+ "value":
14
+ "a"
15
+ }, "b", "c", "d"]
16
+
17
+ with gr.Blocks() as demo:
18
+ mgr.Markdown(
19
+ f"""<select-box shape="card" options='{json.dumps(options)}' select-once equal-height></select-box>
20
+
21
+ Custom Columns:
22
+
23
+ <select-box shape="card" columns="2" options='{json.dumps(options)}' select-once equal-height></select-box>
24
+
25
+ Vertical Direction:
26
+
27
+ <select-box shape="card" direction="vertical" options='{json.dumps(options)}' select-once equal-height></select-box>
28
+ """)
29
+
30
+ if __name__ == "__main__":
31
+ demo.queue().launch()