diff --git a/README-zh_CN.md b/README-zh_CN.md index d7e6f83285094bab6c52317ce7e16fae412e4deb..423fb7ad36d247ff260af84d0dd63ec3937667a1 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -27,7 +27,9 @@ ## 依赖 -- Gradio >= 4.43.0 +- Gradio >= 6.0.0 + +> 注意:您的 Gradio 版本必须`<=6.8.0`,[为什么?](https://github.com/gradio-app/gradio/issues/13131) ## 安装 @@ -35,22 +37,12 @@ pip install modelscope_studio ``` -## 示例 - - - -## 迁移到 1.0 - -如果您在之前使用了`modelscope_studio`的组件,并且想要在新版本中继续使用。不需要对原有组件做任何修改,只需要在外层引入`ms.Application`即可。 +如果您需要使用`4.43.0 <= Gradio < 6.0.0`,请使用 1.x 版本: -```python -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr +```sh +pip install modelscope_studio~=1.0 +``` -with gr.Blocks() as demo: - with ms.Application(): - mgr.Chatbot() +## 示例 -demo.launch() -``` + diff --git a/README.md b/README.md index 0772dfc60a9f68a4e4863bb362f8f691fe22f324..057ac30ee72708e34b7aead85ece3343bfb41c19 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,9 @@ However, when your application needs Gradio to handle more built-in data on the ## Dependencies -- Gradio >= 4.43.0 +- Gradio >= 6.0.0 + +> Note: Your Gradio version must`<=6.8.0`, [why?](https://github.com/gradio-app/gradio/issues/13131) ## Installation @@ -53,22 +55,12 @@ However, when your application needs Gradio to handle more built-in data on the pip install modelscope_studio ``` -## Examples - - - -## Migration to 1.0 - -If you have used the `modelscope_studio` component before and want to continue using it in the new version, you do not need to make any changes to the original component, just import `ms.Application` in the outer layer. +If you need to use `4.43.0 <= Gradio < 6.0.0`, please use 1.x version: -```python -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr +```sh +pip install modelscope_studio~=1.0 +``` -with gr.Blocks() as demo: - with ms.Application(): - mgr.Chatbot() +## Examples -demo.launch() -``` + diff --git a/api/app.py b/api/app.py deleted file mode 100644 index 6f651d0bf3117ec127ca067c1c710df74910ddcf..0000000000000000000000000000000000000000 --- a/api/app.py +++ /dev/null @@ -1,19 +0,0 @@ -import os - -from components.legacy.Docs import Docs - - -def resolve(relative_path: str): - return os.path.join(os.path.dirname(__file__), relative_path) - - -docs = Docs( - __file__, - markdown_files=([ - filename for filename in os.listdir(resolve('.')) - if filename.endswith(".md") - ]), -) - -if __name__ == "__main__": - docs.render().queue().launch() diff --git a/api/load-zh_CN.md b/api/load-zh_CN.md deleted file mode 100644 index e2335833108056b7f1bdd61cf69b9dfe363abea1..0000000000000000000000000000000000000000 --- a/api/load-zh_CN.md +++ /dev/null @@ -1,30 +0,0 @@ -# load - -该特性与 [gr.load](https://www.gradio.app/docs/gradio/load) 类似。允许用户从已有创空间 [ModelScope Studio](https://modelscope.cn/studios) 仓库构造 demo。 - -## 如何使用 - -### 基本使用 - -```python -import modelscope_studio.components.legacy as mgr -demo = mgr.load("modelscope/modelscope-studio") -demo.launch() -``` - -### 使用访问令牌 - -使用访问令牌来加载私有创空间。在这里找到您的 sdk 令牌:https://modelscope.cn/my/myaccesstoken。 - -```python -import modelscope_studio.components.legacy as mgr -demo = mgr.load("modelscope/modelscope-studio", token="YOUR_ACCESS_TOKEN") -demo.launch() -``` - -## 初始化 - -| 属性 | 类型 | 默认值 | 描述 | -| ----- | ---- | ------ | ---------------------------------------------------------------------------------------------------- | -| name | str | None | 必填。 创空间名称(如: "modelscope/modelscope-studio")。 | -| token | str | None | 用于加载私有创空间的可选访问令牌。 在这里找到您的 sdk 令牌:https://modelscope.cn/my/myaccesstoken。 | diff --git a/api/load.md b/api/load.md deleted file mode 100644 index 114baa1552200161830345a04e8c94c7c11ff1b3..0000000000000000000000000000000000000000 --- a/api/load.md +++ /dev/null @@ -1,30 +0,0 @@ -# load - -This feature is similar to [gr.load](https://www.gradio.app/docs/gradio/load). Allow users to Construct a demo from a [ModelScope Studio](https://modelscope.cn/studios) repo. - -## How to Use - -### Basic Usage - -```python -import modelscope_studio.components.legacy as mgr -demo = mgr.load("modelscope/modelscope-studio") -demo.launch() -``` - -### With Access Token - -Use the access token to load a private ModelScope Studio repo. Find your sdk token here: https://modelscope.cn/my/myaccesstoken. - -```python -import modelscope_studio.components.legacy as mgr -demo = mgr.load("modelscope/modelscope-studio", token="YOUR_ACCESS_TOKEN") -demo.launch() -``` - -## Initialization - -| Parameter | Type | Default Value | Description | -| --------- | ---- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| name | str | None | required. the name of the ModelScope Studio repo (e.g. "modelscope/modelscope-studio"). | -| token | str | None | optional access token for loading private ModelScope Studio repo. Find your sdk token here: https://modelscope.cn/my/myaccesstoken. | diff --git a/app.py b/app.py index a185c0d3405aa202fcddc320c4a5709437b0266e..68fa1e0f0c12fca3e93f4e99465c46676547106b 100644 --- a/app.py +++ b/app.py @@ -6,7 +6,6 @@ import modelscope_studio.components.base as ms from helper.Docs import Docs from helper.env import is_modelscope_studio from helper.Site import Site -from legacy_app import legacy_demo is_dev = os.environ.get("GRADIO_WATCH_MODULE_NAME") == 'docs.app' @@ -225,6 +224,9 @@ antd_menu_items = [{ }, { "label": get_text("Layout", "Layout 布局"), "key": "layout" + }, { + "label": get_text("Masonry", "Masonry 瀑布流"), + "key": "masonry" }, { "label": get_text("Space", "Space 间距"), "key": "space" @@ -452,6 +454,9 @@ antdx_menu_items = [{ }, { "label": get_text("Conversations", "Conversations 管理对话"), "key": "conversations" + }, { + "label": get_text("Notification", "Notification 系统通知"), + "key": "notification" }] }, { "label": @@ -486,6 +491,9 @@ antdx_menu_items = [{ "type": "group", "children": [{ + "label": get_text("Think", "Think 思考过程"), + "key": "think" + }, { "label": get_text("ThoughtChain", "ThoughtChain 思考链"), "key": "thought_chain" }] @@ -497,6 +505,21 @@ antdx_menu_items = [{ "children": [{ "label": get_text("Actions", "Actions 操作列表"), "key": "actions" + }, { + "label": get_text("CodeHighlighter", "CodeHighlighter 代码高亮"), + "key": "code_highlighter" + }, { + "label": get_text("FileCard", "FileCard 文件卡片"), + "key": "file_card" + }, { + "label": get_text("Folder", "Folder 文件夹"), + "key": "folder" + }, { + "label": get_text("Mermaid", "Mermaid 图表工具"), + "key": "mermaid" + }, { + "label": get_text("Sources", "Sources 来源引用"), + "key": "sources" }] }, { "label": @@ -573,11 +596,6 @@ tabs = [ "default_active_key": "overview", "menus": antdx_menu_items, }, - { - "label": get_text("Version 0.x", "0.x 版本"), - "key": "legacy", - "content": legacy_demo - } if not is_dev else None, ] site = Site( @@ -593,8 +611,8 @@ site = Site( default_active_tab=default_active_tab, logo=logo) -demo = site.render() +demo, css = site.render() if __name__ == "__main__": demo.queue(default_concurrency_limit=100, - max_size=100).launch(ssr_mode=False, max_threads=100) + max_size=100).launch(css=css, ssr_mode=False, max_threads=100) diff --git a/components/antd/config_provider/demos/basic.py b/components/antd/config_provider/demos/basic.py index 58b16056704eb4176fe31cafcd27b6b4c835e1ea..7989f9a74f6048f95b9ee416d83535afa075fa1f 100644 --- a/components/antd/config_provider/demos/basic.py +++ b/components/antd/config_provider/demos/basic.py @@ -10,7 +10,7 @@ with gr.Blocks() as demo: with antd.ConfigProvider( locale=default_locale, direction=default_direction, - theme=dict(token=dict( + theme_config=dict(token=dict( colorPrimary=default_color))) as config_provider: with antd.Card(): with ms.Div(elem_style=dict(marginBottom=16)): @@ -61,7 +61,7 @@ with gr.Blocks() as demo: outputs=[config_provider]) gr.on( [theme.change, color.change], - fn=lambda _theme, _color: gr.update(theme=dict( + fn=lambda _theme, _color: gr.update(theme_config=dict( token=dict(colorPrimary=_color) if _color else None, algorithm=dict(dark=True if _theme and 'dark' in _theme else False, diff --git a/components/antd/masonry/README-zh_CN.md b/components/antd/masonry/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..b296ce7949d5b71081f5d55f479c775f2840f465 --- /dev/null +++ b/components/antd/masonry/README-zh_CN.md @@ -0,0 +1,9 @@ +# Masonry + +A masonry/waterfall layout component for displaying content with different heights. See [Ant Design](https://ant.design/components/masonry/) for more information. + +## Examples + + + + diff --git a/components/antd/masonry/README.md b/components/antd/masonry/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b296ce7949d5b71081f5d55f479c775f2840f465 --- /dev/null +++ b/components/antd/masonry/README.md @@ -0,0 +1,9 @@ +# Masonry + +A masonry/waterfall layout component for displaying content with different heights. See [Ant Design](https://ant.design/components/masonry/) for more information. + +## Examples + + + + diff --git a/components/legacy/MultimodalInput/app.py b/components/antd/masonry/app.py similarity index 68% rename from components/legacy/MultimodalInput/app.py rename to components/antd/masonry/app.py index ea841f78832d9254426dc781674f7e39f7f7fd2f..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 100644 --- a/components/legacy/MultimodalInput/app.py +++ b/components/antd/masonry/app.py @@ -1,4 +1,4 @@ -from components.legacy.Docs import Docs +from helper.Docs import Docs docs = Docs(__file__) diff --git a/components/antd/masonry/demos/basic.py b/components/antd/masonry/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..090062e6fe3b994372e777a6ba72aeee1b688e40 --- /dev/null +++ b/components/antd/masonry/demos/basic.py @@ -0,0 +1,36 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +card_contents = [ + ("Nature", "The natural world is full of wonder and beauty.", 120), + ("Technology", "Modern technology shapes how we live and work every day.", + 100), + ("Travel", + "Exploring new destinations broadens the mind and enriches the soul.", + 140), + ("Food", "Culinary traditions reflect the culture and history of a place.", + 80), + ("Science", + "Scientific discoveries have transformed our understanding of the universe.", + 160), + ("Art", + "Artistic expression takes countless forms across different cultures and eras.", + 110), +] + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Masonry(columns=3, gutter=16): + for title, content, height in card_contents: + with antd.Masonry.Item(): + with antd.Card(title=title, + elem_style=dict(marginBottom=0)): + ms.Div(content, + elem_style=dict(height=height, + display='flex', + alignItems='center')) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antd/masonry/demos/columns.py b/components/antd/masonry/demos/columns.py new file mode 100644 index 0000000000000000000000000000000000000000..b3a4cd97a29a95437376c0a19afd29b0ee2d69b0 --- /dev/null +++ b/components/antd/masonry/demos/columns.py @@ -0,0 +1,49 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +card_contents = [ + ("Card 1", 120), + ("Card 2", 80), + ("Card 3", 160), + ("Card 4", 100), + ("Card 5", 140), + ("Card 6", 90), + ("Card 7", 110), + ("Card 8", 130), +] + +default_columns = 3 + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Flex(gap="middle", vertical=True): + ms.Div("Select number of columns:") + columns_segmented = antd.Segmented(default_columns, + options=[ + dict(label="1 Column", + value=1), + dict(label="2 Columns", + value=2), + dict(label="3 Columns", + value=3), + dict(label="4 Columns", + value=4), + ]) + with antd.Masonry(columns=default_columns, + gutter=16) as masonry: + for title, height in card_contents: + with antd.Masonry.Item(): + with antd.Card(title=title, + elem_style=dict(marginBottom=0)): + ms.Div(elem_style=dict(height=height, + background='#f0f5ff', + borderRadius=4)) + columns_segmented.change( + fn=lambda _columns: gr.update(columns=_columns), + inputs=[columns_segmented], + outputs=[masonry]) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antd/masonry/demos/responsive.py b/components/antd/masonry/demos/responsive.py new file mode 100644 index 0000000000000000000000000000000000000000..d6acb86af4c6db4f158c1154bd868a66bf8fad2a --- /dev/null +++ b/components/antd/masonry/demos/responsive.py @@ -0,0 +1,40 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +items = [ + dict(color='#1677ff', height=150, label='Item A'), + dict(color='#52c41a', height=80, label='Item B'), + dict(color='#fa8c16', height=200, label='Item C'), + dict(color='#722ed1', height=120, label='Item D'), + dict(color='#eb2f96', height=100, label='Item E'), + dict(color='#13c2c2', height=180, label='Item F'), + dict(color='#faad14', height=90, label='Item G'), + dict(color='#f5222d', height=160, label='Item H'), + dict(color='#1677ff', height=110, label='Item I'), + dict(color='#52c41a', height=140, label='Item J'), + dict(color='#fa8c16', height=70, label='Item K'), + dict(color='#722ed1', height=190, label='Item L'), +] + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Masonry(columns=4, gutter=12): + for item in items: + with antd.Masonry.Item(): + ms.Div(item['label'], + elem_style=dict( + height=item['height'], + background=item['color'], + borderRadius=8, + display='flex', + alignItems='center', + justifyContent='center', + color='#fff', + fontSize=16, + fontWeight='bold', + )) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/actions/demos/basic.py b/components/antdx/actions/demos/basic.py index adc619f552726013ca42ae7b3f650ea1d83729de..6f154b00ce8905943188bfe490d078eb5da10669 100644 --- a/components/antdx/actions/demos/basic.py +++ b/components/antdx/actions/demos/basic.py @@ -18,33 +18,33 @@ with gr.Blocks() as demo: with ms.Application(): with antdx.XProvider(): with antdx.Actions() as actions: - with antdx.Actions.Item(key="retry", label="Retry"): + with antdx.Actions.ActionItem(key="retry", label="Retry"): with ms.Slot("icon"): antd.Icon("RedoOutlined") - with antdx.Actions.Item(key="copy", label="Copy"): - with ms.Slot("icon"): - antd.Icon("CopyOutlined") - antd.Divider("More Menu Items") + with antdx.Actions.ActionItem(key="copy", label="Copy"): + with ms.Slot("actionRender"): + antdx.Actions.Copy(text="Copy Text") + antd.Divider("More Menu ActionItems") with antdx.Actions() as actions2: - with antdx.Actions.Item(key="retry", label="Retry"): + with antdx.Actions.ActionItem(key="retry", label="Retry"): with ms.Slot("icon"): antd.Icon("RedoOutlined") - with antdx.Actions.Item(key="copy", label="Copy"): + with antdx.Actions.ActionItem(key="copy", label="Copy"): with ms.Slot("icon"): antd.Icon("CopyOutlined") - with antdx.Actions.Item(key="more"): - with antdx.Actions.Item(key="share", label="Share"): - with ms.Slot("icon"): - antd.Icon("ShareAltOutlined") - antdx.Actions.Item(key="qq", label="QQ") - antdx.Actions.Item(key="wechat", label="WeChat") - antdx.Actions.Item(key="import", label="Import") - with antdx.Actions.Item( - key="delete", label="Delete", - danger=True) as actions_delete_item: - with ms.Slot("icon"): - antd.Icon("DeleteOutlined") - with antdx.Actions.Item(key="clear", label="Clear"): + with antdx.Actions.ActionItem(key="more"): + with ms.Slot("subItems"): + with antdx.Actions.ActionItem(key="share", + label="Share"): + with ms.Slot("icon"): + antd.Icon("ShareAltOutlined") + antdx.Actions.ActionItem(key="import", label="Import") + with antdx.Actions.ActionItem( + key="delete", label="Delete", + danger=True) as actions_delete_item: + with ms.Slot("icon"): + antd.Icon("DeleteOutlined") + with antdx.Actions.ActionItem(key="clear", label="Clear"): with ms.Slot("icon"): antd.Icon("ClearOutlined") diff --git a/components/antdx/attachments/README-zh_CN.md b/components/antdx/attachments/README-zh_CN.md index 75f8789144ee308d755ce3e9ad7b1a76a87141c6..6e9888ce16465ce30da82f8a5f2c6598a71fa808 100644 --- a/components/antdx/attachments/README-zh_CN.md +++ b/components/antdx/attachments/README-zh_CN.md @@ -6,4 +6,3 @@ Display the collection of attachment information. See [Ant Design X](https://x.a - diff --git a/components/antdx/attachments/README.md b/components/antdx/attachments/README.md index 75f8789144ee308d755ce3e9ad7b1a76a87141c6..6e9888ce16465ce30da82f8a5f2c6598a71fa808 100644 --- a/components/antdx/attachments/README.md +++ b/components/antdx/attachments/README.md @@ -6,4 +6,3 @@ Display the collection of attachment information. See [Ant Design X](https://x.a - diff --git a/components/antdx/attachments/demos/file_card.py b/components/antdx/attachments/demos/file_card.py deleted file mode 100644 index a5c69790e40fe00c546d8b369df98ce7bfc909b5..0000000000000000000000000000000000000000 --- a/components/antdx/attachments/demos/file_card.py +++ /dev/null @@ -1,71 +0,0 @@ -import gradio as gr -import modelscope_studio.components.antd as antd -import modelscope_studio.components.antdx as antdx -import modelscope_studio.components.base as ms - -file_list = [ - { - "uid": '1', - "name": 'excel-file.xlsx', - "size": 111111, - }, - { - "uid": '2', - "name": 'word-file.docx', - "size": 222222, - }, - { - "uid": '3', - "name": 'image-file.png', - "size": 333333, - }, - { - "uid": '4', - "name": 'pdf-file.pdf', - "size": 444444, - }, - { - "uid": '5', - "name": 'ppt-file.pptx', - "size": 555555, - }, - { - "uid": '6', - "name": 'video-file.mp4', - "size": 666666, - }, - { - "uid": '7', - "name": 'audio-file.mp3', - "size": 777777, - }, - { - "uid": '8', - "name": 'zip-file.zip', - "size": 888888, - }, - { - "uid": '9', - "name": 'markdown-file.md', - "size": 999999, - "description": 'Custom description here', - }, - { - "uid": '10', - "name": 'image-file.png', - "thumbUrl": - 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', - "url": - 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', - "size": 123456, - }, -] -with gr.Blocks() as demo: - with ms.Application(): - with antdx.XProvider(): - with antd.Flex(vertical=True, gap="middle"): - for file in file_list: - antdx.Attachments.FileCard(item=file) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/antdx/bubble/demos/basic.py b/components/antdx/bubble/demos/basic.py index 31763fda56b5994959fecee64cae2060fcbcb3fd..205d0edc2b426d6801422227b9286e8e43b9b3eb 100644 --- a/components/antdx/bubble/demos/basic.py +++ b/components/antdx/bubble/demos/basic.py @@ -31,28 +31,32 @@ with gr.Blocks() as demo: with antd.Avatar(elem_style=fooAvatar): with ms.Slot("icon"): antd.Icon("UserOutlined") - antdx.Bubble(placement="start", - content="What a beautiful day!", - avatar=dict(), - styles={"avatar": hideAvatar}) + with antdx.Bubble(placement="start", + content="What a beautiful day!", + styles={"avatar": hideAvatar}): + with ms.Slot("avatar"): + antd.Avatar() with antdx.Bubble(placement="end", content="Hi, good morning, I'm fine!"): with ms.Slot("avatar"): with antd.Avatar(elem_style=barAvatar): with ms.Slot("icon"): antd.Icon("UserOutlined") - antdx.Bubble(placement="end", - content="Thank you!", - avatar=dict(), - styles={"avatar": hideAvatar}) + with antdx.Bubble(placement="end", + content="Thank you!", + styles={"avatar": hideAvatar}): + with ms.Slot("avatar"): + antd.Avatar() antd.Divider("Header and footer") with antdx.Bubble( "Hello, welcome to use Ant Design X! Just ask if you have any questions.", header="Ant Design X"): - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with ms.Slot("footer"): with antd.Space(size="small"): with antd.Button(value=None, @@ -73,16 +77,20 @@ with gr.Blocks() as demo: ms.Span("Loading State") loading_switch = antd.Switch(value=False) with antdx.Bubble("hello world !") as loading_bubble: - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") loading_switch.change(fn=lambda x: gr.update(loading=x), inputs=[loading_switch], outputs=[loading_bubble]) antd.Divider("Markdown") with antdx.Bubble(): - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with ms.Slot("content"): ms.Markdown("Hello `Markdown`!") diff --git a/components/antdx/bubble/demos/bubble_list.py b/components/antdx/bubble/demos/bubble_list.py index 34e59aa56e1533dca5fa1f3dd5f02bb4bc099e29..bc1cd7f45f1b729122476d76fe59109518c38af8 100644 --- a/components/antdx/bubble/demos/bubble_list.py +++ b/components/antdx/bubble/demos/bubble_list.py @@ -1,3 +1,5 @@ +import time + import gradio as gr import modelscope_studio.components.antd as antd import modelscope_studio.components.antdx as antdx @@ -14,6 +16,7 @@ def get_bubble_items(count): "content": content, "key": i - 1 }) + time.sleep(2) return result @@ -27,20 +30,20 @@ with gr.Blocks() as demo: with ms.Application(): state = gr.State({"history_count": 3}) - with antdx.XProvider(): + with antdx.XProvider(), ms.AutoLoading(): antd.Typography.Paragraph( - "Preset Bubble list. Support auto scroll. Use roles to set default properties of Bubble." + "Preset Bubble list. Support auto scroll. Use role to set default properties of Bubble." ) with antd.Flex(gap="small", vertical=True): with antd.Flex(gap="small", elem_style=dict(alignSelf="flex-end")): add_bubble_btn = antd.Button("Add Bubble") - scroll_btn = antd.Button("Scroll To First") - with antdx.Bubble.List(items=get_bubble_items(3), - elem_style=dict(maxHeight=300), - elem_id="bubble-list") as bubble_list: - # Define Roles - with ms.Slot("roles"): + with antdx.Bubble.List( + items=get_bubble_items(3), + elem_style={"height": 300}, + class_names=dict(scroll="bubble-list")) as bubble_list: + # Define Role + with ms.Slot("role"): with antdx.Bubble.List.Role( role="ai", placement="start", @@ -51,9 +54,9 @@ with gr.Blocks() as demo: backgroundColor="#fde3cf")): with ms.Slot("icon"): antd.Icon("UserOutlined") - # use messageRender to render markdown content + # use contentRender to render markdown content with ms.Slot( - "messageRender", + "contentRender", params_mapping="""content => content"""): ms.Markdown() @@ -67,17 +70,12 @@ with gr.Blocks() as demo: with ms.Slot("icon"): antd.Icon("UserOutlined") with ms.Slot( - "messageRender", + "contentRender", params_mapping="(content) => content"): ms.Markdown() add_bubble_btn.click(fn=add_bubble, inputs=[state], outputs=[state, bubble_list]) - scroll_btn.click(fn=None, - js="""() => { - const bubbleList = document.getElementById("bubble-list"); - bubbleList.scrollTo({ top:0, behavior:'smooth' }); -}""") if __name__ == "__main__": demo.queue().launch() diff --git a/components/antdx/bubble/demos/chatbot.py b/components/antdx/bubble/demos/chatbot.py index 201763a49cdfbe9cf25f4acb7e6359880bf10722..a5a27136942bb4da3c4ce3014e029ea6815c5e9d 100644 --- a/components/antdx/bubble/demos/chatbot.py +++ b/components/antdx/bubble/demos/chatbot.py @@ -64,12 +64,11 @@ with gr.Blocks() as demo: with antd.Flex(gap="small", elem_style=dict(alignSelf="flex-end")): add_bubble_btn = antd.Button("Add Bubble") - scroll_btn = antd.Button("Scroll To First") with antdx.Bubble.List(items=default_history, - elem_style=dict(maxHeight=500), + elem_style=dict(height=500), elem_id="chatbot") as bubble_list: - # Define Roles - with ms.Slot("roles"): + # Define Role + with ms.Slot("role"): with antdx.Bubble.List.Role( role="ai", placement="start", @@ -81,9 +80,9 @@ with gr.Blocks() as demo: backgroundColor="#fde3cf")): with ms.Slot("icon"): antd.Icon("UserOutlined") - # use messageRender to render markdown content + # use contentRender to render markdown content with ms.Slot( - "messageRender", + "contentRender", params_mapping="""content => content"""): ms.Markdown() @@ -149,17 +148,12 @@ with gr.Blocks() as demo: with ms.Slot("icon"): antd.Icon("UserOutlined") with ms.Slot( - "messageRender", + "contentRender", params_mapping="(content) => content"): ms.Markdown() add_bubble_btn.click(fn=add_bubble, inputs=[state], outputs=[state, bubble_list]) - scroll_btn.click(fn=None, - js="""() => { - const bubbleList = document.getElementById("chatbot"); - bubbleList.scrollTo({ top:0, behavior:'smooth' }); -}""") if __name__ == "__main__": demo.queue().launch() diff --git a/components/antdx/bubble/demos/custom_list_content.py b/components/antdx/bubble/demos/custom_list_content.py index a54466e8c1df8545063ddd3cfe03f49ea198f4b0..84e180f24654aba8667758b7f08759f86936aa86 100644 --- a/components/antdx/bubble/demos/custom_list_content.py +++ b/components/antdx/bubble/demos/custom_list_content.py @@ -45,16 +45,14 @@ items = [ "content": [ { "uid": '1', - "name": 'excel-file.xlsx', - "size": 111111, + "filename": 'excel-file.xlsx', + "byte": 111111, "description": 'Checking the data', }, { "uid": '2', - "name": 'word-file.docx', - "size": 222222, - "status": 'uploading', - "percent": 23, + "filename": 'word-file.docx', + "byte": 222222 }, ], }, @@ -68,8 +66,8 @@ with gr.Blocks() as demo: "Customize the content of the bubble list, which is very useful for personalized customization scenarios." ) with antdx.Bubble.List(items=items) as bubble_list: - # Define Roles - with ms.Slot("roles"): + # Define Role + with ms.Slot("role"): with antdx.Bubble.List.Role(role="ai-markdown", placement="start"): with ms.Slot("avatar"): @@ -77,7 +75,7 @@ with gr.Blocks() as demo: backgroundColor="#fde3cf")): with ms.Slot("icon"): antd.Icon("UserOutlined") - with ms.Slot("messageRender", + with ms.Slot("contentRender", params_mapping="(content) => content"): ms.Markdown() with antdx.Bubble.List.Role(role="ai-error-message", @@ -87,32 +85,28 @@ with gr.Blocks() as demo: backgroundColor="#fde3cf")): with ms.Slot("icon"): antd.Icon("UserOutlined") - with ms.Slot("messageRender", + with ms.Slot("contentRender", params_mapping="(content) => content"): antd.Typography.Text(type="danger") - with antdx.Bubble.List.Role( - role="ai-suggestion", - placement="start", - variant="borderless", - avatar=dict(style=dict(visibility='hidden'))): - with ms.Slot("messageRender", + with antdx.Bubble.List.Role(role="ai-suggestion", + placement="start", + variant="borderless"): + with ms.Slot("contentRender", params_mapping="(items) => ({ items })"): prompts = antdx.Prompts(vertical=True) - with antdx.Bubble.List.Role( - role="ai-file", - placement="start", - variant="borderless", - avatar=dict(style=dict(visibility='hidden'))): - with ms.Slot("messageRender", + with antdx.Bubble.List.Role(role="ai-file", + placement="start", + variant="borderless"): + with ms.Slot("contentRender", params_mapping="""(content) => { return { - each: content?.map(item => ({ item })) + each: content } }"""): with antd.Flex(vertical=True, gap="middle"): with ms.Each(as_item="each"): - antdx.Attachments.FileCard() + antdx.FileCard() if __name__ == "__main__": demo.queue().launch() diff --git a/components/antdx/bubble/demos/typing_effect.py b/components/antdx/bubble/demos/typing_effect.py index 63e5ef4a34df52a1f4c871239d482d5c5f4dce2a..15d27808868144e9189e8e31735dc4c2e5aa5892 100644 --- a/components/antdx/bubble/demos/typing_effect.py +++ b/components/antdx/bubble/demos/typing_effect.py @@ -28,13 +28,16 @@ with gr.Blocks() as demo: with antd.Flex(vertical=True, gap="small"): with antdx.Bubble(content=text, typing=dict(step=2, interval=50)) as bubble1: - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with antdx.Bubble(content=text, - typing=dict(step=2, interval=50, - suffix="💗")) as bubble2: - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + typing=dict(step=2, interval=50)) as bubble2: + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") btn = antd.Button("Repeat 1 Times", elem_style=dict(alignSelf="flex-end")) btn.click(fn=repeat, diff --git a/components/antdx/bubble/demos/variant.py b/components/antdx/bubble/demos/variant.py index 6b5ff50e10f8be1ddb750f9a50b006e4ad43f662..e4ed890cff7a60a2dfbeaafa825fb3c5acf4076a 100644 --- a/components/antdx/bubble/demos/variant.py +++ b/components/antdx/bubble/demos/variant.py @@ -11,18 +11,27 @@ with gr.Blocks() as demo: ) with antd.Flex(vertical=True, gap="middle"): with antdx.Bubble(variant="filled", content="variant: filled"): - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with antdx.Bubble(variant="outlined", content="variant: outlined"): - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with antdx.Bubble(variant="shadow", content="variant: shadow"): - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with antdx.Bubble(variant="borderless"): - with ms.Slot("avatar.icon"): - antd.Icon("UserOutlined") + with ms.Slot("avatar"): + with antd.Avatar(): + with ms.Slot("icon"): + antd.Icon("UserOutlined") with ms.Slot("content"): with antdx.Prompts( vertical=True, diff --git a/components/antdx/code_highlighter/README-zh_CN.md b/components/antdx/code_highlighter/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..b6a6cacb4eaa4eae7d25d9a654ae4ad0388b2a5f --- /dev/null +++ b/components/antdx/code_highlighter/README-zh_CN.md @@ -0,0 +1,7 @@ +# CodeHighlighter + +A component for syntax highlighting of code blocks. See [Ant Design X](https://x.ant.design/components/code-highlighter/) for more information. + +## Examples + + diff --git a/components/antdx/code_highlighter/README.md b/components/antdx/code_highlighter/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b6a6cacb4eaa4eae7d25d9a654ae4ad0388b2a5f --- /dev/null +++ b/components/antdx/code_highlighter/README.md @@ -0,0 +1,7 @@ +# CodeHighlighter + +A component for syntax highlighting of code blocks. See [Ant Design X](https://x.ant.design/components/code-highlighter/) for more information. + +## Examples + + diff --git a/components/legacy/Chatbot/app.py b/components/antdx/code_highlighter/app.py similarity index 68% rename from components/legacy/Chatbot/app.py rename to components/antdx/code_highlighter/app.py index ea841f78832d9254426dc781674f7e39f7f7fd2f..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 100644 --- a/components/legacy/Chatbot/app.py +++ b/components/antdx/code_highlighter/app.py @@ -1,4 +1,4 @@ -from components.legacy.Docs import Docs +from helper.Docs import Docs docs = Docs(__file__) diff --git a/components/antdx/code_highlighter/demos/basic.py b/components/antdx/code_highlighter/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..ded31c2835b03df23a50b1f28a1f12cea60d4549 --- /dev/null +++ b/components/antdx/code_highlighter/demos/basic.py @@ -0,0 +1,75 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + +python_code = """import gradio as gr +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antdx.CodeHighlighter( + value="print('Hello, World!')", + lang="python", + header=True + ) + +if __name__ == "__main__": + demo.queue().launch() +""" + +javascript_code = """function greet(name) { + return `Hello, ${name}!`; +} + +const result = greet('World'); +console.log(result); +""" + +typescript_code = """interface User { + id: number; + name: string; + email: string; +} + +function createUser(name: string, email: string): User { + return { + id: Math.random(), + name, + email, + }; +} +""" + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antd.Divider("Python Code") + antdx.CodeHighlighter(value=python_code, + lang="python", + header=True) + + antd.Divider("JavaScript Code") + antdx.CodeHighlighter(value=javascript_code, + lang="javascript", + header=True) + + antd.Divider("TypeScript Code") + antdx.CodeHighlighter(value=typescript_code, + lang="typescript", + header=True) + + antd.Divider("Custom Header Slot") + with antdx.CodeHighlighter(value=python_code, lang="python"): + with ms.Slot("header"): + with antd.Flex(justify="space-between", align="center"): + ms.Span("Python Example") + with antd.Button(value=None, size="small", + type="text"): + with ms.Slot("icon"): + antd.Icon("CopyOutlined") + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/file_card/README-zh_CN.md b/components/antdx/file_card/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..7c051497c7b068fad1a1dc450106ec0fcf3450cb --- /dev/null +++ b/components/antdx/file_card/README-zh_CN.md @@ -0,0 +1,7 @@ +# FileCard + +Used to display files during conversations or input. See [Ant Design X](https://x.ant.design/components/file-card/) for more information. + +## Examples + + diff --git a/components/antdx/file_card/README.md b/components/antdx/file_card/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7c051497c7b068fad1a1dc450106ec0fcf3450cb --- /dev/null +++ b/components/antdx/file_card/README.md @@ -0,0 +1,7 @@ +# FileCard + +Used to display files during conversations or input. See [Ant Design X](https://x.ant.design/components/file-card/) for more information. + +## Examples + + diff --git a/components/legacy/Flow/app.py b/components/antdx/file_card/app.py similarity index 68% rename from components/legacy/Flow/app.py rename to components/antdx/file_card/app.py index ea841f78832d9254426dc781674f7e39f7f7fd2f..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 100644 --- a/components/legacy/Flow/app.py +++ b/components/antdx/file_card/app.py @@ -1,4 +1,4 @@ -from components.legacy.Docs import Docs +from helper.Docs import Docs docs = Docs(__file__) diff --git a/components/antdx/file_card/demos/basic.py b/components/antdx/file_card/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..129158b325ce89d15c30ff7bbbe32abb1c6cbf37 --- /dev/null +++ b/components/antdx/file_card/demos/basic.py @@ -0,0 +1,96 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antd.Divider("File Types") + with antd.Flex(gap="middle", wrap=True): + antdx.FileCard(filename="document.pdf", + type="file", + icon="pdf", + byte=204800) + antdx.FileCard(filename="spreadsheet.xlsx", + type="file", + icon="excel", + byte=102400) + antdx.FileCard(filename="presentation.pptx", + type="file", + icon="ppt", + byte=512000) + antdx.FileCard(filename="report.docx", + type="file", + icon="word", + byte=81920) + antdx.FileCard(filename="archive.zip", + type="file", + icon="zip", + byte=1048576) + antdx.FileCard(filename="README.md", + type="file", + icon="markdown", + byte=4096) + antdx.FileCard(filename="script.py", + type="file", + icon="python", + byte=8192) + + antd.Divider("Image Type") + with antd.Flex(gap="middle", wrap=True): + antdx.FileCard( + filename="photo.jpg", + type="image", + src= + "https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg", + byte=327680) + + antd.Divider("Loading State") + with antd.Flex(gap="middle", wrap=True): + antdx.FileCard(filename="loading-file.pdf", + type="file", + icon="pdf", + loading=True) + + antd.Divider("With Description") + with antd.Flex(gap="middle", wrap=True): + antdx.FileCard(filename="notes.txt", + type="file", + description="Last modified today", + byte=2048) + + antd.Divider("FileCard.List") + antdx.FileCard.List(items=[{ + "filename": "file1.pdf", + "type": "file", + "icon": "pdf", + "byte": 204800 + }, { + "filename": "image1.jpg", + "type": "image", + "byte": 327680 + }, { + "filename": "audio.mp3", + "type": "audio", + "byte": 5242880 + }, { + "filename": "video.mp4", + "type": "video", + "byte": 52428800 + }], + removable=True) + + antd.Divider("FileCard.List with Custom Items") + with antdx.FileCard.List(removable=True): + antdx.FileCard.List.Item(filename="custom1.xlsx", + type="file", + icon="excel", + byte=102400) + antdx.FileCard.List.Item(filename="custom2.pdf", + type="file", + icon="pdf", + byte=204800) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/folder/README-zh_CN.md b/components/antdx/folder/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..dd33337cd8dc7504af5e1a7b483f1b707d909554 --- /dev/null +++ b/components/antdx/folder/README-zh_CN.md @@ -0,0 +1,7 @@ +# Folder + +A folder tree component for displaying file structures. See [Ant Design X](https://x.ant.design/components/folder/) for more information. + +## Examples + + diff --git a/components/antdx/folder/README.md b/components/antdx/folder/README.md new file mode 100644 index 0000000000000000000000000000000000000000..dd33337cd8dc7504af5e1a7b483f1b707d909554 --- /dev/null +++ b/components/antdx/folder/README.md @@ -0,0 +1,7 @@ +# Folder + +A folder tree component for displaying file structures. See [Ant Design X](https://x.ant.design/components/folder/) for more information. + +## Examples + + diff --git a/components/legacy/Lifecycle/app.py b/components/antdx/folder/app.py similarity index 68% rename from components/legacy/Lifecycle/app.py rename to components/antdx/folder/app.py index ea841f78832d9254426dc781674f7e39f7f7fd2f..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 100644 --- a/components/legacy/Lifecycle/app.py +++ b/components/antdx/folder/app.py @@ -1,4 +1,4 @@ -from components.legacy.Docs import Docs +from helper.Docs import Docs docs = Docs(__file__) diff --git a/components/antdx/folder/demos/basic.py b/components/antdx/folder/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..0c60768de4e14d040853f746d8644a4cbcbc4aeb --- /dev/null +++ b/components/antdx/folder/demos/basic.py @@ -0,0 +1,110 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + + +def on_file_click(e: gr.EventData): + print("file clicked:", e._data["payload"]) + + +def on_folder_click(e: gr.EventData): + print("folder clicked:", e._data["payload"]) + + +def on_selected_file_change(e: gr.EventData): + print("selected file changed:", e._data["payload"]) + + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antd.Divider("Basic Folder Tree") + with antdx.Folder(default_expand_all=True) as folder1: + with antdx.Folder.TreeNode(title="src", path="/src"): + antdx.Folder.TreeNode(title="index.ts", + path="/src/index.ts", + content="export * from './app';") + antdx.Folder.TreeNode( + title="app.ts", + path="/src/app.ts", + content= + "// Application entry point\nconsole.log('Hello World');" + ) + with antdx.Folder.TreeNode(title="components", + path="/src/components"): + antdx.Folder.TreeNode( + title="Button.tsx", + path="/src/components/Button.tsx", + content= + "import React from 'react';\n\nexport const Button = () => ;" + ) + antdx.Folder.TreeNode( + title="Input.tsx", + path="/src/components/Input.tsx", + content= + "import React from 'react';\n\nexport const Input = () => ;" + ) + with antdx.Folder.TreeNode(title="utils", + path="/src/utils"): + antdx.Folder.TreeNode( + title="helpers.ts", + path="/src/utils/helpers.ts", + content= + "export const add = (a: number, b: number) => a + b;" + ) + antdx.Folder.TreeNode( + title="package.json", + path="/package.json", + content= + '{\n "name": "my-project",\n "version": "1.0.0"\n}') + antdx.Folder.TreeNode( + title="README.md", + path="/README.md", + content="# My Project\n\nA sample project.") + + antd.Divider("Using tree_data Prop") + antdx.Folder( + default_expand_all=True, + tree_data=[{ + "title": + "project", + "path": + "/project", + "children": [{ + "title": "main.py", + "path": "/project/main.py", + "content": "print('Hello, World!')" + }, { + "title": + "utils.py", + "path": + "/project/utils.py", + "content": + "def greet(name):\n return f'Hello, {name}!'" + }, { + "title": + "tests", + "path": + "/project/tests", + "children": [{ + "title": + "test_main.py", + "path": + "/project/tests/test_main.py", + "content": + "import unittest\n\nclass TestMain(unittest.TestCase):\n pass" + }] + }] + }, { + "title": "requirements.txt", + "path": "/requirements.txt", + "content": "gradio\nmodelscope-studio" + }]) + + folder1.file_click(fn=on_file_click) + folder1.folder_click(fn=on_folder_click) + folder1.selected_file_change(fn=on_selected_file_change) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/mermaid/README-zh_CN.md b/components/antdx/mermaid/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..41a6992f2372e2425d2064767a0bc3b2c45b78ad --- /dev/null +++ b/components/antdx/mermaid/README-zh_CN.md @@ -0,0 +1,7 @@ +# Mermaid + +A Mermaid diagram rendering component. See [Ant Design X](https://x.ant.design/components/mermaid/) for more information. + +## Examples + + diff --git a/components/antdx/mermaid/README.md b/components/antdx/mermaid/README.md new file mode 100644 index 0000000000000000000000000000000000000000..41a6992f2372e2425d2064767a0bc3b2c45b78ad --- /dev/null +++ b/components/antdx/mermaid/README.md @@ -0,0 +1,7 @@ +# Mermaid + +A Mermaid diagram rendering component. See [Ant Design X](https://x.ant.design/components/mermaid/) for more information. + +## Examples + + diff --git a/components/antdx/mermaid/app.py b/components/antdx/mermaid/app.py new file mode 100644 index 0000000000000000000000000000000000000000..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 --- /dev/null +++ b/components/antdx/mermaid/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/components/antdx/mermaid/demos/basic.py b/components/antdx/mermaid/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..d1bda9bff79bf51417049e1b22c005f17820f6fd --- /dev/null +++ b/components/antdx/mermaid/demos/basic.py @@ -0,0 +1,14 @@ +import gradio as gr +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antdx.Mermaid(value="""graph TD + A[Start] --> B{Decision} + B -->|Yes| C[OK] + B -->|No| D[Cancel]""") + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/notification/README-zh_CN.md b/components/antdx/notification/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..2d27e0e71ab19e02c24da702da402fb5d089326a --- /dev/null +++ b/components/antdx/notification/README-zh_CN.md @@ -0,0 +1,7 @@ +# Notification + +A browser native notification component. See [Ant Design X](https://x.ant.design/components/notification/) for more information. + +## Examples + + diff --git a/components/antdx/notification/README.md b/components/antdx/notification/README.md new file mode 100644 index 0000000000000000000000000000000000000000..2d27e0e71ab19e02c24da702da402fb5d089326a --- /dev/null +++ b/components/antdx/notification/README.md @@ -0,0 +1,7 @@ +# Notification + +A browser native notification component. See [Ant Design X](https://x.ant.design/components/notification/) for more information. + +## Examples + + diff --git a/components/antdx/notification/app.py b/components/antdx/notification/app.py new file mode 100644 index 0000000000000000000000000000000000000000..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 --- /dev/null +++ b/components/antdx/notification/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/components/antdx/notification/demos/basic.py b/components/antdx/notification/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..4f9f4a5282ba7a8d36cf16743494cd6cc661597e --- /dev/null +++ b/components/antdx/notification/demos/basic.py @@ -0,0 +1,23 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + notification = antdx.Notification( + title="Hello Notification", + body= + "This is a browser native notification triggered from Gradio.", + duration=5000, + visible=False) + btn = antd.Button("Send Notification", type="primary") + + btn.click( + fn=lambda: gr.update(visible=True), + outputs=[notification], + ) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/prompts/demos/nest_usage.py b/components/antdx/prompts/demos/nest_usage.py index 54ebb75498c4ccb79de3d75bd67556e761ed2dcf..25668714b95604fdd6d946f649a5914b54ebab1a 100644 --- a/components/antdx/prompts/demos/nest_usage.py +++ b/components/antdx/prompts/demos/nest_usage.py @@ -11,7 +11,7 @@ def item_click(e: gr.EventData): with gr.Blocks() as demo: with ms.Application(): - with antdx.XProvider(theme=dict(algorithm=dict(dark=False))): + with antdx.XProvider(theme_config=dict(algorithm=dict(dark=False))): with antd.Card(elem_style=dict(borderRadius=0, border=0)): with antdx.Prompts( title="Do you want?", diff --git a/components/antdx/sources/README-zh_CN.md b/components/antdx/sources/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..eac020b4ea79c19660d6ab77d8231f62896431fb --- /dev/null +++ b/components/antdx/sources/README-zh_CN.md @@ -0,0 +1,7 @@ +# Sources + +A component for displaying information source lists in AI chat scenarios. See [Ant Design X](https://x.ant.design/components/sources/) for more information. + +## Examples + + diff --git a/components/antdx/sources/README.md b/components/antdx/sources/README.md new file mode 100644 index 0000000000000000000000000000000000000000..eac020b4ea79c19660d6ab77d8231f62896431fb --- /dev/null +++ b/components/antdx/sources/README.md @@ -0,0 +1,7 @@ +# Sources + +A component for displaying information source lists in AI chat scenarios. See [Ant Design X](https://x.ant.design/components/sources/) for more information. + +## Examples + + diff --git a/components/antdx/sources/app.py b/components/antdx/sources/app.py new file mode 100644 index 0000000000000000000000000000000000000000..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 --- /dev/null +++ b/components/antdx/sources/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/components/antdx/sources/demos/basic.py b/components/antdx/sources/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..79bcc4b7cdbb00d8b5699138aa056fc1cb77a299 --- /dev/null +++ b/components/antdx/sources/demos/basic.py @@ -0,0 +1,64 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + + +def on_click(e: gr.EventData): + item = e._data["payload"][0] + gr.Info("Clicked: " + str(item.get("title", ""))) + + +def on_expand(e: gr.EventData): + expanded = e._data["payload"][0] + gr.Info("Expanded: " + str(expanded)) + + +source_items = [ + { + "title": "Ant Design X", + "description": "The AI-Native UI solution of Ant Design", + "href": "https://x.ant.design", + }, + { + "title": "Ant Design", + "description": "An enterprise-class UI design language", + "href": "https://ant.design", + }, + { + "title": "GitHub", + "description": "Where the world builds software", + "href": "https://github.com", + }, +] + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antd.Divider("Basic Sources") + sources1 = antdx.Sources(title="References", + items=source_items, + default_expanded=True) + + antd.Divider("Inline Sources") + sources2 = antdx.Sources(title="References", + items=source_items, + inline=True) + + antd.Divider("Sources with Slot Items") + with antdx.Sources(title="Sources") as sources3: + with ms.Slot("items"): + antdx.Sources.Item(title="Ant Design X", + description="The AI-Native UI solution", + url="https://x.ant.design") + antdx.Sources.Item( + title="ModelScope Studio", + description="Gradio component library", + url="https://github.com/modelscope/modelscope-studio") + + sources1.click(fn=on_click) + sources2.click(fn=on_click) + sources1.expand(fn=on_expand) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/think/README-zh_CN.md b/components/antdx/think/README-zh_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..6f1d5186fd5bea20e4d41e257ea846353804962f --- /dev/null +++ b/components/antdx/think/README-zh_CN.md @@ -0,0 +1,7 @@ +# Think + +A component for displaying AI model thinking process in chat scenarios. See [Ant Design X](https://x.ant.design/components/think/) for more information. + +## Examples + + diff --git a/components/antdx/think/README.md b/components/antdx/think/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6f1d5186fd5bea20e4d41e257ea846353804962f --- /dev/null +++ b/components/antdx/think/README.md @@ -0,0 +1,7 @@ +# Think + +A component for displaying AI model thinking process in chat scenarios. See [Ant Design X](https://x.ant.design/components/think/) for more information. + +## Examples + + diff --git a/components/antdx/think/app.py b/components/antdx/think/app.py new file mode 100644 index 0000000000000000000000000000000000000000..0018b7c1d02f97731da6e29c06bb4ebb0326d3e9 --- /dev/null +++ b/components/antdx/think/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/components/antdx/think/demos/basic.py b/components/antdx/think/demos/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..ad28db9293a3c52961cfb27fc5c95c2663096ad4 --- /dev/null +++ b/components/antdx/think/demos/basic.py @@ -0,0 +1,42 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.antdx as antdx +import modelscope_studio.components.base as ms + +thinking_content = """I need to analyze the user's question carefully. + +First, let me consider the context and requirements. +Then, I'll formulate a comprehensive response based on my analysis. +Finally, I'll present the answer in a clear and concise manner.""" + +with gr.Blocks() as demo: + with ms.Application(): + with antdx.XProvider(): + antd.Divider("Basic Think") + with antdx.Think(title="Thinking...", default_expanded=True): + ms.Span(thinking_content) + + antd.Divider("Loading State") + with antd.Space(): + ms.Span("Loading State") + loading_switch = antd.Switch(value=True) + with antdx.Think(title="Thinking...", blink=True) as think_loading: + ms.Span(thinking_content) + + antd.Divider("Expanded Control") + with antd.Space(): + ms.Span("Expanded") + expanded_switch = antd.Switch(value=True) + with antdx.Think(title="Think Result", + expanded=True) as think_expanded: + ms.Span(thinking_content) + + loading_switch.change(fn=lambda x: gr.update(loading=x, blink=x), + inputs=[loading_switch], + outputs=[think_loading]) + expanded_switch.change(fn=lambda x: gr.update(expanded=x), + inputs=[expanded_switch], + outputs=[think_expanded]) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/components/antdx/thought_chain/demos/basic.py b/components/antdx/thought_chain/demos/basic.py index 762983df2f1ef0002d320087f11e8eb0362d74fb..5ba59201dc48f22aeb3b8c67ed4737fe4bacc7b9 100644 --- a/components/antdx/thought_chain/demos/basic.py +++ b/components/antdx/thought_chain/demos/basic.py @@ -3,8 +3,6 @@ import modelscope_studio.components.antd as antd import modelscope_studio.components.antdx as antdx import modelscope_studio.components.base as ms -default_collapsible = False - def mock_content(): with antd.Typography.Paragraph(): @@ -24,13 +22,10 @@ def mock_content(): with gr.Blocks() as demo: with ms.Application(): with antdx.XProvider(): - collapsible = antd.Switch(default_collapsible, - checked_children="Collapsible", - un_checked_children="Not Collapsible") with antd.Card(): - with antdx.ThoughtChain( - collapsible=default_collapsible) as thought_chain: - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain(): + with antdx.ThoughtChain.ThoughtChainItem( + collapsible=True, title="Thought Chain Item Title 1", description="description", status="success"): @@ -43,7 +38,7 @@ with gr.Blocks() as demo: with ms.Slot("footer"): antd.Button("Thought Chain Item Footer", block=True) - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="Thought Chain Item Title 2", description="description", status="error"): @@ -56,7 +51,7 @@ with gr.Blocks() as demo: with ms.Slot("footer"): antd.Button("Thought Chain Item Footer", block=True) - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="Thought Chain Item Title 3", description="description", status="pending"): @@ -69,8 +64,5 @@ with gr.Blocks() as demo: with ms.Slot("footer"): antd.Button("Thought Chain Item Footer", block=True) - collapsible.change(fn=lambda x: gr.update(collapsible=x), - inputs=[collapsible], - outputs=[thought_chain]) if __name__ == "__main__": demo.queue().launch() diff --git a/components/antdx/thought_chain/demos/item_status.py b/components/antdx/thought_chain/demos/item_status.py index 8e7284f1c11f27e3b004055799e72f7ab0e5c61e..ac22f9506b585ae31f93613e427f3377c2d0d9f6 100644 --- a/components/antdx/thought_chain/demos/item_status.py +++ b/components/antdx/thought_chain/demos/item_status.py @@ -9,26 +9,22 @@ import modelscope_studio.components.base as ms def run_next(each_value): each_value.append({ "title": f'Thought Chain Item - {len(each_value) + 1}', - "status": 'pending', + "status": 'loading', "description": 'status: pending', - "icon": "LoadingOutlined", "key": str(len(each_value) + 1) }) yield gr.update(value="Running", loading=True), gr.update(value=each_value) time.sleep(0.8) each_value[-1]["status"] = "error" each_value[-1]["description"] = 'status: error' - each_value[-1]["icon"] = "InfoCircleOutlined" yield gr.skip(), gr.update(value=each_value) time.sleep(0.8) - each_value[-1]["status"] = "pending" + each_value[-1]["status"] = "loading" each_value[-1]["description"] = 'status: pending' - each_value[-1]["icon"] = 'LoadingOutlined' yield gr.skip(), gr.update(value=each_value) time.sleep(0.8) each_value[-1]["status"] = "success" each_value[-1]["description"] = 'status: success' - each_value[-1]["icon"] = "CheckCircleOutlined" yield gr.update(value="Run Next", loading=False), gr.update(value=each_value) @@ -49,20 +45,16 @@ with gr.Blocks() as demo: "title": 'Thought Chain Item - 1', "status": 'success', "description": 'status: success', - "icon": 'CheckCircleOutlined', "key": "1" }, { "title": 'Thought Chain Item - 2', "status": 'error', "description": 'status: error', - "icon": 'InfoCircleOutlined', "key": "2" }, ]) as each: - with antdx.ThoughtChain.Item(): - with ms.Slot("icon"): - antd.Icon(as_item="icon") + antdx.ThoughtChain.ThoughtChainItem() btn.click(fn=run_next, inputs=[each], outputs=[btn, each]) diff --git a/components/antdx/thought_chain/demos/nested_use.py b/components/antdx/thought_chain/demos/nested_use.py index 9ba985835dc14d02b4d06cb1fff8f47719099f81..01c1473a021f406f66fd12a12726d947e25a73ce 100644 --- a/components/antdx/thought_chain/demos/nested_use.py +++ b/components/antdx/thought_chain/demos/nested_use.py @@ -7,8 +7,8 @@ with gr.Blocks() as demo: with ms.Application(): with antdx.XProvider(): with antd.Card(): - with antdx.ThoughtChain(collapsible=True): - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain(): + with antdx.ThoughtChain.ThoughtChainItem( title="1 - Thought Chain Item", description="description"): with ms.Slot("extra"): @@ -17,7 +17,7 @@ with gr.Blocks() as demo: antd.Icon("MoreOutlined") with ms.Slot("content"): with antdx.ThoughtChain(): - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="1-1 - Thought Chain Item", description="description"): with ms.Slot("extra"): @@ -25,7 +25,7 @@ with gr.Blocks() as demo: type="text"): with ms.Slot("icon"): antd.Icon("MoreOutlined") - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="1-2 - Thought Chain Item", description="description"): with ms.Slot("extra"): @@ -35,7 +35,7 @@ with gr.Blocks() as demo: antd.Icon("MoreOutlined") with ms.Slot("footer"): antd.Button("1 - Thought Chain Item Footer") - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="2 - Thought Chain Item", description="description"): with ms.Slot("extra"): @@ -44,7 +44,7 @@ with gr.Blocks() as demo: antd.Icon("MoreOutlined") with ms.Slot("content"): with antdx.ThoughtChain(): - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="2-1 - Thought Chain Item", description="description"): with ms.Slot("extra"): @@ -52,7 +52,7 @@ with gr.Blocks() as demo: type="text"): with ms.Slot("icon"): antd.Icon("MoreOutlined") - with antdx.ThoughtChain.Item( + with antdx.ThoughtChain.ThoughtChainItem( title="2-2 - Thought Chain Item", description="description"): with ms.Slot("extra"): diff --git a/components/legacy/Chatbot/README-zh_CN.md b/components/legacy/Chatbot/README-zh_CN.md deleted file mode 100644 index 8b8398ae2c51586e4d5ae63c8d89ce3f073be2b4..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/README-zh_CN.md +++ /dev/null @@ -1,144 +0,0 @@ -# Chatbot - -升级版的 gradio Chatbot。 - -- 支持前端匀速流式输出 message -- 支持输出多模态内容(音频、视频、图片、文本) -- 内置标签(chart、select-box、accordion) -- 支持多 agent 场景 -- 支持自定义渲染组件,并与 Python 事件交互 - -## 如何使用 - -### 基本使用 - - - -### 多模态 & 支持本地文件的展示 - - - -### 控制打字机单句 message 开关 - - - -### 支持手风琴内容展示 - -在返回的内容中加入 `accordion` 标签,可以在内容中加入手风琴,更多用法详见 Markdown 内置自定义标签 - -同时为了适配大模型的工具调用链路,额外对某些大模型的格式做了预设配置,支持下述格式的预设处理(会将下面的格式转换成上方`accordion`标签包裹形式) - -```python -import modelscope_studio.components.legacy as mgr -from modelscope_studio.components.legacy.Chatbot.llm_thinking_presets import qwen - -# 添加 qwen 解析预设 -mgr.Chatbot(llm_thinking_presets=[qwen()]) -``` - -```text -Action: image_gen -Action Input: {"text": "glorious weather", "resolution": "1024*1024"} -Observation: ![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) 根据您的描述"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) - -Action: 「任意文本表示,将展示为思考链调用的名称」 -Action Input: 「任意json or md 内容,将展示到调用过程的下拉框」 -Observation: 「任意 md 内容,将作为完成调用的展示的下拉框内」 -``` - - - -### 支持用户选择交互 - -在返回的内容中加入 `select-box` 标签,更多用法详见 Markdown 内置自定义标签 - - - -### 支持图表展示 - -在返回的内容中加入 `chart` 标签,更多用法详见 Markdown 内置自定义标签 - - - -### 多 bot 场景 - - - -### 自定义标签(高阶用法,需要了解前端知识) - -详见 Markdown 组件 - -## API 及参数列表 - -以下 API 均为在原有 gradio Chatbot 外的额外拓展参数。 - -### value - -接口定义: - -```python - -class FileMessage(GradioModel): - file: FileData - alt_text: Optional[str] = None - - -class MultimodalMessage(GradioModel): - # 默认以 index 为作为 id,id 改变会导致 message 重新渲染 - id: Optional[str] = None - # message 容器的 elem id - elem_id: Optional[str] = None - # message 容器的 elem classes - elem_classes: Optional[List[str] | str] = None - name: Optional[str] = None - text: Optional[str] = None - flushing: Optional[bool] = None - avatar: Optional[Union[str, FileData]] = '' - files: Optional[List[Union[FileMessage, dict, FileData, str]]] = None - -# 支持多 bot 场景 -MultimodalMessageItem = Optional[Union[MultimodalMessage, MultimodalInputData, - dict, str]] - - -class ChatbotData(GradioRootModel): - root: List[Tuple[Union[MultimodalMessageItem, List[MultimodalMessageItem]], - Union[MultimodalMessageItem, - List[MultimodalMessageItem]]]] -``` - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ----------------------------- | -------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| flushing | bool | True | 是否开启打字机效果。默认只有 bot 的 message 会开启,可以通过单独修改 message 的 flushing 属性精确控制每一条 message 的显示效果 | -| enable_base64 | bool | False | 是否支持渲染的内容为 base64,因为直接渲染 base64 会带来安全问题,默认为 False。 | -| enable_latex | bool | True | 是否支持 Latex 公式渲染 | -| latex_single_dollar_delimiter | bool | True | 是否支持单`$`符号在 Latex 公式中渲染 | -| preview | bool | True | 是否开启图片预览功能 | -| avatar_images | tuple\[str \| Path \| None \| dict \| list, str \| Path \| None \| dict\| list\] | None | 拓展gr.Chatbot的参数值,除了接收 url 外还可以接收 dict 和 list,dict 可以传入avatar和name字段,name字段在渲染时会显示在头像下方。
- 当传入 dict 时,必须包含有avatar字段。
- 当传入 list 时,一般对应多 bot 模式,每一项可以接收前面所有的值,每个 bot 的头像与 message 中 bot 的位置一一对应 | -| avatar_image_align | Literal['top', 'middle', 'bottom'] | 'bottom' | 控制头像与 message 的对齐方式,默认为下对齐 | -| avatar_image_width | int | 45 | 头像与名称的宽度 | -| flushing_speed | int | 3 | 打字机速度,值为 1 - 10,值越大速度越快 | -| llm_thinking_presets | list\[dict\] | \[\] | llm 思考链路解析预设,可以将 llm 调用工具的输出格式转为固定的前端展示格式,需要从modelscope_studio.Chatbot.llm_thinking_presets引入,目前支持:qwen | -| custom_components | dict\[str, CustomComponentDict\] CustomComponentDict 定义见下方 | None | 支持用户定义自定义标签,并通过 js 控制标签渲染样式与触发 python 事件。 | - -**CustomComponentDict 定义如下** - -```python -class CustomComponentDict(TypedDict): - props: Optional[List[str]] - template: Optional[str] - js: Optional[str] -``` - -### 内置的自定义标签 - -见 Markdown 内置自定义标签 - -### event listeners - -| 事件 | 描述 | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `mgr.Chatbot.flushed(fn, ···)` | 当打字机效果结束时触发。EventData 为:
- index:当前 message 的 index tuple。
- value:当前 message value。 | -| `mgr.Chatbot.custom(fn, ···)` | 自定义标签触发事件时触发,EventData 为:
- index:当前 message 的 index tuple ([message index, user group(index 0) or bot group(index 1), user/bot group index])。
- tag:当前触发的标签。
- tag_index:当前触发标签的 index,此 index 在 message 的 index tuple 基础上重新计算。
- value:自定义传入的值。 | diff --git a/components/legacy/Chatbot/README.md b/components/legacy/Chatbot/README.md deleted file mode 100644 index ef41002eb4652e35a6207600fe30b09a82c1d467..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# Chatbot - -Upgraded gradio Chatbot. - -- Supports uniform frontend streaming output of messages -- Supports output of multimodal content (audio, video, image, text) -- Built-in tags (chart, select-box, accordion) -- Supports multi-agent scenarios -- Supports custom rendering components and interaction with Python events - -## How to Use - -### Basic Usage - - - -### Multimodal & Support for Local File Display - - - -### Control for Typewriter Single Sentence Message - - - -### Support for Accordion Content Display - -Include the `accordion` tag in the returned content to add an accordion within the content. For more usage details, see Markdown Built-in Custom Tags. -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). - -```python -import modelscope_studio.components.legacy as mgr -from modelscope_studio.components.legacy.Chatbot.llm_thinking_presets import qwen - -# Add qwen preset -mgr.Chatbot(llm_thinking_presets=[qwen()]) -``` - -```text -Action: image_gen -Action Input: {"text": "glorious weather", "resolution": "1024*1024"} -Observation: ![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) 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) - -Action: 「An arbitrary text representation that will be displayed as the name of the thought chain call」 -Action Input: 「Any json or md content will be displayed in the drop-down box of the calling process」 -Observation: 「Any md content will be displayed in the drop-down box when the call is completed」 -``` - - - -### Support for User Selection Interaction - -Include the `select-box` tag in the returned content. For more usage details, see Markdown Built-in Custom Tags . - - - -### Support for Chart Display - -Include the `chart` tag in the returned content. For more usage details, see Markdown Built-in Custom Tags . - - - -### Multi-bot Scenarios - - - -### Custom Tags (Advanced Usage, Requires Frontend Knowledge) - -See the Markdown component for details. - -## API and Parameter List - -The following APIs are additional extended parameters beyond the original gradio Chatbot. - -### value - -Interface definition: - -```python - -class FileMessage(GradioModel): - file: FileData - alt_text: Optional[str] = None - - -class MultimodalMessage(GradioModel): - # By default, message index is used as id. it will cause the message to be re-rendered when id changed. - id: Optional[str] = None - # elem id of message container - elem_id: Optional[str] = None - # elem classes of message container - elem_classes: Optional[List[str] | str] = None - name: Optional[str] = None - text: Optional[str] = None - flushing: Optional[bool] = None - avatar: Optional[Union[str, FileData]] = '' - files: Optional[List[Union[FileMessage, dict, FileData, str]]] = None - -# Support multi-bot scenarios -MultimodalMessageItem = Optional[Union[MultimodalMessage, MultimodalInputData, - dict, str]] - - -class ChatbotData(GradioRootModel): - root: List[Tuple[Union[MultimodalMessageItem, List[MultimodalMessageItem]], - Union[MultimodalMessageItem, - List[MultimodalMessageItem]]]] -``` - -### props - -| Attribute | Type | Default Value | Description | -| ----------------------------- | -------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 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. | -| enable_base64 | bool | False | Whether to support rendering content as base64, since rendering base64 is unsafe, the default is False. | -| enable_latex | bool | True | Whether to enable LaTeX rendering. | -| latex_single_dollar_delimiter | bool | True | Whether to enable single dollar delimiter `$` for LaTeX rendering. | -| preview | bool | True | Whether to enable image preview functionality. | -| 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.
- When passing a dict, it must include an avatar field.
- 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. | -| avatar_image_align | Literal['top', 'middle', 'bottom'] | 'bottom' | Controls the alignment of the avatar with the messages, default is bottom-aligned. | -| avatar_image_width | int | 45 | The width of the avatar and name. | -| flushing_speed | int | 3 | Typewriter speed, values range from 1 - 10, with larger values indicating faster speeds. | -| 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. | -| 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. | - -**Definition of CustomComponent is as follows:** - -```python -class CustomComponentDict(TypedDict): - props: Optional[List[str]] - template: Optional[str] - js: Optional[str] -``` - -### Built-in Custom Tags - -See Markdown Built-in Custom Tags - -### event listeners - -| Event | Description | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `mgr.Chatbot.flushed(fn, ···)` | Triggered when the typewriter effect ends. EventData is:
- index: The index tuple of the current message.
- value: The current message value. | -| `mgr.Chatbot.custom(fn, ···)` | Triggered when a custom tag event occurs. EventData is:
- index: The index tuple of the current message ([message index, user group(index 0) or bot group(index 1), user/bot group index]).
- tag: The current tag that triggered the event.
- tag_index: The index of the current triggered tag, re-calculated based on the message’s index tuple.
- value: The custom value passed in. | diff --git a/components/legacy/Chatbot/demos/accordion.py b/components/legacy/Chatbot/demos/accordion.py deleted file mode 100644 index 2c00ebfcbd4376593dc881f7f54572c6e2c453b8..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/accordion.py +++ /dev/null @@ -1,51 +0,0 @@ -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr -from modelscope_studio.components.legacy.Chatbot.llm_thinking_presets import \ - qwen - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -conversation = [ - [ - None, { - "text": f""" -Use accordion tag: - - - -```json -{{"text": "glorious weather", "resolution": "1024*1024"}} -``` - - - -Qwen preset: -Action: image_gen -Action Input: {{"text": "glorious weather", "resolution": "1024*1024"}} -Observation: ![IMAGEGEN]({resolve_assets("screen.jpeg")}) Based on your description"glorious weather",I generated a picture.![]({resolve_assets("screen.jpeg")}) - -Action: 「An arbitrary text representation that will be displayed as the name of the thought chain call」 -Action Input: 「Any json or md content will be displayed in the drop-down box of the calling process」 -Observation: 「Any md content will be displayed in the drop-down box when the call is completed」 -""", - "flushing": False - } - ], -] - -with gr.Blocks() as demo, ms.Application(): - mgr.Chatbot( - value=conversation, - llm_thinking_presets=[qwen()], - height=600, - ) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Chatbot/demos/basic.py b/components/legacy/Chatbot/demos/basic.py deleted file mode 100644 index 13570f9a6ce0058575567994aff36915d71ec4fa..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/basic.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -import time - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -conversation = [ - [ - None, - { - # The first message of bot closes the typewriter. - "text": "Hello I'm a chatbot", - "flushing": False - } - ], -] - - -def submit(_input, _chatbot): - _chatbot.append([_input, None]) - yield gr.update(interactive=False, value=None), _chatbot - time.sleep(2) - _chatbot[-1][1] = {"text": _input.text + '!'} - yield { - chatbot: _chatbot, - } - - -def flushed(): - return gr.update(interactive=True) - - -with gr.Blocks() as demo, ms.Application(): - chatbot = mgr.Chatbot( - value=conversation, - avatar_images=[ - os.path.join(os.path.dirname(__file__), - "../../resources/user.jpeg"), { - "name": - "bot", - "avatar": - os.path.join(os.path.dirname(__file__), - "../../resources/bot.jpeg") - } - ], - height=600, - ) - - input = mgr.MultimodalInput() - input.submit(fn=submit, inputs=[input, chatbot], outputs=[input, chatbot]) - chatbot.flushed(fn=flushed, outputs=[input]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Chatbot/demos/chart.py b/components/legacy/Chatbot/demos/chart.py deleted file mode 100644 index e73cf301bf7eaaa9a2609b0a304c7f6c0088ad43..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/chart.py +++ /dev/null @@ -1,43 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# echarts options, see: https://echarts.apache.org/en/index.html -option1 = { - "xAxis": { - "type": 'category', - "data": ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], - }, - "yAxis": { - "type": 'value', - }, - "series": [ - { - "data": [150, 230, 224, 218, 135, 147, 260], - "type": 'line', - }, - ], -} - -conversation = [ - [ - None, { - "text": f""" -Chart: - -""" - } - ], -] - -with gr.Blocks() as demo, ms.Application(): - mgr.Chatbot( - value=conversation, - flushing=False, - height=600, - ) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Chatbot/demos/message_config.py b/components/legacy/Chatbot/demos/message_config.py deleted file mode 100644 index cddb958ec420fadb31670906d48c38413096def2..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/message_config.py +++ /dev/null @@ -1,35 +0,0 @@ -import time - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def submit(_chatbot): - _chatbot.append(["test user", - "test bot"]) # bot starts the typewriter by default - yield _chatbot - time.sleep(2) - _chatbot.append(["test user", { - "text": "test bot", - "flushing": False - }]) # both start the typewriter - yield _chatbot - time.sleep(2) - _chatbot.append([{ - "text": "test user", - "flushing": True - }, { - "text": "test bot", - "flushing": False - }]) # user starts the typewriter - yield _chatbot - - -with gr.Blocks() as demo, ms.Application(): - chatbot = mgr.Chatbot(height=600, ) - button = gr.Button("Submit") - button.click(fn=submit, inputs=[chatbot], outputs=[chatbot]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Chatbot/demos/multi_bots.py b/components/legacy/Chatbot/demos/multi_bots.py deleted file mode 100644 index 21795b02978988ff8c57acadb969ce6be1a22c28..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/multi_bots.py +++ /dev/null @@ -1,87 +0,0 @@ -import os -import time - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -conversation = [ - [None, { - "text": "Hello I'm a chatbot", - "flushing": False - }], -] - - -def get_last_bot_message(chatbot): - return chatbot[-1][1] - - -def create_music_bot_message(text: str): - return { - "text": text, - } - - -def create_image_bot_message(text: str): - return { - "text": text, - } - - -def submit(_input, _chatbot): - _chatbot.append([_input, None]) - yield gr.update(interactive=False, value=None), _chatbot - _chatbot[-1][1] = [ - "Hello", - create_image_bot_message("Hello"), - create_music_bot_message("Hello") - ] - - time.sleep(2) - get_last_bot_message(_chatbot)[1][ - "text"] = f"""Hello, I\'m a image bot\n![image]({resolve_assets("user.jpeg")})""" - get_last_bot_message(_chatbot)[2][ - "text"] = f"""Hello, I\'m a music bot """ - yield { - chatbot: _chatbot, - } - - -def flushed(): - return gr.update(interactive=True) - - -with gr.Blocks() as demo, ms.Application(): - chatbot = mgr.Chatbot( - value=conversation, - avatar_image_width=40, - avatar_images=[ - resolve_assets('user.jpeg'), - # default bot avatar and name - [{ - "name": "bot", - "avatar": resolve_assets('bot.jpeg') - }, { - "name": "image bot", - "avatar": resolve_assets('image-bot.jpeg') - }, { - "name": "music bot", - "avatar": resolve_assets('music-bot.jpeg') - }] - ], - height=600, - ) - - input = mgr.MultimodalInput() - input.submit(fn=submit, inputs=[input, chatbot], outputs=[input, chatbot]) - chatbot.flushed(fn=flushed, outputs=[input]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Chatbot/demos/multimodal.py b/components/legacy/Chatbot/demos/multimodal.py deleted file mode 100644 index cbb2fae83535c20290792f873cc8ba01fda66b54..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/multimodal.py +++ /dev/null @@ -1,39 +0,0 @@ -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -conversation = [ - [ - None, { - "text": f""" -Image - -![image]({resolve_assets("bot.jpeg")}) - - - -Audio - - -""", - "flushing": False - } - ], -] - -with gr.Blocks() as demo, ms.Application(): - mgr.Chatbot( - value=conversation, - height=600, - ) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Chatbot/demos/select-box.py b/components/legacy/Chatbot/demos/select-box.py deleted file mode 100644 index cfbae22e363944831f537c9d7ab63f610efc69f1..0000000000000000000000000000000000000000 --- a/components/legacy/Chatbot/demos/select-box.py +++ /dev/null @@ -1,48 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# `label` will display on the page, and `value` is the actual selected value. -options = [{"label": "A", "value": "a"}, "b", "c"] - -conversation = [[ - None, f""" -Single Select: - -Multiple Select: - -Vertical Direction: - - - -Card Shape: - - - - - - - - -""" -]] - - -# The custom data must be marked by `gr.EventData` -def fn(data: gr.EventData): - print(data._data) - - -with gr.Blocks() as demo, ms.Application(): - chatbot = mgr.Chatbot( - value=conversation, - flushing=False, - height=600, - ) - # All custom tags will trigger the custom event - chatbot.custom(fn=fn) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Docs.py b/components/legacy/Docs.py deleted file mode 100644 index 6c1eb421dd657e16c1484aa36441e419e2509e91..0000000000000000000000000000000000000000 --- a/components/legacy/Docs.py +++ /dev/null @@ -1,178 +0,0 @@ -import os -import re -from typing import Callable - -import gradio as gr -import modelscope_studio.components.legacy as mgr -from helper.env import is_modelscope_studio - -from .parse_markdown import parse_markdown - -with open(os.path.join(os.path.dirname(__file__), "tab-link.js")) as f: - tab_link_js = f.read() - -custom_components = { - "tab-link": { - "props": ["tab", "component-tab"], - "js": tab_link_js - } -} - - -def remove_formatter(markdown_text): - pattern = r"^ *---[\s\S]*?---" - - replaced_text = re.sub(pattern, "", markdown_text) - - return replaced_text - - -def list_demos(dir_path: str, prefix=''): - result = [] - if (not os.path.isdir(dir_path)): - return result - for name in os.listdir(dir_path): - path = os.path.join(dir_path, name) - - if os.path.isfile(path): - result.append(prefix + name) - elif os.path.isdir(path): - sub_prefix = prefix + name + '/' - result.extend(list_demos(path, sub_prefix)) - - return result - - -def get_demo_modules(file_path: str): - import importlib.util - - demos = [ - demo for demo in list_demos( - os.path.join(os.path.dirname(file_path), "demos")) - if demo.endswith(".py") and not demo.startswith("__") - ] - demo_modules = {} - for demo in demos: - demo_name = demo.split(".")[0] - spec = importlib.util.spec_from_file_location( - "demo", os.path.join(os.path.dirname(file_path), "demos", demo)) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - demo_modules[demo_name] = module - return demo_modules - - -class Docs: - - def __init__(self, file_path: str, markdown_files: list = None): - self.file_path = file_path - self.demo_modules = get_demo_modules(file_path) - # default current directory - self.markdown_files = markdown_files if markdown_files else [ - filename for filename in os.listdir(os.path.dirname(file_path)) - if filename.endswith(".md") - ] - if is_modelscope_studio: - self.markdown_files = list( - filter( - lambda x: x.endswith("-zh_CN.md") or - (f"{'.'.join(x.split('.')[:-1])}-zh_CN.md" not in self. - markdown_files), self.markdown_files)) - else: - self.markdown_files = list( - filter(lambda x: not x.endswith("-zh_CN.md"), - self.markdown_files)) - - self.tabs = None - - def read_file(self, relative_path: str): - with open(os.path.join(os.path.dirname(self.file_path), relative_path), - "r") as f: - return f.read() - - def render_demo(self, - demo_name, - code_position='left', - prefix='', - suffix=''): - content = self.read_file(f"./demos/{demo_name}.py") - module = self.demo_modules[demo_name] - with gr.Accordion("Show Demo", open=False): - - def render_code(): - mgr.Markdown(f"""{prefix} -````python -{content} -```` -{suffix}""", - header_links=True, - custom_components=custom_components) - - if code_position == 'top': - with gr.Row(): - with gr.Column(): - render_code() - with gr.Row(): - if code_position == 'left': - with gr.Column(): - render_code() - with gr.Column(): - module.demo.render() - if code_position == 'right': - with gr.Column(): - render_code() - if code_position == 'bottom': - with gr.Row(): - with gr.Column(): - render_code() - - def render_markdown(self, - markdown_file, - on_tab_link_click: Callable = None, - components_tabs=None): - items = parse_markdown(remove_formatter(self.read_file(markdown_file)), - read_file=self.read_file) - for item in items: - if item["type"] == "text": - md = mgr.Markdown(item["value"], - header_links=True, - custom_components=custom_components, - preview=False) - deps = [dep for dep in [components_tabs, self.tabs] if dep] - if len(deps) > 0: - md.custom(fn=on_tab_link_click, outputs=deps) - elif item["type"] == "demo": - self.render_demo(item["name"], - prefix=item["prefix"], - suffix=item["suffix"], - code_position=item["code_position"]) - - def render(self, components_tabs=None): - - def tab_link_click(data: gr.EventData): - tab: str = data._data.get("value", {}).get("tab", '') - component_tab: str = data._data["value"].get("component_tab", '') - if tab and tabs: - return {tabs: gr.update(selected=tab)} - elif components_tabs and component_tab: - return {components_tabs: gr.update(selected=component_tab)} - - with gr.Blocks() as demo: - - if len(self.markdown_files) > 1: - with gr.Tabs() as tabs: - self.tabs = tabs - - for markdown_file in self.markdown_files: - tab_name = ".".join(markdown_file.split(".")[:-1]) - tab_name = tab_name.split("-zh_CN")[0] - with gr.TabItem(tab_name, id=tab_name): - self.render_markdown( - markdown_file, - on_tab_link_click=tab_link_click, - components_tabs=components_tabs) - elif (len(self.markdown_files) == 1): - self.render_markdown(self.markdown_files[0], - on_tab_link_click=tab_link_click, - components_tabs=components_tabs) - return demo diff --git a/components/legacy/Flow/README-zh_CN.md b/components/legacy/Flow/README-zh_CN.md deleted file mode 100644 index 0c4afb7e97c43aaa3d69acdaacdae787a32d4892..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/README-zh_CN.md +++ /dev/null @@ -1,109 +0,0 @@ -# Flow - -基于 [reactflow](https://reactflow.dev/) 实现的 Flow 组件。 - -- 支持通过 schema 自定义渲染节点 -- 支持自定义节点的渲染组件,并与 Python 事件交互 - -## 如何使用 - -### 定义 schema 节点 (重要) - -详见:Define Schema - -### 基本使用 - - - -### 组件配置项 - - - -### 自定义节点类型(高阶用法,需要了解前端知识) - - - -## API 及参数列表 - -### value - -接口定义: - -```python -class NodePosition(GradioModel): - x: Optional[int] = 0 - y: Optional[int] = 0 - - -class Node(GradioModel): - id: Optional[str] = None - name: str - title: Optional[str] = None - position: Optional[Union[NodePosition, dict]] = None - data: Optional[dict] = None - -class EdgePort(GradioModel): - attr: Optional[str] = None - attrItemIndex: Optional[int] = None - handleIndex: Optional[int] = None - -class Edge(GradioModel): - id: Optional[str] = None - source: str - target: str - sourcePort: Optional[Union[EdgePort, dict]] = None - targetPort: Optional[Union[EdgePort, dict]] = None - - -class FlowData(GradioModel): - nodes: Optional[List[Union[Node, dict]]] = [] - edges: Optional[List[Union[Edge, dict]]] = [] - -``` - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ------------------- | --------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| height | int \| str | 600 | Flow 组件高度。 | -| sync_on_data_change | bool | None | 是否仅在数据更改时同步 Python 值(例如:节点属性、节点计数、边缘计数、连接端口等,不包括节点位置)。 如果您想要更好的页面性能而不是完整数据同步,则应将其设置为 True。 | -| schema | FlowSchemaDict \| dict | None | 定义 Flow 组件的 nodes 与 edges。 | -| show_sidebar | bool | True | 是否展示侧 Flow 组件侧边栏。 | -| show_minimap | bool | True | 是否展示侧 Flow 组件小地图。 | -| show_controls | bool | True | 是否展示侧Flow 组件控制栏。 | -| background_props | BackgroundPropsDict \| dict CustomComponentDict 定义见下方 | None | 修改 Flow组件背景,详见 BackgroundPropsDict 类型。 | -| min_zoom | int | 0.1 | Flow 组件最小缩放倍率。 | -| max_zoom | int | 2 | Flow 组件最大缩放倍率。 | -| custom_components | dict\[str, CustomComponentDict\] CustomComponentDict 定义见下方 | None | 支持用户自定义节点类型,并通过 js 控制渲染样式与触发 python 事件。 | - -**BackgroundPropsDict 定义如下** - -```python -class BackgroundPropsDict(TypedDict): - color: Optional[str] - className: Optional[str] - # The gap between patterns. Passing in a tuple allows you to control the x and y gap independently. - gap: Optional[Union[int, Tuple[int, int]]] - # The radius of each dot or the size of each rectangle if BackgroundVariant.Dots or BackgroundVariant.Cross is used. This defaults to 1 or 6 respectively, or ignored if BackgroundVariant.Lines is used. - size: Optional[int] - offset: Optional[int] - lineWidth: Optional[int] - variant: Optional[Literal['dots', 'lines', 'cross']] -``` - -**CustomComponentDict 定义如下** - -```python -class CustomComponentDict(TypedDict): - props: Optional[List[str]] - template: Optional[str] - js: Optional[str] -``` - -### event listeners - -| 事件 | 描述 | -| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `mgr.Flow.change(fn, ···)` | 当 value 更新时触发,如果 sync_on_data_change 值为 True 时,此时 flow 的实际数据可能并不是实时的,建议监听 data_change 事件。 | -| `mgr.Flow.data_change(fn, ···)` | 当在数据更改时触发(例如:节点属性、节点计数、边缘计数、连接端口等,不包括节点位置) | -| `mgr.Flow.custom(fn, ···)` | 自定义标签触发事件时触发,EventData 为:
- id:当前触发节点 id。
- node:当前触发节点类型。
- attr:当前触发节点属性。
- index:当前触发节点属性索引,当节点属性为 list 时有值。
- value:自定义传入的值。 | diff --git a/components/legacy/Flow/README.md b/components/legacy/Flow/README.md deleted file mode 100644 index b7ebf875a609b8127407d48177bb836b692f4d46..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/README.md +++ /dev/null @@ -1,108 +0,0 @@ -# Flow - -A Flow component implemented based on [reactflow](https://reactflow.dev/). - -- Supports customization of node rendering through a schema. -- Allows for custom node render components with interaction from Python. - -## How to Use - -### Defining Schema Nodes (Important) - -See: Define Schema - -### Basic Usage - - - -### Component Options - - - -### Custom Node Types (Advanced usage, requires frontend knowledge) - - - -## API and Parameter List - -### value - -Interface definition: - -```python -class NodePosition(GradioModel): - x: Optional[int] = 0 - y: Optional[int] = 0 - - -class Node(GradioModel): - id: Optional[str] = None - name: str - title: Optional[str] = None - position: Optional[Union[NodePosition, dict]] = None - data: Optional[dict] = None - -class EdgePort(GradioModel): - attr: Optional[str] = None - attrItemIndex: Optional[int] = None - handleIndex: Optional[int] = None - -class Edge(GradioModel): - id: Optional[str] = None - source: str - target: str - sourcePort: Optional[Union[EdgePort, dict]] = None - targetPort: Optional[Union[EdgePort, dict]] = None - - -class FlowData(GradioModel): - nodes: Optional[List[Union[Node, dict]]] = [] - edges: Optional[List[Union[Edge, dict]]] = [] -``` - -### props - -| Attribute | Type | Default Value | Description | -| ------------------- | --------------------------------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| height | int \| str | 600 | Height of the Flow component. | -| sync_on_data_change | bool | None | Whether to sync the Python value only on data change (e.g., node attributes, node count, edge count, connection ports, not including node positions). If you want better page performance without full data sync, set this to True. | -| schema | FlowSchemaDict \| dict | None | Defines the nodes and edges of the Flow component. | -| show_sidebar | bool | True | Whether to display the sidebar in the Flow component. | -| show_minimap | bool | True | Whether to display the minimap in the Flow component. | -| show_controls | bool | True | Whether to display the controls bar in the Flow component. | -| background_props | BackgroundPropsDict \| dict BackgroundPropsDict definition below | None | Modify the background of the Flow component, see the BackgroundPropsDict type. | -| min_zoom | int | 0.1 | Minimum zoom level for the Flow component. | -| max_zoom | int | 2 | Maximum zoom level for the Flow component. | -| 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. | - -**BackgroundPropsDict definition:** - -```python -class BackgroundPropsDict(TypedDict): - color: Optional[str] - className: Optional[str] - # The gap between patterns. Passing in a tuple allows you to control the x and y gap independently. - gap: Optional[Union[int, Tuple[int, int]]] - # The radius of each dot or the size of each rectangle if BackgroundVariant.Dots or BackgroundVariant.Cross is used. This defaults to 1 or 6 respectively, or ignored if BackgroundVariant.Lines is used. - size: Optional[int] - offset: Optional[int] - lineWidth: Optional[int] - variant: Optional[Literal['dots', 'lines', 'cross']] -``` - -**CustomComponentDict definition:** - -```python -class CustomComponentDict(TypedDict): - props: Optional[List[str]] - template: Optional[str] - js: Optional[str] -``` - -### Event Listeners - -| Event | Description | -| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `mgr.Flow.change(fn, ...)` | Triggers when the `value` updates. If `sync_on_data_change` is True, the actual data at this point might not be up-to-date; consider listening to the `data_change` event instead. | -| `mgr.Flow.data_change(fn, ...)` | Triggers when there's a data change (e.g., node attributes, node count, edge count, connection ports), but not node positions. | -| `mgr.Flow.custom(fn, ...)` | Triggers when a custom label event occurs. The `EventData` includes:
- `id`: ID of the currently triggered node.
- `node`: Type of the currently triggered node.
- `attr`: Attributes of the currently triggered node.
- `index`: Index of the attribute if it's a list.
- `value`: Custom passed-in value. | diff --git a/components/legacy/Flow/define_schema-zh_CN.md b/components/legacy/Flow/define_schema-zh_CN.md deleted file mode 100644 index dfd15303d31764b01c8170275d0d91b43f61dfe5..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/define_schema-zh_CN.md +++ /dev/null @@ -1,266 +0,0 @@ -# Define Schema - -在使用 Flow 组件前,需要预先创建 Schema 定义 node 节点,schema 类型定义如下: - -```ts -export interface FlowSchema { - nodes: FlowNodeSchema[]; -} - -export interface FlowNodeSchema { - /** - * 作为节点的唯一标识。必填。 - */ - name: string; - - /** - * 节点显示图标。 - */ - icon?: string; - - /** - * 节点标题,如果没有提供则默认使用 name。 - */ - title?: string; - - /** - * 节点的简短描述。 - */ - description?: string; - - /** - * 节点宽度。 - */ - width?: number; - - /** - * 节点高度。 - */ - height?: number; - - /** - * 显示/隐藏工具栏(删除、复制、重命名等)。 - * @default true - */ - show_toolbar?: boolean; - - /** - * 启用/禁止添加更多此类节点实例。 - * @default true - */ - addable?: boolean; - - /** - * 启用/禁止删除现有此类节点实例。 - * @default true - */ - deletable?: boolean; - - /** - * 可以同时存在的此类节点的最大数量。 - */ - max?: number; - - /** - * 可以同时存在的此类节点的最小数量。 - */ - min?: number; - - /** - * 节点连接端口的配置。 - */ - ports?: { - /** - * 节点作为连接的源端口。 - * @default ['right'] - */ - source?: Position[]; - - /** - * 允许此节点 source 端口连接到的其他节点或属性。默认为所有节点和属性。 - * @default [] - */ - sourceConnections?: PortConnection[]; - - /** - * 节点作为连接的目标端口。 - * @default ['left'] - */ - target?: Position[]; - - /** - * 其他允许连接到此节点 target 端口的节点或属性。默认为所有节点和属性 - * @default [] - */ - targetConnections?: PortConnection[]; - }; - - /** - * 节点的属性配置。 - */ - attrs?: FlowNodeAttrSchema[]; - - /** - * 创建新实例时节点属性的初始值。 - */ - template?: { - /** - * 在`attrs`字段中与其名称相对应的属性值,例如 { "a": 1, "b": 2 }。 - */ - attrs?: Attrs; - }; -} - -export interface FlowNodeAttrSchema { - /** - * 唯一的属性名称,在 node data 中用作 key。必填。 - */ - name: string; - - /** - * 属性标题,如果没有提供则默认使用 name。 - */ - title?: string; - - /** - * 属性的简短描述 - */ - description?: string; - - /** - * 禁用用户编辑属性值。默认情况下,属性是可编辑的。 - * @default false - */ - disabled?: boolean; - - /** - * 属性输入类型。可以是内置的 Ant Design 组件或自定义组件之一。默认为'input'。 - * @default 'input' - */ - type?: - | 'input' - | 'textarea' - | 'radio' - | 'checkbox' - | 'number' - | 'select' - | 'switch' - | 'upload' - // 自定义 - | (string & {}); - - /** - * 针对所选组件类型的特定配置选项,支持 Ant Design 组件({@link https://ant.design/components/overview/})或自定义组件的属性。 - */ - props?: Record; - - /** - * 节点属性连接端口的配置。 - */ - ports?: { - /** - * 节点属性作为连接的源端口。 - * @default [] - */ - source?: Position[]; - - /** - * 允许此节点属性 source 端口连接到的其他节点或属性。 - * @default [] - */ - sourceConnections?: PortConnection[]; - - /** - * 节点属性作为连接的目标端口。 - * @default [] - */ - target?: Position[]; - - /** - * 其他允许连接到此节点属性 target 端口的节点或属性。 - * @default [] - */ - targetConnections?: PortConnection[]; - }; - - /** - * 表示该属性是否为列表值。 - * @default false - */ - list?: - | boolean - | { - /** - * 列表中每个 item 的端口配置。 - */ - ports?: { - /** - * 列表 item 作为连接的源端口。 - * @default [] - */ - source?: Position[]; - - /** - * 允许此列表 item source 端口连接到的其他节点或属性。 - * @default [] - */ - sourceConnections?: PortConnection[]; - - /** - * 列表 item 作为连接的目标端口。 - */ - target?: Position[]; - - /** - * 其他允许连接到此列表 item target 端口的节点或属性。 - */ - targetConnections?: PortConnection[]; - }; - - /** - * 列表中的最小 item 数量。 - */ - min?: number; - - /** - * 列表中的最大 item 数量。 - */ - max?: number; - }; - - /** - * 启用/禁用手风琴 UI。 - * @default true - */ - accordion?: boolean; - - /** - * 指定该属性值是否为必填项。默认情况为非必填项。 - * @default false - */ - required?: - | boolean - | { - message?: string; - }; - - /** - * 使用 JSON schema 验证属性值。 - */ - json_schema_validator?: Record; -} -``` - -你可以通过 json 文件(推荐)或直接在 Python 端通过导出类型定义: - -- 通过 json 定义: - -```json - -``` - -- 通过 Python 定义: - -```python - -``` diff --git a/components/legacy/Flow/define_schema.md b/components/legacy/Flow/define_schema.md deleted file mode 100644 index bb2c78c17655240097841083b9feec32981b13a5..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/define_schema.md +++ /dev/null @@ -1,262 +0,0 @@ -# Define Schema - -Before using the Flow component, need to create a Schema definition node in advance. The schema type is defined as follows: - -```ts -export interface FlowSchema { - nodes: FlowNodeSchema[]; -} - -export interface FlowNodeSchema { - /** - * As a unique identifier for the node. Mandatory. - */ - name: string; - - /** - * Display icon for the node. - */ - icon?: string; - - /** - * Display title for the node, defaults to the node name if not provided. - */ - title?: string; - - /** - * A short description of the node's purpose. - */ - description?: string; - - /** - * Width of the node. - */ - width?: number; - - /** - * Height of the node. - */ - height?: number; - - /** - * Shows/hides the toolbar (delete, copy, rename, etc.). - * @default true - */ - show_toolbar?: boolean; - - /** - * Enables/disables adding more instances of this node. - * @default true - */ - addable?: boolean; - - /** - * Enables/disables deleting existing instances of this node. - * @default true - */ - deletable?: boolean; - - /** - * Maximum number of this node type that can exist simultaneously. - */ - max?: number; - - /** - * Minimum number of this node type that must exist simultaneously. - */ - min?: number; - - /** - * Configurations for the node's connection ports. - */ - ports?: { - /** - * Source ports for the node as a connection. - * @default ['right'] - */ - source?: Position[]; - - /** - * Allowed the source ports of this node to connect to other nodes or attributes. Defaults to all nodes and attributes - */ - sourceConnections?: PortConnection[]; - - /** - * Target ports for the node as a connection - * @default ['left'] - */ - target?: Position[]; - - /** - * Allowed other nodes or attributes allowed to connect to the target ports of this node. Defaults to all nodes and attributes - * - */ - targetConnections?: PortConnection[]; - }; - - /** - * Configuration of the node's attributes. - */ - attrs?: FlowNodeAttrSchema[]; - - /** - * Initial values for the node's attributes when creating a new instance. - */ - template?: { - /** - * Attribute values corresponding to their names in the `attrs` field, e.g., `{ "a": 1, "b": 2 }`. - */ - attrs?: Attrs; - }; -} - -export interface FlowNodeAttrSchema { - /** - * Unique attribute name used as a key in the node data. Mandatory. - */ - name: string; - - /** - * Display title for the attribute, defaults to the attribute name if not provided. - */ - title?: string; - - /** - * A brief explanation about the attribute purpose. - */ - description?: string; - - /** - * Disables user editing of the attribute value. By default, attributes are editable. - * @default false - */ - disabled?: boolean; - - /** - * Attribute input type. Can be one of the built-in Ant Design components or a custom component. Defaults to 'input'. - * @default 'input' - */ - type?: - | 'input' - | 'textarea' - | 'radio' - | 'checkbox' - | 'number' - | 'select' - | 'switch' - | 'upload' - // custom - | (string & {}); - - /** - * Configuration options specific to the chosen component type, supporting Ant Design ({@link https://ant.design/components/overview/}) or custom component properties. - */ - props?: Record; - - /** - * Configurations for the node attribute ports. - */ - ports?: { - /** - * Source ports for the attribute as a connection. - * @default [] - */ - source?: Position[]; - - /** - * Allowed the source ports of this attribute to connect to other nodes or attributes. Defaults to all nodes and attributes - */ - sourceConnections?: PortConnection[]; - - /** - * Target ports for the attribute as a connection - * @default [] - */ - target?: Position[]; - - /** - * Allowed other nodes or attributes allowed to connect to the target ports of this attribute. Defaults to all nodes and attributes - */ - targetConnections?: PortConnection[]; - }; - - /** - * Indicates whether the attribute is a list. - * @default false - */ - list?: - | boolean - | { - /** - * Port configurations for each item in the list. - */ - ports?: { - /** - * Source ports for the list item as a connection. - * @default [] - */ - source?: Position[]; - - /** - * Allowed the source ports of this list item to connect to other nodes or attributes. Defaults to all nodes and attributes - */ - sourceConnections?: PortConnection[]; - - /** - * Target ports for the list item as a connection - */ - target?: Position[]; - - /** - * Allowed other nodes or attributes allowed to connect to the target ports of this list item. Defaults to all nodes and attributes - */ - targetConnections?: PortConnection[]; - }; - - /** - * Minimum number of items in the list. - */ - min?: number; - - /** - * Maximum number of items in the list. - */ - max?: number; - }; - - /** - * Enable/disable accordion UI. - * @default true - */ - accordion?: boolean; - - /** - * Specifies if the attribute value is mandatory. By default, attributes are optional. - * @default false - */ - required?: - | boolean - | { - message?: string; - }; - - /** - * Validates attribute values using JSON schema. - */ - json_schema_validator?: Record; -} -``` - -You can define the schema by a json file (recommended) or directly on the Python by the exported types: - -- Defined by json: - -```json - -``` - -- Defined by Python: - -```python - -``` diff --git a/components/legacy/Flow/demos/basic.py b/components/legacy/Flow/demos/basic.py deleted file mode 100644 index 48f18eff6e59b11bd40890a7e4d25a5a42799074..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/demos/basic.py +++ /dev/null @@ -1,35 +0,0 @@ -import json -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr -from modelscope_studio.components.legacy.Flow import Edge, Node - -with open((os.path.join(os.path.dirname(__file__), - "../schema/agents_schema.json"))) as f: - schema = json.load(f) - -# define the initial value of the flow -data = { - "nodes": [ - Node(id="start-node", name="start", position=dict(x=0, y=0)), - Node(id="initial-agent-node", - name="agent", - position=dict(x=200, y=0), - data=dict(condition=[''])) - ], - "edges": [Edge(source='start-node', target="initial-agent-node")], -} - - -def on_data_change(_flow): - print(_flow) - - -with gr.Blocks() as demo, ms.Application(): - flow = mgr.Flow(value=data, schema=schema, sync_on_data_change=True) - flow.data_change(fn=on_data_change, inputs=[flow]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Flow/demos/component_options.py b/components/legacy/Flow/demos/component_options.py deleted file mode 100644 index 79ccb9f0096791420ec47d2b5a95d87af812de34..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/demos/component_options.py +++ /dev/null @@ -1,109 +0,0 @@ -import json -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr -from modelscope_studio.components.legacy.Flow import (BackgroundPropsDict, - Edge, Node) - -with open((os.path.join(os.path.dirname(__file__), - "../schema/agents_schema.json"))) as f: - schema = json.load(f) - -# define the initial value of the flow -data = { - "nodes": [ - Node(id="start-node", name="start", position=dict(x=0, y=0)), - Node(id="initial-agent-node", - name="agent", - position=dict(x=200, y=0), - data=dict(condition=[''])) - ], - "edges": [Edge(source='start-node', target="initial-agent-node")], -} - - -def on_data_change(_flow): - print(_flow) - - -flow_props = ["show_sidebar", "show_minimap", "show_controls"] - - -def on_change(_flow_config, _bgc_variant, _bgc_color, _bgc_bg_color, _bgc_gap, - _bgc_size, _bgc_offset, _bgc_line_width): - new_props = {} - new_background_props = { - "variant": _bgc_variant, - "bgColor": _bgc_bg_color, - "color": _bgc_color, - "gap": _bgc_gap, - "size": _bgc_size, - "offset": _bgc_offset, - 'lineWidth': _bgc_line_width - } - for choice in flow_props: - if choice in _flow_config: - new_props[choice] = True - else: - new_props[choice] = False - return gr.update(**new_props, background_props=new_background_props) - - -with gr.Blocks() as demo, ms.Application(): - with gr.Accordion(label="Flow Options"): - flow_config = gr.CheckboxGroup( - container=False, - value=["show_sidebar", "show_minimap", "show_controls"], - choices=flow_props) - with gr.Accordion(label="Background Props"): - with gr.Row(): - with gr.Column(): - bgc_variant = gr.Radio(choices=["dots", "lines", "cross"], - label="variant", - value="dots") - with gr.Column(): - bgc_color = gr.ColorPicker(label="color", value="") - with gr.Column(): - bgc_bg_color = gr.ColorPicker(label="bgColor", value="") - with gr.Column(): - bgc_gap = gr.Slider(label="gap", value=28) - with gr.Column(): - bgc_size = gr.Slider(label="size", - value=1, - maximum=10, - step=1) - with gr.Column(): - bgc_offset = gr.Slider(label="offset", - value=1, - step=1, - maximum=10) - with gr.Column(): - bgc_line_width = gr.Slider(label="lineWidth", - value=1, - step=1, - maximum=10) - - flow = mgr.Flow(value=data, - schema=schema, - show_controls=True, - show_minimap=True, - show_sidebar=True, - sync_on_data_change=True, - background_props=BackgroundPropsDict(variant='dots')) - gr.on(triggers=[ - flow_config.change, bgc_variant.change, bgc_color.change, - bgc_bg_color.change, bgc_gap.change, bgc_size.change, - bgc_offset.change, bgc_line_width.change - ], - fn=on_change, - inputs=[ - flow_config, bgc_variant, bgc_color, bgc_bg_color, bgc_gap, - bgc_size, bgc_offset, bgc_line_width - ], - outputs=[flow]) - flow.data_change(fn=on_data_change, inputs=[flow]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Flow/demos/custom_node_type.py b/components/legacy/Flow/demos/custom_node_type.py deleted file mode 100644 index d2b50b1e5e8e7336d0c2407b4db6133d82de6473..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/demos/custom_node_type.py +++ /dev/null @@ -1,69 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr -from modelscope_studio.components.legacy.Flow import (FlowSchemaDict, Node, - NodeSchemaAttributeDict, - NodeSchemaDict) - - -def on_data_change(_flow): - print(_flow) - - -def on_custom(data: gr.EventData): - print(data._data) - - -custom_components = { - "my-input": { - "js": - """ -(props, cc, { el, theme, onMount, onUpdate }) => { - onMount(() => { - el.innerHTML = `` - const input = el.querySelector('input') - input.style.color = theme === 'dark' ? 'white' : 'black' - input.style.backgroundColor = theme === 'dark' ? 'black' : 'white' - input.addEventListener('change', (e) => { - cc.dispatch(e.target.value) - }) - }) - // props update - onUpdate( - () => { - const input = el.querySelector('input') - input.setAttribute('value', props.value || '') - }, - // By default, the callback will not be called when the component is being mounted. Set `callAfterMount` to true to enable it. - { callAfterMount: true } - ) -} -""" - } -} - -schema = FlowSchemaDict(nodes=[ - NodeSchemaDict(name="my-input-node", - title="MyInputNode", - attrs=[NodeSchemaAttributeDict(name="a", type="my-input")]) -]) - -data = { - "nodes": [ - Node(name="my-input-node", - position=dict(x=0, y=0), - data=dict(a='Hello')) - ] -} - -with gr.Blocks() as demo, ms.Application(): - flow = mgr.Flow(value=data, - schema=schema, - custom_components=custom_components, - sync_on_data_change=True) - flow.data_change(fn=on_data_change, inputs=[flow]) - # called when custom component dispatch event - flow.custom(fn=on_custom) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Flow/schema/agents_schema.json b/components/legacy/Flow/schema/agents_schema.json deleted file mode 100644 index 3134b2dc35895f14c0f1ff11061db9a13836f0f7..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/schema/agents_schema.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/modelscope/modelscope-studio/main/frontend/Flow/schema.json", - "nodes": [ - { - "max": 1, - "min": 1, - "addable": false, - "show_toolbar": false, - "name": "start", - "title": "Start", - "ports": { - "source": ["right"], - "target": [] - } - }, - { - "icon": "https://img.alicdn.com/imgextra/i4/O1CN01fvt4it25rEZU4Gjso_!!6000000007579-2-tps-128-128.png", - "name": "agent", - "title": "Agent Node", - "description": "Agent Flow Node", - "ports": { - "target": ["left"], - "source": [] - }, - "attrs": [ - { - "name": "prompt", - "title": "Agent Prompt", - "type": "textarea", - "required": { - "message": "Agent Prompt is required" - } - }, - { - "name": "tool", - "title": "Tools", - "type": "select", - "props": { - "mode": "multiple", - "options": [ - { "label": "Wanx Image Generation", "value": "image_gen" }, - { "label": "Code Interpreter", "value": "code_interpreter" }, - { "label": "Web Browsing", "value": "web_browser" } - ] - } - }, - { - "name": "condition", - "title": "Jump Condition", - "list": { - "min": 1, - "ports": { - "source": ["right"] - } - }, - "accordion": false - } - ], - "template": { - "attrs": { - "condition": [""] - } - } - } - ] -} diff --git a/components/legacy/Flow/schema/agents_schema.py b/components/legacy/Flow/schema/agents_schema.py deleted file mode 100644 index d80f78483713a654899a9bcfe73ee836e8c2ff6a..0000000000000000000000000000000000000000 --- a/components/legacy/Flow/schema/agents_schema.py +++ /dev/null @@ -1,59 +0,0 @@ -import os - -from modelscope_studio.components.legacy.Flow import ( - FlowSchemaDict, NodeSchemaAttributeDict, NodeSchemaAttributeListDict, - NodeSchemaAttributeRequiredDict, NodeSchemaDict, NodeSchemaPortsDict, - NodeSchemaTemplateDict) - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -schema = FlowSchemaDict(nodes=[ - NodeSchemaDict(max=1, - min=1, - addable=False, - show_toolbar=False, - name="start", - title="Start", - ports=NodeSchemaPortsDict(source=['right'], target=[])), - NodeSchemaDict( - icon=resolve_assets('./bot.jpeg'), - name="agent", - title="Agent Node", - description="Agent Flow Node", - ports=NodeSchemaPortsDict(source=[], target=['left']), - attrs=[ - NodeSchemaAttributeDict(name="prompt", - title="Agent Prompt", - type='textarea', - required=NodeSchemaAttributeRequiredDict( - message="Agent Prompt is required")), - NodeSchemaAttributeDict(name="tool", - title="Tools", - type="select", - props={ - "mode": - "multiple", - "options": [{ - "label": "Wanx Image Generation", - "value": "image_gen" - }, { - "label": "Code Interpreter", - "value": "code_interpreter" - }, { - "label": "Web Browsing", - "value": "web_browser" - }] - }), - NodeSchemaAttributeDict( - name="condition", - title="Jump Condition", - list=NodeSchemaAttributeListDict( - min=1, ports=NodeSchemaPortsDict(source=['right'])), - accordion=False) - ], - template=NodeSchemaTemplateDict(attrs=dict(condition=['']))) -]) diff --git a/components/legacy/Lifecycle/README-zh_CN.md b/components/legacy/Lifecycle/README-zh_CN.md deleted file mode 100644 index 2a110cbdbbcd3934c63fd412764634c46b1925bd..0000000000000000000000000000000000000000 --- a/components/legacy/Lifecycle/README-zh_CN.md +++ /dev/null @@ -1,53 +0,0 @@ -# Lifecycle - -生命周期组件,用于获取当前用户的环境信息。 - -- 获取当前用户的语言、页面主题、user agent 和屏幕状态。 -- 监听页面行为并触发相应事件(页面加载、尺寸变化、页面关闭等)。 - -## 如何使用 - -### 基本使用 - - - -### 自动适配用户语言环境 - - - -### 根据用户界面主题返回不同权重内容 - - - -## API 及参数列表 - -### value - -接口定义: - -```python -class LifecycleScreenData(GradioModel): - width: float - height: float - scrollX: float - scrollY: float - - -class LifecycleData(GradioModel): - screen: LifecycleScreenData - language: str - theme: str - userAgent: str -``` - -### props - -该组件不支持传入 props。 - -### event listeners - -| 事件 | 描述 | -| -------------------------------- | --------------------------------------------------------------------- | -| `mgr.Lifecycle.mount(fn, ···)` | 用户页面加载时触发,EventData 为当前组件 value 的 dict 类型值。 | -| `mgr.Lifecycle.unmount(fn, ···)` | 用户页面关闭时触发,EventData 为当前组件 value 的 dict 类型值。 | -| `mgr.Lifecycle.resize(fn, ···)` | 自定义标签触发事件时触发,EventData 为当前组件 value 的 dict 类型值。 | diff --git a/components/legacy/Lifecycle/README.md b/components/legacy/Lifecycle/README.md deleted file mode 100644 index 66c646f9d311a6702078e4cb45cb147308e22a80..0000000000000000000000000000000000000000 --- a/components/legacy/Lifecycle/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Lifecycle - -A Lifecycle component for getting the current user's environment information. - -- Get the current user's language, page theme, user agent, and screen state. -- Listen to page actions and trigger corresponding events (page loading, size changes, page closing, etc.). - -## How to Use - -### Basic Usage - - - -### Automatically Adapt to User Language Environment - - - -### Return Different Weighted Content Based on UI Theme - - - -## API and Parameter List - -### Value - -Interface definition: - -```python -class LifecycleScreenData(GradioModel): - width: float - height: float - scrollX: float - scrollY: float - - -class LifecycleData(GradioModel): - screen: LifecycleScreenData - language: str - theme: str - userAgent: str -``` - -### Props - -This component does not support passing in props. - -### Event Listeners - -| Event | Description | -| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `mgr.Lifecycle.mount(fn, ···)` | Triggered when the user's page loads. The EventData is a dictionary type value of the current component's value. | -| `mgr.Lifecycle.unmount(fn, ···)` | Triggered when the user's page closes. The EventData is a dictionary type value of the current component's value. | -| `mgr.Lifecycle.resize(fn, ···)` | Triggered when custom labels trigger events. The EventData is a dictionary type value of the current component's value. | diff --git a/components/legacy/Lifecycle/demos/basic.py b/components/legacy/Lifecycle/demos/basic.py deleted file mode 100644 index dc35dd8a38fae9d9def1b8dfe1494117361fe93a..0000000000000000000000000000000000000000 --- a/components/legacy/Lifecycle/demos/basic.py +++ /dev/null @@ -1,28 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def mount(e: gr.EventData): - # current page state - print("onMount", e._data) - - -def resize(e: gr.EventData): - print("onResize", e._data) - - -def onUnmount(e: gr.EventData): - print("onUnmount", e._data) - - -with gr.Blocks() as demo, ms.Application(): - gr.Markdown("The Lifecycle component will not be rendered on the page.") - lifecycle = mgr.Lifecycle() - # listen to the page lifecycle - lifecycle.mount(fn=mount) - lifecycle.resize(fn=resize) - lifecycle.unmount(fn=onUnmount) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Lifecycle/demos/language_adaptation.py b/components/legacy/Lifecycle/demos/language_adaptation.py deleted file mode 100644 index c6f53551f373fbcd43bc9d09264dd11c07633370..0000000000000000000000000000000000000000 --- a/components/legacy/Lifecycle/demos/language_adaptation.py +++ /dev/null @@ -1,41 +0,0 @@ -import time - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -messages = { - 'en': { - "hello": "Hello" - }, - 'en-US': { - "hello": "Hello" - }, - 'zh-CN': { - "hello": "你好" - } -} - -default_lang = "en" - - -def mount(_lifecycle, _state): - lang = _lifecycle.language - if (lang in messages): - _state["current_lang"] = lang - yield 'Switch Language...', _state - time.sleep(2) - yield messages[lang]["hello"], _state - - -with gr.Blocks() as demo, ms.Application(): - lifecycle = mgr.Lifecycle() - state = gr.State({"current_lang": default_lang}) - markdown = gr.Markdown(value=messages[default_lang]["hello"]) - - lifecycle.mount(fn=mount, - inputs=[lifecycle, state], - outputs=[markdown, state]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Lifecycle/demos/theme_adaptation.py b/components/legacy/Lifecycle/demos/theme_adaptation.py deleted file mode 100644 index e1b87b6b72513e390a64f438a495086eff7c7960..0000000000000000000000000000000000000000 --- a/components/legacy/Lifecycle/demos/theme_adaptation.py +++ /dev/null @@ -1,28 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def mount(_lifecycle, _state): - _state["theme"] = _lifecycle.theme - yield _state - - -def fn(_state): - theme = _state["theme"] - color = '000/fff' if theme == 'dark' else 'fff/000' - yield gr.update( - value=f"https://dummyimage.com/200x100/{color}.png&text={theme}") - - -with gr.Blocks() as demo, ms.Application(): - lifecycle = mgr.Lifecycle() - state = gr.State({"theme": "light"}) - btn = gr.Button() - image = gr.Image() - - lifecycle.mount(fn=mount, inputs=[lifecycle, state], outputs=[state]) - btn.click(fn=fn, inputs=[state], outputs=[image]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/README-zh_CN.md b/components/legacy/Markdown/README-zh_CN.md deleted file mode 100644 index 00b406acdd547c21cad85e58e07f416a34ca9e06..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/README-zh_CN.md +++ /dev/null @@ -1,97 +0,0 @@ -# Markdown - -升级版的 gradio Markdown。 - -- 支持输出多模态内容(音频、视频、图片、文本) -- 内置标签(chart、select-box、accordion) -- 支持自定义渲染组件,并与 Python 事件交互 - -## 如何使用 - -### 基本使用 - - - -### 多模态 & 支持本地文件的展示 - - - -### 支持手风琴内容展示 - -在返回的内容中加入 `accordion` 标签,更多用法详见 accordion - - - -### 支持用户选择交互 - -在返回的内容中加入 `select-box` 标签,更多用法详见 select-box - - - -### 支持图表展示 - -在返回的内容中加入 `chart` 标签,更多用法详见 chart - - - -### 自定义标签(高阶用法,需要了解前端知识) - - - -#### 引入 js - - - -template只能做简单的变量替换,如果想要引入更多自定义的行为,如条件判断、循环渲染等,请使用 js 控制 el 自行处理,下面是简单的示例: - - - -custom_select.js - -```js - -``` - - - - -#### 与 Python 交互 - -在 js 中可以使用`cc.dispatch`触发 Python 侧监听的`custom`事件,以前面的custom_select.js为例,我们在前端调用了`cc.dispatch(options[i])`,则会向 Python 侧同时发送通知。 - - - -## API 及参数列表 - -以下 API 均为在原有 gradio Markdown 外的额外拓展参数。 - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ----------------------------- | --------------------------------------------------------------- | ------ | --------------------------------------------------------------------------- | -| enable_base64 | bool | False | 是否支持渲染的内容为 base64,因为直接渲染 base64 有安全问题,默认为 False。 | -| enable_latex | bool | True | 是否支持 Latex 公式渲染 | -| latex_single_dollar_delimiter | bool | True | 是否支持单`$`符号在 Latex 公式中渲染 | -| preview | bool | True | 是否开启图片预览功能 | -| custom_components | dict\[str, CustomComponentDict\] CustomComponentDict 定义见下方 | None | 支持用户定义自定义标签,并通过 js 控制标签渲染样式与触发 python 事件。 | - -**CustomComponentDict 定义如下** - -```python -class CustomComponentDict(TypedDict): - props: Optional[List[str]] - template: Optional[str] - js: Optional[str] -``` - -### 内置的自定义标签 - -- select-box -- accordion -- chart - -### event listeners - -| 事件 | 描述 | -| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- | -| `mgr.Markdown.custom(fn, ···)` | 自定义标签触发事件时触发,EventData 为:
- tag_index:当前触发标签的 index。
- value:自定义传入的值。 | diff --git a/components/legacy/Markdown/README.md b/components/legacy/Markdown/README.md deleted file mode 100644 index 9a705158481c04a05043a751f081e737a64f9bea..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# Markdown - -Upgraded gradio Markdown. - -- Supports output of multimodal content (audio, video, image, text) -- Built-in tags (chart, select-box, accordion) -- Supports custom rendering components and interaction with Python events - -## How to Use - -### Basic Usage - - - -### Multimodal & Support for Local File Display - - - -### Support for Accordion Content Display - -Include the `accordion` tag in the returned content. For more usage details, see accordion - - -### Support for User Selection Interaction - -Include the `select-box` tag in the returned content. For more usage details, see select-box - - -### Support for Chart Display - -Include the `chart` tag in the returned content. For more usage details, see chart - - -### Custom Tags (Advanced Usage, Requires Frontend Knowledge) - - - -#### Import JS - - -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: - - -custom_select.js - -```js - -``` - - - - -#### Interaction with Python - -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. - - -## API and Parameter List - -The following APIs are additional extended parameters beyond the original gradio Markdown. - -### props - -| Attribute | Type | Default Value | Description | -| ----------------------------- | ------------------------------------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------- | -| enable_base64 | bool | False | Whether to support rendering content as base64, since rendering base64 is unsafe, the default is False. | -| preview | bool | True | Whether to enable image preview functionality. | -| enable_latex | bool | True | Whether to enable LaTeX rendering. | -| latex_single_dollar_delimiter | bool | True | Whe ther to enable single dollar delimiter `$` for LaTeX rendering. | -| 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. | -| | - -**CustomComponent definition is as follows:** - -```python -class CustomComponentDict(TypedDict): - props: Optional[List[str]] - template: Optional[str] - js: Optional[str] -``` - -### Built-in Custom Tags - -- select-box -- accordion -- chart - -### Event Listeners - -| Event | Description | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `mgr.Markdown.custom(fn, ···)` | Triggered when a custom tag event occurs. EventData is:
- tag: The current tag that triggered the event.
- tag_index: The index of the current triggered tag.
- value: The custom value passed in. | diff --git a/components/legacy/Markdown/app.py b/components/legacy/Markdown/app.py deleted file mode 100644 index 7b991a9dd6cdf70f2cf2bb84766850a0f2c3cd21..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/app.py +++ /dev/null @@ -1,20 +0,0 @@ -import os - -from components.legacy.Docs import Docs - - -def resolve(relative_path: str): - return os.path.join(os.path.dirname(__file__), relative_path) - - -docs = Docs( - __file__, - markdown_files=(["README.md", "README-zh_CN.md"] + [ - f"custom_tags/{filename}" - for filename in os.listdir(resolve('custom_tags')) - if filename.endswith(".md") - ]), -) - -if __name__ == "__main__": - docs.render().queue().launch() diff --git a/components/legacy/Markdown/custom_tags/accordion-zh_CN.md b/components/legacy/Markdown/custom_tags/accordion-zh_CN.md deleted file mode 100644 index 6a62712515e4dc14cdfd17865deb80811fa15abb..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/custom_tags/accordion-zh_CN.md +++ /dev/null @@ -1,23 +0,0 @@ -# accordion - -在 markdown 文本中添加手风琴效果。 - -## 如何使用 - -### 基本使用 - - - -### 使用 accordion-title 标记 - -使用`::accordion-title[content]`的形式可以在标题输入 markdown 文本。 - - - -## API 及参数列表 - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ----- | ------ | ------ | ------------ | -| title | string | | 手风琴的标题 | diff --git a/components/legacy/Markdown/custom_tags/accordion.md b/components/legacy/Markdown/custom_tags/accordion.md deleted file mode 100644 index 66f1d1e9ea8505914a077d9dfce3ca8b577eace5..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/custom_tags/accordion.md +++ /dev/null @@ -1,22 +0,0 @@ -# accordion - -Add an accordion effect to markdown text. - -## How to Use - -### Basic Usage - - - -### Using the accordion-title Marker - -Using the form `::accordion-title[content]`, you can input markdown text into the title. - - -## API and Parameter List - -### props - -| Attribute | Type | Default Value | Description | -| --------- | ------ | ------------- | -------------------------- | -| title | string | | The title of the accordion | diff --git a/components/legacy/Markdown/custom_tags/chart-zh_CN.md b/components/legacy/Markdown/custom_tags/chart-zh_CN.md deleted file mode 100644 index caca68a9e3ef4b4d7a83320cfef55fb48968ed9c..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/custom_tags/chart-zh_CN.md +++ /dev/null @@ -1,17 +0,0 @@ -# chart - -在 markdown 文本中添加图表。 - -## 如何使用 - -### 基本使用 - - - -## API 及参数列表 - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ------- | ------ | ------ | ----------------------------------------------------------------------------------------- | -| options | object | | `echarts`的 options 配置,详见:[echarts docs](https://echarts.apache.org/en/option.html) | diff --git a/components/legacy/Markdown/custom_tags/chart.md b/components/legacy/Markdown/custom_tags/chart.md deleted file mode 100644 index c5fa26a2d9dadf4be5c48cdeafb828cb6daa3f02..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/custom_tags/chart.md +++ /dev/null @@ -1,17 +0,0 @@ -# chart - -Add a chart to markdown text. - -## How to Use - -### Basic Usage - - - -## API and Parameter List - -### props - -| Attribute | Type | Default Value | Description | -| --------- | ------ | ------------- | --------------------------------------------------------------------------------- | -| options | object | | `echarts` options, see: [echarts docs](https://echarts.apache.org/en/option.html) | diff --git a/components/legacy/Markdown/custom_tags/select-box-zh_CN.md b/components/legacy/Markdown/custom_tags/select-box-zh_CN.md deleted file mode 100644 index c309287508232e756d9dd039d9b49dadec959f53..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/custom_tags/select-box-zh_CN.md +++ /dev/null @@ -1,45 +0,0 @@ -# select-box - -在 markdown 文本中添加选择交互框。 - -## 如何使用 - -### 基本使用 - - - -### Card 样式 - - - -### Card 自适应内部元素宽度 - - - -### 监听 Python 事件 - - - -## API 及参数列表 - -### value - -custom 事件中 custom_data value 对应值, 返回值为用户 options 传入的对应 value ,如果type="checkbox",则返回一个 list。 - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ------------ | ------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| type | 'checkbox' \| 'radio' | 'radio' | 选择框类型,'radio' 为单选框、'checkbox'为多选框。 | -| disabled | boolean | | 禁用选择,通常在需要读取历史信息二次渲染时会用到。 | -| value | string | | 默认选中值,通常适用于`type="checkbox"`时提前为用户选择部分选项和设置`disabled`后的默认值渲染。 | -| direction |  'horizontal' \| 'vertical' | 'horizontal' | 横向或竖向排列选择框 | -| shape | 'card' \| 'default' | 'default' | 选择框样式 | -| options | (string\| { label?: string, value?: string, imgSrc?: string})\[\] | | 为用户提供的选项值,每一项可以为 string 或 object。 当值为 object 时可以接收更多自定义值,其中imgSrc只有当shape="card"时才生效。 | -| select-once | boolean | false | 是否只允许用户选择一次 | -| submit-text | string | | 提交按钮的展示值,当该属性有值时,会展示提交按钮,此时用户只有点击提交按钮后才会触发选择事件。 | -| 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 整除,否则可能列数会不符合预期。 当此项传入值为对象时,可以响应式控制每一行渲染列数,响应阈值如下:
- xs:屏幕 < 576px
- sm:屏幕 ≥ 576px
- md:屏幕 ≥ 768px
- lg:屏幕 ≥ 992px
- xl:屏幕 ≥ 1200px
- xxl:屏幕 ≥ 1600px 当direction为vertical时此配置不生效。 | -| item-width | string | | 当shape="card"时才生效。每个选项的宽度,如:'auto'、'100px',默认使用 columns 自动分配的宽度。 | -| item-height | string | | 当shape="card"时才生效。每个选项的高度,默认自适应元素高度。 | -| img-height | string | '160px' | 当shape="card"时才生效。每个选项中图片的高度。 | -| equal-height | boolean | false | 当shape="card"时才生效。是否每一行的选项高度都相等,会使用高度最高的选项。 | diff --git a/components/legacy/Markdown/custom_tags/select-box.md b/components/legacy/Markdown/custom_tags/select-box.md deleted file mode 100644 index fb2b210a291d29f0876f68d4af9c468014b3f2cb..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/custom_tags/select-box.md +++ /dev/null @@ -1,45 +0,0 @@ -# select-box - -Add a selection interaction box to markdown text. - -## How to Use - -### Basic Usage - - - -### Card Style - - - -### Card Adapts to Width of Inner Elements - - - -### Listening to Python Events - - - -## API and Parameter List - -### value - -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. - -### props - -| Attribute | Type | Default Value | Description | -| ------------ | ------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| type | 'checkbox' \| 'radio' | 'radio' | The type of selection box: 'radio' for radio buttons, 'checkbox' for checkboxes. | -| disabled | boolean | | Disable the selection, usually used when reading historical information for re-rendering. | -| 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`. | -| direction | 'horizontal' \| 'vertical' | 'horizontal' | Arrange selection boxes horizontally or vertically. | -| shape | 'card' \| 'default' | 'default' | The style of the selection box. | -| 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". | -| select-once | boolean | false | Whether to allow the user to make a selection only once. | -| 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. | -| 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:
- xs: screen < 576px
- sm: screen ≥ 576px
- md: screen ≥ 768px
- lg: screen ≥ 992px
- xl: screen ≥ 1200px
- xxl: screen ≥ 1600px This configuration does not take effect when direction is vertical. | -| 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. | -| item-height | string | | Effective only when shape="card". The height of each option, defaults to adapt to the height of the element. | -| img-height | string | '160px' | Effective only when shape="card". The height of the images within each option. | -| 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. | diff --git a/components/legacy/Markdown/demos/accordion.py b/components/legacy/Markdown/demos/accordion.py deleted file mode 100644 index 6bc3615a2e17fe7866ac12e7310964da458dbcbe..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/accordion.py +++ /dev/null @@ -1,28 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(""" - - -```json -{"text": "glorious weather", "resolution": "1024*1024"} -``` - - - -Use `::accordion-title` to support markdown: - - - -::accordion-title[Using `tool`] - -```json -{"text": "glorious weather", "resolution": "1024*1024"} -``` - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/basic.py b/components/legacy/Markdown/demos/basic.py deleted file mode 100644 index 4f2332a7604d8fa1d40dea3f9e0de6bd8e8dd5e1..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/basic.py +++ /dev/null @@ -1,11 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown( - "This _example_ was **written** in [Markdown](https://en.wikipedia.org/wiki/Markdown)\n" - ) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/chart.py b/components/legacy/Markdown/demos/chart.py deleted file mode 100644 index e4c492b0336ec3e52f913863a7b4eca70f5abae0..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/chart.py +++ /dev/null @@ -1,31 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# echarts options, see: https://echarts.apache.org/en/index.html -option1 = { - "xAxis": { - "type": 'category', - "data": ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], - }, - "yAxis": { - "type": 'value', - }, - "series": [ - { - "data": [150, 230, 224, 218, 135, 147, 260], - "type": 'line', - }, - ], -} - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(f""" -Chart: - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom-tag.py b/components/legacy/Markdown/demos/custom-tag.py deleted file mode 100644 index 8e053a563a6ad95cb3d61f63c5e25b1fc5f7f82b..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom-tag.py +++ /dev/null @@ -1,21 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown( - """ -custom tag: -""", - custom_components={ - # Key is the tag name - "custom-tag": { - # The tag props. - "props": ["value"], - # The tag template, use `{prop}` as placeholder. - "template": "
{value}
" - } - }) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom-tag2.py b/components/legacy/Markdown/demos/custom-tag2.py deleted file mode 100644 index ecb3acefd0d171b1af15818cdcb04eb3f2f59c29..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom-tag2.py +++ /dev/null @@ -1,55 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown( - """ -custom tag: -""", - custom_components={ - "custom-tag": { - "props": ["value"], - "template": - "", - # The `js` property should be a string containing a JavaScript Function. - "js": - """ -(props, cc, { el, onMount, onUpdate }) => { - // `onMount` will be called after the template first rendered - onMount(() => { - // `el` is the container element - console.log(el) - - // the return function will be called when the component is being unmounted - return () => { - console.log('unmount') - } - }) - - // `onUpdate` will be called when the props changed - onUpdate(() => { - console.log(props) - }) - onUpdate( - () => { - console.log(props, 'after mount') - }, - // By default, the callback will not be called when the component is being mounted. Set `callAfterMount` to true to enable it. - { callAfterMount: true } - ) - 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 'xx'. - - // The return value will be merged with `props` and passed to the template. - return { - value: 'Click Me: ' + props.value, - onClick: () => { - alert('hello') - } - } -}""" - } - }) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom-tag3.py b/components/legacy/Markdown/demos/custom-tag3.py deleted file mode 100644 index 6d92315c032aeaf5b87abb8f3db42a38a12ff92c..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom-tag3.py +++ /dev/null @@ -1,31 +0,0 @@ -import json -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -options = ["a", "b", "c"] - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -with open(resolve_assets("./custom_components/custom_select.js"), 'r') as f: - custom_select_js = f.read() - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(value=f""" -custom tag: -""", - custom_components={ - "custom-select": { - "props": ["options"], - "js": custom_select_js, - } - }) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom-tag4.py b/components/legacy/Markdown/demos/custom-tag4.py deleted file mode 100644 index 405c52c095c7ce02713362d58a08cb06b0c67213..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom-tag4.py +++ /dev/null @@ -1,38 +0,0 @@ -import json -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -options = ["a", "b", "c"] - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -with open(resolve_assets("./custom_components/custom_select.js"), 'r') as f: - custom_select_js = f.read() - - -def fn(data: gr.EventData): - # custom {'index': [0, 1, 0], 'tag': 'custom-select', 'tag_index': 0, 'value': 'option A'} - print("custom value", data._data) - - -with gr.Blocks() as demo, ms.Application(): - md = mgr.Markdown(value=f""" -custom tag: -""", - custom_components={ - "custom-select": { - "props": ["options"], - "js": custom_select_js, - } - }) - md.custom(fn=fn) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/accordion/accordion-title.py b/components/legacy/Markdown/demos/custom_tags/accordion/accordion-title.py deleted file mode 100644 index 9057415f7e4a3a6d89a6df18d4c61048b571cbaa..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/accordion/accordion-title.py +++ /dev/null @@ -1,19 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(""" - - -::accordion-title[Using `tool`] - -```json -{"text": "glorious weather", "resolution": "1024*1024"} -``` - - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/accordion/basic.py b/components/legacy/Markdown/demos/custom_tags/accordion/basic.py deleted file mode 100644 index 4020df36938a44f3cba2d983290fcad001600755..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/accordion/basic.py +++ /dev/null @@ -1,17 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(""" - - -```json -{"text": "glorious weather", "resolution": "1024*1024"} -``` - - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/chart/basic.py b/components/legacy/Markdown/demos/custom_tags/chart/basic.py deleted file mode 100644 index ad3ac880eeb8b2cec77c5680dbd1745f8e5e61a4..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/chart/basic.py +++ /dev/null @@ -1,84 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# echarts options, see: https://echarts.apache.org/en/index.html -option1 = { - "xAxis": { - "type": 'category', - "data": ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], - }, - "yAxis": { - "type": 'value', - }, - "series": [ - { - "data": [150, 230, 224, 218, 135, 147, 260], - "type": 'line', - }, - ], -} - -option2 = { - "tooltip": { - "trigger": 'item' - }, - "legend": { - "top": '5%', - "left": 'center' - }, - "series": [{ - "name": - 'Access From', - "type": - 'pie', - "radius": ['40%', '70%'], - "avoidLabelOverlap": - False, - "itemStyle": { - "borderRadius": 10, - "borderColor": '#fff', - "borderWidth": 2 - }, - "label": { - "show": False, - "position": 'center' - }, - "emphasis": { - "label": { - "show": True, - "fontSize": 40, - "fontWeight": 'bold' - } - }, - "labelLine": { - "show": False - }, - "data": [{ - "value": 1048, - "name": 'Search Engine' - }, { - "value": 735, - "name": 'Direct' - }, { - "value": 580, - "name": 'Email' - }, { - "value": 484, - "name": 'Union Ads' - }, { - "value": 300, - "name": 'Video Ads' - }] - }] -} - -with gr.Blocks() as demo, ms.Application(): - chatbot = mgr.Markdown(f""" - - -""") -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/select-box/basic.py b/components/legacy/Markdown/demos/custom_tags/select-box/basic.py deleted file mode 100644 index da1858770f574e668eaf20f629582d0108f58315..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/select-box/basic.py +++ /dev/null @@ -1,21 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -options = [{"label": "A", "value": "a"}, "b", "c"] - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown( - f"""Single Select: - -Multiple Select: - -Vertical Direction: - - -""", ) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/select-box/card_shape.py b/components/legacy/Markdown/demos/custom_tags/select-box/card_shape.py deleted file mode 100644 index 3ba4fccd6e21e17a6e474833a2eaeab1c2c2d766..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/select-box/card_shape.py +++ /dev/null @@ -1,33 +0,0 @@ -import json -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# Card shape supports setting `imgSrc` as the cover. -options = [{ - "label": - "A", - "imgSrc": - os.path.join(os.path.dirname(__file__), - '../../../../resources/screen.jpeg'), - "value": - "a" -}, "b", "c", "d"] - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown( - f""" - -Custom Columns: - - - -Vertical Direction: - - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/select-box/card_shape_width_auto.py b/components/legacy/Markdown/demos/custom_tags/select-box/card_shape_width_auto.py deleted file mode 100644 index 2ea9fb95524065c62dc2be0d183de85b5499be31..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/select-box/card_shape_width_auto.py +++ /dev/null @@ -1,27 +0,0 @@ -import json -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# Card shape supports setting `imgSrc` as the cover. -options = [{ - "label": - "A", - "imgSrc": - os.path.join(os.path.dirname(__file__), - '../../../../resources/screen.jpeg'), - "value": - "a" -}, "b", "c", "d"] - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown( - # item-width="auto" - f""" - -""", ) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/custom_tags/select-box/python_events.py b/components/legacy/Markdown/demos/custom_tags/select-box/python_events.py deleted file mode 100644 index 4cff53b6a76d19e89c0cf2dbbb56750986cef57b..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/custom_tags/select-box/python_events.py +++ /dev/null @@ -1,24 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -options = [{"label": "A", "value": "a"}, "b", "c"] - - -def fn(data: gr.EventData): - custom_data = data._data - if (custom_data["tag"] == "select-box"): - print(custom_data["value"] - ) # 'a' or 'b' or 'c', the value set in the options. - - -with gr.Blocks() as demo, ms.Application(): - md = mgr.Markdown( - f"" - ) - md.custom(fn=fn) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/multimodal.py b/components/legacy/Markdown/demos/multimodal.py deleted file mode 100644 index ec205ef7c092960ba34936aebe952e78f42b9bf2..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/multimodal.py +++ /dev/null @@ -1,27 +0,0 @@ -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(f""" -Image - -![image]({resolve_assets("bot.jpeg")}) - - - -Audio - - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/Markdown/demos/select-box.py b/components/legacy/Markdown/demos/select-box.py deleted file mode 100644 index ae2cff107cd5e2a8f156d7de97866f9b75012024..0000000000000000000000000000000000000000 --- a/components/legacy/Markdown/demos/select-box.py +++ /dev/null @@ -1,32 +0,0 @@ -import json - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - -# `label` will display on the page, and `value` is the actual selected value. -options = [{"label": "A", "value": "a"}, "b", "c"] - -with gr.Blocks() as demo, ms.Application(): - mgr.Markdown(f""" -Single Select: - -Multiple Select: - -Vertical Direction: - - - -Card Shape: - - - - - - - - -""") - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/MultimodalInput/README-zh_CN.md b/components/legacy/MultimodalInput/README-zh_CN.md deleted file mode 100644 index d98029e5adc6f54f066f900211daf7fb1e8e5e15..0000000000000000000000000000000000000000 --- a/components/legacy/MultimodalInput/README-zh_CN.md +++ /dev/null @@ -1,50 +0,0 @@ -# MutilmodalInput  - -多模态输入框,支持上传文件、录音、照相等功能。 - -- 支持文本输入+文件上传共同提交 -- 支持文件上传时的图片、音频预览 -- 提交内容作为 Chatbot 输入多模态内容作为用户输入问题自动匹配 -- 支持用户录音和拍照 - -## 如何使用 - -### 基本使用 - - - -### 与 Chatbot 配合使用 - - - -### 配置上传/提交按钮 - - - -### 允许用户录音或拍照 - - - -## API 及参数列表 - -以下 API 均为在原有 gradio Textbox 外的额外拓展参数。 - -### value - -接口定义: - -```python -class MultimodalInputData(GradioModel): - files: List[Union[FileData, str]] = [] - text: str -``` - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ------------------- | -------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------- | -| sources | list\[Literal\['upload', 'microphone','webcam'\]\] | \['upload'\] | 上传文件的类型列表。 "upload"会提供上文文件按钮。 "microphone"支持用户录音输入。 "webcam"支持用户照相生成图片或视频 | -| webcam_props | dict | None | webcam 组件属性,目前支持传入mirror_webcam(bool)、include_audio(bool) | -| upload_button_props | dict | None | 上传文件按钮属性,同 gradio UploadButton | -| submit_button_props | dict | None | 提交按钮属性,同 gradio Button | -| file_preview_props | dict | None | 文件预览组件属性,目前支持传入 height (int) | diff --git a/components/legacy/MultimodalInput/README.md b/components/legacy/MultimodalInput/README.md deleted file mode 100644 index e82c502fd4b3ae76deb07aeed336389461442102..0000000000000000000000000000000000000000 --- a/components/legacy/MultimodalInput/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# MutilmodalInput - -A multimodal input field that supports uploading files, recording audio, taking photos, etc. - -- Supports text input and file upload for joint submission -- Supports image and audio previews during file upload -- Submissions serve as Chatbot input, matching multimodal content as user input questions automatically -- Supports user recording and photography - -## How to Use - -### Basic Usage - - - -### Using with Chatbot - - - -### Configuring Upload/Submit Buttons - - - -### Allowing User Recording or Photography - - - -## API and Parameter List - -The following APIs are additional expanded parameters beyond the original gradio Textbox. - -### value - -Interface definition: - -```python -class MultimodalInputData(GradioModel): - files: List[Union[FileData, str]] = [] - text: str -``` - -### props - -| Attribute | Type | Default Value | Description | -| ------------------- | ----------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| sources | List[Literal['upload', 'microphone', 'webcam']] | ['upload'] | A list of types for uploading files. "upload" provides an upload file button. "microphone" supports user audio input. "webcam" supports user photography to generate images or videos. | -| webcam_props | dict | None | webcam component properties, currently supports passing mirror_webcam(bool), include_audio(bool) | -| upload_button_props | dict | None | Upload file button properties, same as gradio UploadButton | -| submit_button_props | dict | None | Submit button properties, same as gradio Button | -| file_preview_props | dict | None | File preview component properties, currently supports passing height (int) | diff --git a/components/legacy/MultimodalInput/demos/basic.py b/components/legacy/MultimodalInput/demos/basic.py deleted file mode 100644 index ee3ade2b6ec877c87bf3a9bed8e9d1a9798ffdf6..0000000000000000000000000000000000000000 --- a/components/legacy/MultimodalInput/demos/basic.py +++ /dev/null @@ -1,16 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def fn(value): - # value includes `text`` and `files`` - print(value.text, value.files) - - -with gr.Blocks() as demo, ms.Application(): - input = mgr.MultimodalInput() - input.change(fn=fn, inputs=[input]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/MultimodalInput/demos/config_buttons.py b/components/legacy/MultimodalInput/demos/config_buttons.py deleted file mode 100644 index 84a5a4bde4692399834050f246929689296d96a2..0000000000000000000000000000000000000000 --- a/components/legacy/MultimodalInput/demos/config_buttons.py +++ /dev/null @@ -1,16 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def fn(value): - print(value.text, value.files) - - -with gr.Blocks() as demo, ms.Application(): - input = mgr.MultimodalInput(upload_button_props=dict(variant="primary"), - submit_button_props=dict(visible=False)) - input.change(fn=fn, inputs=[input]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/MultimodalInput/demos/upload_sources.py b/components/legacy/MultimodalInput/demos/upload_sources.py deleted file mode 100644 index 7358329e8b08c8962f38d25fe1caad5dcf350820..0000000000000000000000000000000000000000 --- a/components/legacy/MultimodalInput/demos/upload_sources.py +++ /dev/null @@ -1,15 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def fn(value): - print(value.text, value.files) - - -with gr.Blocks() as demo, ms.Application(): - input = mgr.MultimodalInput(sources=["upload", "microphone", "webcam"]) - input.change(fn=fn, inputs=[input]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/MultimodalInput/demos/with_chatbot.py b/components/legacy/MultimodalInput/demos/with_chatbot.py deleted file mode 100644 index 64cf913c06f736e8586d81e024059a81e74a1921..0000000000000000000000000000000000000000 --- a/components/legacy/MultimodalInput/demos/with_chatbot.py +++ /dev/null @@ -1,36 +0,0 @@ -import time - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def fn(input, chatbot): - chatbot.append([{ - "text": input.text, - "files": input.files, - }, None]) - yield { - user_input: mgr.MultimodalInput(interactive=False), - user_chatbot: chatbot - } - time.sleep(2) - chatbot[-1][1] = {"text": "Hello!"} - yield {user_chatbot: chatbot} - - -# Triggered when the typewriter is ending. -def flushed(): - return mgr.MultimodalInput(interactive=True) - - -with gr.Blocks() as demo, ms.Application(): - user_chatbot = mgr.Chatbot() - user_input = mgr.MultimodalInput() - user_input.submit(fn=fn, - inputs=[user_input, user_chatbot], - outputs=[user_input, user_chatbot]) - user_chatbot.flushed(fn=flushed, outputs=[user_input]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/README-zh_CN.md b/components/legacy/README-zh_CN.md deleted file mode 100644 index 578a17393bbd2e735c0dd12d6c94894ea8b15aeb..0000000000000000000000000000000000000000 --- a/components/legacy/README-zh_CN.md +++ /dev/null @@ -1,33 +0,0 @@ -

ModelScope Studio

- -

- - - ✖️ - - -

- -

-GitHub | 🤖 ModelScope Studio | 🤗 Hugging Face Space - -`modelscope_studio` 是一套基于 gradio 4.x 的扩展组件库,致力于服务于 ModelScope 创空间中对于 gradio 应用的各类扩展需求,目前主要聚集在对话场景增强、多模态场景以及一些其他垂直场景支持。 - -## Install - -```sh -pip install modelscope_studio -``` - -## API - -- load - -## Components - -- Chatbot -- MultimodalInput -- Markdown -- WaterfallGallery -- Lifecycle -- Flow diff --git a/components/legacy/README.md b/components/legacy/README.md deleted file mode 100644 index 821b96faa7c0e722c74f2d6455ae9eb4ec315003..0000000000000000000000000000000000000000 --- a/components/legacy/README.md +++ /dev/null @@ -1,33 +0,0 @@ -

ModelScope Studio

- -

- - - ✖️ - - -

- -

-GitHub | 🤖 ModelScope Studio | 🤗 Hugging Face Space - -`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. - -## Install - -```sh -pip install modelscope_studio -``` - -## API - -- load - -## Components - -- Chatbot -- MultimodalInput -- Markdown -- Lifecycle -- WaterfallGallery -- Flow diff --git a/components/legacy/WaterfallGallery/README-zh_CN.md b/components/legacy/WaterfallGallery/README-zh_CN.md deleted file mode 100644 index 94552d6c36dc16a3717e9ff437ddb441bc7788dc..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/README-zh_CN.md +++ /dev/null @@ -1,71 +0,0 @@ -# WaterfallGallery - -瀑布流形式的 gradio Gallery。 - -- 支持瀑布流展示图片 -- 增加点赞按钮,支持图片额外绑定`like`事件 -- 增加 action 按钮,支持图片额外绑定`click`事件 -- 响应式 columns - -## 如何使用 - -### 基本使用 - - - -### 响应式 columns - - - -### 加载更多 - - - -### 点赞/点击反馈 - - - -## API 及参数列表 - -以下 API 均为在原有 gradio Gallery 外的额外拓展参数。 - -### value - -接口定义: - -```python -GalleryImageType = Union[np.ndarray, _Image.Image, FileData, Path, str] -CaptionedGalleryImageType = Tuple[GalleryImageType, str] - - -class GalleryImage(GradioModel): - image: Union[FileData, Path, str] - caption: Optional[str] = None - liked: Optional[bool] = None - # custom meta data - meta: Optional[Any] = None - - -class GalleryData(GradioRootModel): - root: List[GalleryImage] -``` - -### props - -| 属性 | 类型 | 默认值 | 描述 | -| ---------------------- | -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| has_more | bool | None | 如果为 True,会显示 "加载更多" 按钮 | -| load_more_button_props | dict | None | ”加载更多“按钮属性,同 gradio Button | -| columns | int \| tuple \| dict | 2 | 展示在以下尺寸屏幕(<576px(xs)、<768px(sm)、<992px(md)、<1200px(lg)、<1600px(xl)、>1600px(xll))中在一行显示的图像数量。
- 如果传入 int, 则应用于所有尺寸屏幕;
- 如果传入 tuple, 当给出的断点少于 6 个, 则最后一个断点将用于所有后续断点;
- 如果传入 dict, 则可以以 [xs,sm,md,lg,xl,xll] 为键表示每个尺寸屏幕的图像数量。 | -| gap | tuple \| int | 8 | 图片之间的间隙 (px)。 如果传递一个元组,则第一个值是宽度的间隙,第二个值是高度的间隙。如果传递数字,则宽度和高度的间隙相同 | -| action_label | str | 'Click' | action 按钮的文案。当 `clickable`为 True 时才展示 | -| likeable | bool | None | 是否显示喜欢或不喜欢按钮。 可以通过显示绑定 `.like` 方法自动设置。 | -| clickable | bool | None | 是否显示 action 按钮。 可以通过显示绑定 `.click` 方法自动设置。 | - -### event listeners - -| 事件 | 描述 | -| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `mgr.WaterfallGallery.load_more(fn, ···)` | “加载更多”按钮被点击时触发。 | -| `mgr.WaterfallGallery.like(fn, ···)` | 当点赞/点踩按钮被点击时触发,EventData 为:
- index:当前图片索引。
- value:当前图片信息。
- liked:当前图片的喜欢/不喜欢状态,可以为 None,代表用户取消操作。 | -| `mgr.WaterfallGallery.click(fn, ···)` | action 按钮被点击时触发,EventData 为:
- index:当前图片索引。
- value:当前图片信息。 | diff --git a/components/legacy/WaterfallGallery/README.md b/components/legacy/WaterfallGallery/README.md deleted file mode 100644 index 392fe320a45a75d44b8f0111deb73e4a1021da23..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# WaterfallGallery - -gradio Gallery with waterfall flow. - -- Support waterfall flow display images -- Added a like button, support additional binding of `like` events to images -- Added an action button, support additional binding of `click` event to images -- Responsive columns - -## How to Use - -### Basic Usage - - - -### Responsive columns - - - -### Load More - - - -### Like/Click Feedback - - - -## API and Parameter List - -The following APIs are additional extended parameters beyond the original gradio Gallery. - -### value - -Interface definition: - -```python -GalleryImageType = Union[np.ndarray, _Image.Image, FileData, Path, str] -CaptionedGalleryImageType = Tuple[GalleryImageType, str] - - -class GalleryImage(GradioModel): - image: Union[FileData, Path, str] - caption: Optional[str] = None - liked: Optional[bool] = None - # custom meta data - meta: Optional[Any] = None - - -class GalleryData(GradioRootModel): - root: List[GalleryImage] -``` - -### props - -| Attribute | Type | Default Value | Description | -| ---------------------- | -------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| has_more | bool | None | If True, will show the "Load More" button. | -| lode_more_button_props | dict | None | “Load More” button properties, same as gradio Button | -| columns | int \| tuple \| dict | 2 | Displays the number of images displayed in a row on the following screen sizes (<576px(xs), <768px(sm), <992px(md), <1200px(lg), <1600px(xl), >1600px(xll)).
- If int is passed in, it will apply to all screen sizes;
- If tuple is passed in, when less than 6 breakpoints are given, the last breakpoint will be used for all subsequent breakpoints ;
- If a dict is passed in, you can represents the number of images for each size screen with [xs,sm,md,lg,xl,xll] as the key. | -| gap | tuple \| int | 8 | The gap (px) between images. If a tuple is passed, the first value is the gap for width and the second value is the gap for height.If a number is passed, the gap will be the same for width and height. | -| action_label | str | 'Click' | The label for the action button. Only displayed if `clickable` is set to True. | -| likeable | bool | None | Whether the gallery image display a like or dislike button. Set automatically by the .like method but has to be present in the signature for it to show up in the config. | -| clickable | bool | None | Whether the gallery image display an action button. Set automatically by the .click method but has to be present in the signature for it to show up in the config. | - -### Event Listeners - -| Event | Description | -| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `mgr.WaterfallGallery.load_more(fn, ···)` | Triggered when the "Load More" button is clicked. | -| `mgr.WaterfallGallery.like(fn, ···)` | Triggered when the Like/Dislike button is clicked. EventData is:
- index: current image index.
- value: current image info.
- liked: like/dislike status of the current image, which can be None, indicating that the user cancels the operation. | -| `mgr.WaterfallGallery.click(fn, ···)` | Triggered when the action button is clicked, EventData is:
- index: current image index.
- value: current image info. | diff --git a/components/legacy/WaterfallGallery/app.py b/components/legacy/WaterfallGallery/app.py deleted file mode 100644 index ea841f78832d9254426dc781674f7e39f7f7fd2f..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/app.py +++ /dev/null @@ -1,6 +0,0 @@ -from components.legacy.Docs import Docs - -docs = Docs(__file__) - -if __name__ == "__main__": - docs.render().queue().launch() diff --git a/components/legacy/WaterfallGallery/demos/basic.py b/components/legacy/WaterfallGallery/demos/basic.py deleted file mode 100644 index 1071ef06844b4f3399f35a1325e318f34cb92699..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/demos/basic.py +++ /dev/null @@ -1,30 +0,0 @@ -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -with gr.Blocks() as demo, ms.Application(): - mgr.WaterfallGallery( - value=[ - resolve_assets('modelscope.svg'), - # pass a tuple - [resolve_assets('bot.jpeg'), 'bot'], - # pass a dict - { - "image": resolve_assets('user.jpeg'), - "caption": "user", - }, - resolve_assets('screen.jpeg'), - ], - columns=2, - height=600) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/WaterfallGallery/demos/like_click_feedback.py b/components/legacy/WaterfallGallery/demos/like_click_feedback.py deleted file mode 100644 index 64299d854f90c963bd1b953871b488490d6e7839..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/demos/like_click_feedback.py +++ /dev/null @@ -1,37 +0,0 @@ -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -def fn(data: gr.EventData): - print(data._data) - - -with gr.Blocks() as demo, ms.Application(): - gallery = mgr.WaterfallGallery( - value=[ - resolve_assets('modelscope.svg'), - # pass a tuple - [resolve_assets('bot.jpeg'), 'bot'], - # pass a dict - { - "image": resolve_assets('user.jpeg'), - "caption": "user", - }, - resolve_assets('screen.jpeg'), - ], - action_label="Click Me!", - columns=2, - height=600) - gallery.like(fn=fn) - gallery.click(fn=fn) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/WaterfallGallery/demos/load_more.py b/components/legacy/WaterfallGallery/demos/load_more.py deleted file mode 100644 index 28fe008ec3f99005cbc97d523ceac1019afc3a6f..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/demos/load_more.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -import time - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -def load_more(_gallery): - time.sleep(1) - _gallery.append(resolve_assets('modelscope.svg')) - _gallery.append(resolve_assets('bot.jpeg')) - _gallery.append(resolve_assets('user.jpeg')) - _gallery.append(resolve_assets('screen.jpeg')) - has_more = True - if (len(_gallery) > 10): - has_more = False - return gr.update(value=_gallery, has_more=has_more) - - -with gr.Blocks() as demo, ms.Application(): - gallery = mgr.WaterfallGallery( - value=[ - resolve_assets('modelscope.svg'), - # pass a tuple - [resolve_assets('bot.jpeg'), 'bot'], - # pass a dict - { - "image": resolve_assets('user.jpeg'), - "caption": "user", - }, - resolve_assets('screen.jpeg'), - ], - has_more=True, - columns=2, - height=600) - gallery.load_more(fn=load_more, inputs=[gallery], outputs=[gallery]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/WaterfallGallery/demos/responsive_columns.py b/components/legacy/WaterfallGallery/demos/responsive_columns.py deleted file mode 100644 index dcea88d8e18c7e24e9fd89be7638826f91e417cb..0000000000000000000000000000000000000000 --- a/components/legacy/WaterfallGallery/demos/responsive_columns.py +++ /dev/null @@ -1,35 +0,0 @@ -import os - -import gradio as gr -import modelscope_studio.components.base as ms -import modelscope_studio.components.legacy as mgr - - -def resolve_assets(relative_path): - return os.path.join(os.path.dirname(__file__), "../../resources", - relative_path) - - -def fn(): - return gr.update(columns={"xs": 2, "lg": 3}) - - -with gr.Blocks() as demo, ms.Application(): - gallery = mgr.WaterfallGallery( - value=[ - resolve_assets('modelscope.svg'), - # pass a tuple - [resolve_assets('bot.jpeg'), 'bot'], - # pass a dict - { - "image": resolve_assets('user.jpeg'), - "caption": "user", - }, - resolve_assets('screen.jpeg'), - ], - columns=[2, 3, 4], - height=600) - gr.Button("Update Columns").click(fn=fn, outputs=[gallery]) - -if __name__ == "__main__": - demo.queue().launch() diff --git a/components/legacy/app.py b/components/legacy/app.py deleted file mode 100644 index 3606901af2b5fa0e4dd0244818fe5e4b9b9df35d..0000000000000000000000000000000000000000 --- a/components/legacy/app.py +++ /dev/null @@ -1,34 +0,0 @@ -import gradio as gr -import modelscope_studio.components.base as ms -from api.app import docs as api_docs -from components.legacy.Chatbot.app import docs as chatbot_docs -from components.legacy.Docs import Docs -from components.legacy.Flow.app import docs as flow_docs -from components.legacy.Lifecycle.app import docs as lifecycle_docs -from components.legacy.Markdown.app import docs as markdown_docs -from components.legacy.MultimodalInput.app import docs as multimodel_input_docs -from components.legacy.WaterfallGallery.app import \ - docs as waterfall_gallery_docs - -readme_docs = Docs(__file__) - -docs = [ - ["Quick Start", readme_docs], - ["API", api_docs], - ["Chatbot", chatbot_docs], - ["MultimodalInput", multimodel_input_docs], - ["Markdown", markdown_docs], - ["Lifecycle", lifecycle_docs], - ["WaterfallGallery", waterfall_gallery_docs], - ["Flow", flow_docs], -] - -with gr.Blocks() as legacy_demo: - with ms.Application(): - with gr.Tabs() as components_tabs: - for doc in docs: - with gr.TabItem(doc[0], id=doc[0]): - doc[1].render(components_tabs) - -if __name__ == "__main__": - legacy_demo.launch() diff --git a/components/legacy/parse_markdown.py b/components/legacy/parse_markdown.py deleted file mode 100644 index 56074f51585def881aa974994f2fa944c335c8ac..0000000000000000000000000000000000000000 --- a/components/legacy/parse_markdown.py +++ /dev/null @@ -1,85 +0,0 @@ -from html.parser import HTMLParser - - -def default_read_file(path): - with open(path, "r") as f: - return f.read() - - -enable_tags = ["demo", "demo-prefix", "demo-suffix", "file"] - - -class MarkdownParser(HTMLParser): - - def __init__(self, read_file=None): - super().__init__() - self.value = [{"type": "text", "value": ""}] - self.tag_stack = [] - self.read_file = read_file or default_read_file - self.current_tag = None - - def get_value(self): - return self.value - - def handle_data(self, data: str) -> None: - if self.value[-1]["type"] == "text": - self.value[-1]["value"] += data - elif self.current_tag is None: - self.value.append({"type": "text", "value": data}) - elif self.current_tag == "demo-prefix": - self.value[-1]["prefix"] += data - elif self.current_tag == "demo-suffix": - self.value[-1]["suffix"] += data - - def handle_startendtag(self, tag: str, attrs) -> None: - if tag not in enable_tags: - self.handle_data(self.get_starttag_text()) - return - - def handle_starttag(self, tag: str, attrs) -> None: - if (tag not in enable_tags): - self.handle_data(self.get_starttag_text()) - return - if tag == "demo": - self.value.append({ - "type": - "demo", - "code_position": - dict(attrs).get("code-position", 'left'), - "name": - dict(attrs)["name"], - "prefix": - "", - "suffix": - "" - }) - elif tag == "file": - content = self.read_file(dict(attrs)["src"]) - if self.value[-1]["type"] == "text": - self.value[-1]["value"] += content - elif self.current_tag == "demo-prefix": - self.value[-1]["prefix"] += content - elif self.current_tag == "demo-suffix": - self.value[-1]["suffix"] += content - self.current_tag = tag - self.tag_stack.append(self.current_tag) - - def handle_endtag(self, tag: str) -> None: - - if (tag not in enable_tags): - self.handle_data(f"") - return - if (len(self.tag_stack) > 0): - self.tag_stack.pop() - if (len(self.tag_stack) > 0): - self.current_tag = self.tag_stack[-1] - else: - self.current_tag = None - else: - self.current_tag = None - - -def parse_markdown(markdown: str, read_file=None): - parser = MarkdownParser(read_file=read_file) - parser.feed(markdown) - return parser.get_value() diff --git a/components/legacy/resources/audio.wav b/components/legacy/resources/audio.wav deleted file mode 100644 index 105190ad88e2e177540361de340e54feb1587f3c..0000000000000000000000000000000000000000 Binary files a/components/legacy/resources/audio.wav and /dev/null differ diff --git a/components/legacy/resources/bot.jpeg b/components/legacy/resources/bot.jpeg deleted file mode 100644 index 5fde8cc45f61b677c0581e6889b11e269c35be08..0000000000000000000000000000000000000000 Binary files a/components/legacy/resources/bot.jpeg and /dev/null differ diff --git a/components/legacy/resources/custom_components/custom_select.js b/components/legacy/resources/custom_components/custom_select.js deleted file mode 100644 index f4a1cb405ae5efb33e31990018b2beac5ac26aa3..0000000000000000000000000000000000000000 --- a/components/legacy/resources/custom_components/custom_select.js +++ /dev/null @@ -1,29 +0,0 @@ -(props, cc, { el, onUpdate }) => { - const options = JSON.parse(props.options); - el.innerHTML = ` - ${options - .map((option) => { - return `

- -
`; - }) - .join('')} - `; - onUpdate( - () => { - const inputs = Array.from(el.getElementsByTagName('input')); - Array.from(el.getElementsByTagName('label')).forEach((label, i) => { - label.addEventListener('click', () => { - inputs.forEach((input) => { - input.checked = false; - }); - const input = label.getElementsByTagName('input')[0]; - input.checked = true; - // Use cc.dispatch to trigger events. - cc.dispatch(options[i]); - }); - }); - }, - { callAfterMount: true } - ); -}; diff --git a/components/legacy/resources/image-bot.jpeg b/components/legacy/resources/image-bot.jpeg deleted file mode 100644 index 5df101fedca7e0b76eaa1119506ca4c1941c9fc7..0000000000000000000000000000000000000000 Binary files a/components/legacy/resources/image-bot.jpeg and /dev/null differ diff --git a/components/legacy/resources/modelscope.svg b/components/legacy/resources/modelscope.svg deleted file mode 100644 index 093ba6fe2a55a9b6c5f5105af9f3544d60429e7b..0000000000000000000000000000000000000000 --- a/components/legacy/resources/modelscope.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/components/legacy/resources/music-bot.jpeg b/components/legacy/resources/music-bot.jpeg deleted file mode 100644 index 00288fb576845921bbc3247ca8da3fbbdea12800..0000000000000000000000000000000000000000 Binary files a/components/legacy/resources/music-bot.jpeg and /dev/null differ diff --git a/components/legacy/resources/screen.jpeg b/components/legacy/resources/screen.jpeg deleted file mode 100644 index 574735acb117e86c5c0850e2b5489b8f8efa20cc..0000000000000000000000000000000000000000 Binary files a/components/legacy/resources/screen.jpeg and /dev/null differ diff --git a/components/legacy/resources/user.jpeg b/components/legacy/resources/user.jpeg deleted file mode 100644 index 536948b6bd19cb0b49c44b74e2790198301520e5..0000000000000000000000000000000000000000 Binary files a/components/legacy/resources/user.jpeg and /dev/null differ diff --git a/components/legacy/tab-link.js b/components/legacy/tab-link.js deleted file mode 100644 index bcd9143dcafadafedfb4b711e704a6ca7e32b74c..0000000000000000000000000000000000000000 --- a/components/legacy/tab-link.js +++ /dev/null @@ -1,15 +0,0 @@ -(props, cc, { onMount, el }) => { - onMount(() => { - el.addEventListener('click', () => { - cc.dispatch({ - tab: props.tab, - component_tab: props['component-tab'], - }); - }); - }); - const children = props.children[0].value; - el.innerHTML = `${children}`; - el.style.display = 'inline-block'; - el.style.cursor = 'pointer'; - el.style.color = 'var(--link-text-color)'; -}; diff --git a/components/pro/chatbot/README-zh_CN.md b/components/pro/chatbot/README-zh_CN.md index 56840caac495958acd2284e14e6ca72abd5f0c98..5856b10faf3f828f2c84b464bfbade30411358bd 100644 --- a/components/pro/chatbot/README-zh_CN.md +++ b/components/pro/chatbot/README-zh_CN.md @@ -72,10 +72,10 @@ ### 插槽 ```python -SLOTS=["roles"] +SLOTS=["role"] ``` -另外,如果已有的 role 样式不符合预期,也可以和`Ant Design X`的`Bubble`组件一样使用`ms.Slot("roles")`进行自定义。 +另外,如果已有的 role 样式不符合预期,也可以和`Ant Design X`的`Bubble`组件一样使用`ms.Slot("role")`进行自定义。 ### 类型 @@ -107,7 +107,7 @@ class ChatbotPromptsConfig(GradioModel): # Ant Design X welcome props: https://x.ant.design/components/welcome class ChatbotWelcomeConfig(GradioModel): variant: Optional[Literal['borderless', 'filled']] = 'borderless' - icon: Optional[Union[str, Path]] = None + icon: Optional[Union[str, Path, dict]] = None title: Optional[str] = None description: Optional[str] = None extra: Optional[str] = None @@ -277,6 +277,8 @@ class ChatbotDataFileContentOptions(GradioModel): gap: Optional[Union[Literal["small", "middle", "large"], str, int, float]] = "small" image_props: Optional[dict] = None + video_props: Optional[dict] = None + audio_props: Optional[dict] = None # Ant Design X prompts props: https://x.ant.design/components/prompts @@ -318,7 +320,8 @@ class ChatbotDataMessageContent(GradioModel): class ChatbotDataMessage(ChatbotBotConfig): - role: Union[Literal['user', 'assistant', 'system'], str] = None + role: Union[Literal['user', 'assistant', 'system', 'divider'], str] = None + divider_props: Optional[dict] = None key: Optional[Union[str, int, float]] = None # If status is 'pending', the message will not render the footer area (including 'actions' and 'footer'). status: Optional[Literal['pending', 'done']] = None diff --git a/components/pro/chatbot/README.md b/components/pro/chatbot/README.md index c9cedad340ae41f62fedae99d34126b7919ccbef..55763eb3cb3afb088b61e9dae364f35ebf00dc64 100644 --- a/components/pro/chatbot/README.md +++ b/components/pro/chatbot/README.md @@ -71,10 +71,10 @@ The `message` object includes all configurations from `bot_config` and `user_con ### Slots ```python -SLOTS=["roles"] +SLOTS=["role"] ``` -Additionally, if the role style does not meet your expectations, you can also use `ms.Slot("roles")` to customize it, just like the `Bubble` component of `Ant ​​Design X`. +Additionally, if the role style does not meet your expectations, you can also use `ms.Slot("role")` to customize it, just like the `Bubble` component of `Ant ​​Design X`. ### Types @@ -106,7 +106,7 @@ class ChatbotPromptsConfig(GradioModel): # Ant Design X welcome props: https://x.ant.design/components/welcome class ChatbotWelcomeConfig(GradioModel): variant: Optional[Literal['borderless', 'filled']] = 'borderless' - icon: Optional[Union[str, Path]] = None + icon: Optional[Union[str, Path, dict]] = None title: Optional[str] = None description: Optional[str] = None extra: Optional[str] = None @@ -276,6 +276,8 @@ class ChatbotDataFileContentOptions(GradioModel): gap: Optional[Union[Literal["small", "middle", "large"], str, int, float]] = "small" image_props: Optional[dict] = None + video_props: Optional[dict] = None + audio_props: Optional[dict] = None # Ant Design X prompts props: https://x.ant.design/components/prompts @@ -317,7 +319,8 @@ class ChatbotDataMessageContent(GradioModel): class ChatbotDataMessage(ChatbotBotConfig): - role: Union[Literal['user', 'assistant', 'system'], str] = None + role: Union[Literal['user', 'assistant', 'system', 'divider'], str] = None + divider_props: Optional[dict] = None key: Optional[Union[str, int, float]] = None # If status is 'pending', the message will not render the footer area (including 'actions' and 'footer'). status: Optional[Literal['pending', 'done']] = None diff --git a/components/pro/chatbot/demos/multimodal.py b/components/pro/chatbot/demos/multimodal.py index 1d0b11dd8de0499a5fbeac5e8b01a00daa4954a0..bd495449b2ea5e2324679195296ef40f83fe0d3c 100644 --- a/components/pro/chatbot/demos/multimodal.py +++ b/components/pro/chatbot/demos/multimodal.py @@ -19,7 +19,7 @@ client = OpenAI( api_key=os.getenv("MODELSCOPE_ACCESS_TOKEN"), # ModelScope Token ) -model = "Qwen/Qwen2.5-VL-72B-Instruct" +model = "Qwen/Qwen3-VL-8B-Instruct" def prompt_select(input_value, e: gr.EventData): diff --git a/components/pro/multimodal_input/README-zh_CN.md b/components/pro/multimodal_input/README-zh_CN.md index 95ae0d42f6c3487118739a25e416f582d325fd2c..f966a55a45eccee5342d0ab1a3ef8339483dcb2d 100644 --- a/components/pro/multimodal_input/README-zh_CN.md +++ b/components/pro/multimodal_input/README-zh_CN.md @@ -39,11 +39,16 @@ | placeholder | `str \| None` | None | 输入框的提示信息。 | | disabled | `bool \| None` | None | 是否禁用。 | | upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | 文件上传配置。 | +| slot_config | `dict \| None` | None | 词槽配置,配置后输入框将变为词槽模式,支持结构化输入,此模式 value 配置将无效。 | +| skill | `dict \| None` | None | 技能配置,输入框将变为词槽模式,支持结构化输入,此模式 value 配置将无效。 | ### 插槽 ```python -SLOTS=['actions', "prefix", 'footer', 'header'] +SLOTS = [ + 'suffix', 'header', 'prefix', 'footer', 'skill.title', + 'skill.toolTip.title', 'skill.closable.closeIcon' +] ``` ### 类型 @@ -110,5 +115,4 @@ class MultimodalInputUploadConfig(GradioModel): class MultimodalInputValue(GradioModel): files: Optional[ListFiles] = None text: Optional[str] = None - ``` diff --git a/components/pro/multimodal_input/README.md b/components/pro/multimodal_input/README.md index f3ecec2852aeaf90dbb72e23d0555921707fb9cd..b7bbe1265e78e14c052918175784f60fe013f479 100644 --- a/components/pro/multimodal_input/README.md +++ b/components/pro/multimodal_input/README.md @@ -28,22 +28,27 @@ A multimodal input component based on [Ant Design X](https://x.ant.design), supp ### Props -| Attribute | Type | Default Value | Description | -| ------------- | -------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------- | -| value | `dict \| MultimodalInputValue \| None` | None | Default value to display, formatted as `{ "text":"", "files":[] }`. | -| loading | `bool \| None` | None | Whether the input is in a loading state, in which case the `cancel` event can be triggered. | -| mode | `inline \| block` | 'inline' | The rending mode of the input box. If `block`, the input box and the submit button will be rendered separately. | -| auto_size | `bool \| { minRows?: number; maxRows?: number } \| None` | { "maxRows": 8 } | Height auto size feature, can be set to True \| False or an object { "minRows": 2, "maxRows": 6 }. | -| read_only | `bool \| None` | None | Whether the input is read-only. | -| submit_type | `Literal['enter', 'shiftEnter'] \| None` | 'enter' | How the input box triggers the `submit` event. | -| placeholder | `str \| None` | None | Input placeholder text. | -| disabled | `bool \| None` | None | Whether to disable. | -| upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | File upload configuration. | +| Attribute | Type | Default Value | Description | +| ------------- | -------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| value | `dict \| MultimodalInputValue \| None` | None | Default value to display, formatted as `{ "text":"", "files":[] }`. | +| loading | `bool \| None` | None | Whether the input is in a loading state, in which case the `cancel` event can be triggered. | +| mode | `inline \| block` | 'inline' | The rending mode of the input box. If `block`, the input box and the submit button will be rendered separately. | +| auto_size | `bool \| { minRows?: number; maxRows?: number } \| None` | { "maxRows": 8 } | Height auto size feature, can be set to True \| False or an object { "minRows": 2, "maxRows": 6 }. | +| read_only | `bool \| None` | None | Whether the input is read-only. | +| submit_type | `Literal['enter', 'shiftEnter'] \| None` | 'enter' | How the input box triggers the `submit` event. | +| placeholder | `str \| None` | None | Input placeholder text. | +| disabled | `bool \| None` | None | Whether to disable. | +| upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | File upload configuration. | +| slot_config | `dict \| None` | None | Slot configuration, after configuration the input box will switch to slot mode, supporting structured input. In this mode, value configurations will be invalid. | +| skill | `dict \| None` | None | Skill configuration, after configuration the input box will switch to slot mode, supporting structured input. In this mode, value configurations will be invalid. | ### Slots ```python -SLOTS=['actions', "prefix", 'footer', 'header'] +SLOTS = [ + 'suffix', 'header', 'prefix', 'footer', 'skill.title', + 'skill.toolTip.title', 'skill.closable.closeIcon' +] ``` ### Types @@ -106,6 +111,7 @@ class MultimodalInputUploadConfig(GradioModel): } }) + class MultimodalInputValue(GradioModel): files: Optional[ListFiles] = None text: Optional[str] = None diff --git a/components/pro/web_sandbox/README-zh_CN.md b/components/pro/web_sandbox/README-zh_CN.md index 1415d1ef05e655549c082dc539ac446ffcc904ab..acdfeb150e16d2b49888b3e4b21c5c0a3352517b 100644 --- a/components/pro/web_sandbox/README-zh_CN.md +++ b/components/pro/web_sandbox/README-zh_CN.md @@ -23,6 +23,10 @@ +### 自定义 Sandbox 事件 + + + ### 处理错误 @@ -43,11 +47,12 @@ ### 事件 -| 事件 | 描述 | -| ----------------------------------------- | --------------------------- | -| `pro.WebSandbox.compile_success(fn, ···)` | 当 Sandbox 编译成功时触发。 | -| `pro.WebSandbox.compile_error(fn, ···)` | 当 Sandbox 编译失败时触发。 | -| `pro.WebSandbox.render_error(fn, ···)` | 当 Sandbox 渲染抛错时触发。 | +| 事件 | 描述 | +| ----------------------------------------- | ------------------------------------------------------------------------------------------- | +| `pro.WebSandbox.compile_success(fn, ···)` | 当 Sandbox 编译成功时触发。 | +| `pro.WebSandbox.compile_error(fn, ···)` | 当 Sandbox 编译失败时触发。 | +| `pro.WebSandbox.render_error(fn, ···)` | 当 Sandbox 渲染抛错时触发。 | +| `pro.WebSandbox.custom(fn, ···)` | 在 Sandbox 内触发的自定义事件,在 Sandbox 内通过 JavaScript 调用 `window.dispatch` 时触发。 | ### 插槽 diff --git a/components/pro/web_sandbox/README.md b/components/pro/web_sandbox/README.md index 48661ea395917596c44430faa9f9d6e7d626d49b..0f0a714314cca30c86d7301869fe4c8e6a05ee55 100644 --- a/components/pro/web_sandbox/README.md +++ b/components/pro/web_sandbox/README.md @@ -23,6 +23,10 @@ When `template` is set to `react`, the following dependencies will be automatica +### Custom Sandbox Event + + + ### Error Handling @@ -43,11 +47,12 @@ When `template` is set to `react`, the following dependencies will be automatica ### Events -| Event | Description | -| ----------------------------------------- | ------------------------------------------------- | -| `pro.WebSandbox.compile_success(fn, ···)` | Triggered when Sandbox compilation succeeds. | -| `pro.WebSandbox.compile_error(fn, ···)` | Triggered when Sandbox compilation fails. | -| `pro.WebSandbox.render_error(fn, ···)` | Triggered when Sandbox rendering throws an error. | +| Event | Description | +| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `pro.WebSandbox.compile_success(fn, ···)` | Triggered when Sandbox compilation succeeds. | +| `pro.WebSandbox.compile_error(fn, ···)` | Triggered when Sandbox compilation fails. | +| `pro.WebSandbox.render_error(fn, ···)` | Triggered when Sandbox rendering throws an error. | +| `pro.WebSandbox.custom(fn, ···)` | Custom events triggered within the Sandbox are invoked via JavaScript when `window.dispatch` is called within the Sandbox. | ### Slots diff --git a/components/pro/web_sandbox/demos/custom_sandbox_event.py b/components/pro/web_sandbox/demos/custom_sandbox_event.py new file mode 100644 index 0000000000000000000000000000000000000000..f9390434d5d435f57df7cffc5bbd2b7ed52a68f2 --- /dev/null +++ b/components/pro/web_sandbox/demos/custom_sandbox_event.py @@ -0,0 +1,26 @@ +import gradio as gr +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms +import modelscope_studio.components.pro as pro + + +def on_custom(e: gr.EventData): + print(e._data) + + +with gr.Blocks() as demo, ms.Application(), antd.ConfigProvider(): + sandbox = pro.WebSandbox(value={ + "index.tsx": + """ +export default function App() { + return ; +} +""" + }, + template="react") + sandbox.custom(fn=on_custom) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/helper/Site.py b/helper/Site.py index 26eca9a1fb82b3c4a1c91e0e1ef56bb6eaa9e978..bdb7e8f81c115fb9d129ec3b3aa5866e91be303e 100644 --- a/helper/Site.py +++ b/helper/Site.py @@ -32,6 +32,7 @@ class Site: if key in tab_docs: with antd.Tabs.Item( key=key, + additional_props=dict(ms_auto_loading=False), visible=True if tab.get("default_active_key") == key else False) as docs_tab: docs_tabs.append(docs_tab) @@ -57,20 +58,22 @@ class Site: for category in self.docs: for component in self.docs[category]: css += self.docs[category][component].get_css() - with gr.Blocks(css=css + """ + css = css + """ .gradio-container { max-width: 100% !important; padding: 0 !important; } -.gradio-container > main.fillable { +.gradio-container > .main.fillable { max-width: 100% !important; padding: 0 !important; + margin:0 !important; } .docs-layout-sider { width: 100% !important; max-width: 100% !important; } -""") as demo: +""" + with gr.Blocks() as demo: with ms.Application() as app: with antd.ConfigProvider(): with antd.Layout(elem_style=dict( @@ -105,6 +108,8 @@ class Site: for tab in self.tabs: with antd.Tabs.Item( key=tab["key"], + additional_props=dict( + ms_auto_loading=False), elem_style=dict( height= "calc(100vh - var(--size-4) - var(--body-text-size) * 1.5 - 64px)" @@ -167,7 +172,10 @@ class Site: else: tab["extra_menu_footer"].render( ) - with antd.Splitter.Panel(): + with antd.Splitter.Panel( + elem_style=dict( + overflow="auto" + )): with antd.Layout( elem_style=dict( width= @@ -251,4 +259,4 @@ class Site: tab_menu.select( fn=on_tab_menu_select, outputs=[tab_menu, tabs, *tab_components]) - return demo + return demo, css diff --git a/layout_templates/chatbot/demos/basic.py b/layout_templates/chatbot/demos/basic.py index 5bf8cdbf6a566d6c786d47e03e519a01ed1b516c..a9e54b20b3145058408c8fd87411c58157aae743 100644 --- a/layout_templates/chatbot/demos/basic.py +++ b/layout_templates/chatbot/demos/basic.py @@ -25,7 +25,7 @@ client = OpenAI( api_key=MODELSCOPE_ACCESS_TOKEN, ) -model = "Qwen/Qwen2.5-VL-72B-Instruct" +model = "Qwen/Qwen3-VL-8B-Instruct" save_history = False @@ -468,7 +468,7 @@ def logo(): ms.Span("Chatbot") -with gr.Blocks(css=css, fill_width=True) as demo: +with gr.Blocks(fill_width=True) as demo: state = gr.State({ "conversations_history": {}, "conversations": [], @@ -476,7 +476,8 @@ with gr.Blocks(css=css, fill_width=True) as demo: }) with ms.Application(), antdx.XProvider( - theme=DEFAULT_THEME, locale=DEFAULT_LOCALE), ms.AutoLoading(): + theme_config=DEFAULT_THEME, + locale=DEFAULT_LOCALE), ms.AutoLoading(): with antd.Row(gutter=[20, 20], wrap=False, elem_id="chatbot"): # Left Column with antd.Col(md=dict(flex="0 0 260px", span=24, order=0), @@ -694,4 +695,4 @@ with gr.Blocks(css=css, fill_width=True) as demo: queue=False) if __name__ == "__main__": - demo.queue().launch(ssr_mode=False) + demo.queue().launch(css=css, ssr_mode=False) diff --git a/layout_templates/chatbot/demos/copilot.py b/layout_templates/chatbot/demos/copilot.py index ac88cdfb94b820b2151e25621e58d1810e7dac06..33c29ea069d58094d05c832fa08d4142732e7b31 100644 --- a/layout_templates/chatbot/demos/copilot.py +++ b/layout_templates/chatbot/demos/copilot.py @@ -19,7 +19,7 @@ client = OpenAI( api_key=os.getenv("MODELSCOPE_ACCESS_TOKEN"), # ModelScope Token ) -model = "Qwen/Qwen2.5-72B-Instruct" +model = "Qwen/Qwen3-VL-8B-Instruct" def prompt_select(input_value, e: gr.EventData): @@ -171,7 +171,7 @@ css = """ } """ -with gr.Blocks(css=css) as demo, ms.Application() as app, antdx.XProvider(): +with gr.Blocks() as demo, ms.Application() as app, antdx.XProvider(): with antd.Row(elem_classes="copilot-container", wrap=True): # Content column with antd.Col(md=16, xs=24, @@ -322,4 +322,4 @@ achieve it. fn=resize_window, outputs=[copilot_open_btn, copilot_close_btn]) if __name__ == "__main__": - demo.queue().launch() + demo.queue().launch(css=css) diff --git a/layout_templates/chatbot/demos/fine_grained_control.py b/layout_templates/chatbot/demos/fine_grained_control.py index b32234f101f245c1093a6544e4f1942542c1453e..6171f333054f356901ef28a53b980e4577df9fb8 100644 --- a/layout_templates/chatbot/demos/fine_grained_control.py +++ b/layout_templates/chatbot/demos/fine_grained_control.py @@ -18,7 +18,7 @@ client = OpenAI( api_key=MODELSCOPE_ACCESS_TOKEN, ) -model = "Qwen/Qwen2.5-VL-72B-Instruct" +model = "Qwen/Qwen3-VL-8B-Instruct" save_history = False @@ -525,7 +525,7 @@ def logo(): ms.Span("Chatbot") -with gr.Blocks(css=css, fill_width=True) as demo: +with gr.Blocks(fill_width=True) as demo: state = gr.State({ "conversations_history": {}, "conversations": [], @@ -535,7 +535,8 @@ with gr.Blocks(css=css, fill_width=True) as demo: }) with ms.Application(), antdx.XProvider( - theme=DEFAULT_THEME, locale=DEFAULT_LOCALE), ms.AutoLoading(): + theme_config=DEFAULT_THEME, + locale=DEFAULT_LOCALE), ms.AutoLoading(): with antd.Row(gutter=[20, 20], wrap=False, elem_id="chatbot"): # Left Column with antd.Col(md=dict(flex="0 0 260px", span=24, order=0), @@ -575,14 +576,16 @@ with gr.Blocks(css=css, fill_width=True) as demo: with antdx.Bubble.List( items=DEFAULT_CONVERSATIONS_HISTORY, elem_classes="chatbot-chat-messages") as chatbot: - # Define Chatbot Roles - with ms.Slot("roles"): + # Define Chatbot Role + with ms.Slot("role"): # Placeholder Role with antdx.Bubble.List.Role( role="placeholder", - styles=dict(content=dict(width="100%")), + styles=dict(content=dict(width="100%"), + root=dict(paddingInlineEnd=0), + body=dict(width='100%')), variant="borderless"): - with ms.Slot("messageRender"): + with ms.Slot("contentRender"): with antd.Space( direction="vertical", size=16, @@ -633,12 +636,12 @@ with gr.Blocks(css=css, fill_width=True) as demo: with antd.Avatar(): with ms.Slot("icon"): antd.Icon("UserOutlined") - with ms.Slot("messageRender", + with ms.Slot("contentRender", params_mapping="""(content) => { if (typeof content === 'string') { return { content, files: [], files_container: { style: { display: 'none' }} } } - return { content: content.text, files_container: content.files?.length > 0 ? undefined : { style: { display: 'none' }}, files: (content.files || []).map(file => ({ item: file }))} + return { content: content.text, files_container: content.files?.length > 0 ? undefined : { style: { display: 'none' }}, files: (content.files || []).map(file => file)} }"""): with antd.Flex(vertical=True, @@ -648,16 +651,17 @@ with gr.Blocks(css=css, fill_width=True) as demo: wrap=True, as_item="files_container"): with ms.Each(as_item="files"): - antdx.Attachments.FileCard() + antdx.FileCard() ms.Markdown(as_item="content") with ms.Slot("footer", - params_mapping="""(bubble) => { + params_mapping= + """(content, info, bubble) => { return { copy_btn: { copyable: { text: typeof bubble.content === 'string' ? bubble.content : bubble.content?.text, tooltips: false }, }, - edit_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, - delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, + edit_btn: { conversationKey: bubble.key, disabled: bubble.meta?.disabled }, + delete_btn: { conversationKey: bubble.key, disabled: bubble.meta?.disabled }, }; }"""): with antd.Typography.Text( @@ -712,9 +716,9 @@ with gr.Blocks(css=css, fill_width=True) as demo: with antd.Avatar(): with ms.Slot("icon"): antd.Icon("RobotOutlined") - with ms.Slot( - "messageRender", - params_mapping="""(content, bubble) => { + with ms.Slot("contentRender", + params_mapping= + """(content, info, bubble) => { if (bubble.meta?.canceled) { return { value: content } } @@ -727,15 +731,16 @@ with gr.Blocks(css=css, fill_width=True) as demo: as_item="canceled", type="warning") with ms.Slot("footer", - params_mapping="""(bubble) => { + params_mapping= + """(content, info, bubble) => { if (bubble?.meta?.end) { return { copy_btn: { copyable: { text: bubble.content, tooltips: false }, }, - regenerate_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, - delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, - edit_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, + regenerate_btn: { conversationKey: bubble.key, disabled: bubble.meta?.disabled }, + delete_btn: { conversationKey: bubble.key, disabled: bubble.meta?.disabled }, + edit_btn: { conversationKey: bubble.key, disabled: bubble.meta?.disabled }, like_btn: { conversationKey: bubble.key, color: bubble.meta?.action === 'like' ? 'primary' : 'default', @@ -1034,4 +1039,4 @@ with gr.Blocks(css=css, fill_width=True) as demo: queue=False) if __name__ == "__main__": - demo.queue().launch(ssr_mode=False) + demo.queue().launch(css=css, ssr_mode=False) diff --git a/layout_templates/coder_artifacts/demos/app.py b/layout_templates/coder_artifacts/demos/app.py index 302e8e97afb63299b53e36c17f495c31eb9deb75..45cb2702ea40d9bc214741789112d2fad403cfd0 100644 --- a/layout_templates/coder_artifacts/demos/app.py +++ b/layout_templates/coder_artifacts/demos/app.py @@ -15,7 +15,7 @@ MODELSCOPE_ACCESS_TOKEN = os.getenv('MODELSCOPE_ACCESS_TOKEN') client = OpenAI(api_key=MODELSCOPE_ACCESS_TOKEN, base_url="https://api-inference.modelscope.cn/v1") -model = "Qwen/Qwen2.5-Coder-32B-Instruct" +model = "Qwen/Qwen3-Coder-480B-A35B-Instruct" # =========== Configuration 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. @@ -212,16 +212,17 @@ css = """ #coder-artifacts-code-drawer .output-code { flex:1; } -#coder-artifacts-code-drawer .output-code .ms-gr-ant-spin-nested-loading { +#coder-artifacts-code-drawer .output-code .ms-gr-ant-spin { min-height: 100%; } """ -with gr.Blocks(css=css) as demo: +with gr.Blocks() as demo: # Global State state = gr.State({"system_prompt": DEFAULT_SYSTEM_PROMPT, "history": []}) with ms.Application(elem_id="coder-artifacts") as app: - with antd.ConfigProvider(theme=DEFAULT_THEME, locale=DEFAULT_LOCALE): + with antd.ConfigProvider(theme_config=DEFAULT_THEME, + locale=DEFAULT_LOCALE): # Header with antd.Flex(justify="center", align="center", gap="middle"): antd.Typography.Title("Coder-Artifacts", @@ -382,7 +383,6 @@ with gr.Blocks(css=css) as demo: width="750px") as history_drawer: history_output = gr.Chatbot( show_label=False, - type="messages", height='100%', elem_classes="history_chatbot") # Tour @@ -476,4 +476,4 @@ with gr.Blocks(css=css) as demo: outputs=[output_code_drawer]) if __name__ == "__main__": - demo.queue().launch(ssr_mode=False) + demo.queue().launch(css=css, ssr_mode=False) diff --git a/legacy_app.py b/legacy_app.py deleted file mode 100644 index d7b855dfbec86a9b10abf03321848795d3775a21..0000000000000000000000000000000000000000 --- a/legacy_app.py +++ /dev/null @@ -1,6 +0,0 @@ -from components.legacy.app import legacy_demo - -demo = legacy_demo - -if __name__ == "__main__": - demo.launch() diff --git a/requirements.txt b/requirements.txt index 35b48eee6af588d3899d7f6604cb42d55291a13a..eb3824d8e629cfea8e7af75972fe50bd3f4de91e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ gradio==5.34.1 -modelscope_studio==1.6.0 +modelscope_studio==2.0.0 openai diff --git a/src/pyproject.toml b/src/pyproject.toml index 3127ad9dd1832533c369c3755a2e699488ad1bd0..e8dc0a128c94a6eac1aff0fbf880a001f54bd26a 100644 --- a/src/pyproject.toml +++ b/src/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "hatchling.build" [project] name = "modelscope_studio" -version = "1.6.0" +version = "2.0.0" description = "A third-party component library based on Gradio." readme = "README.md" license = "Apache-2.0" @@ -45,12 +45,6 @@ dev = ["build", "twine"] [tool.hatch.build] artifacts = [ "*.pyi", - "backend/modelscope_studio/components/legacy/Chatbot/templates", - "backend/modelscope_studio/components/legacy/Flow/templates", - "backend/modelscope_studio/components/legacy/MultimodalInput/templates", - "backend/modelscope_studio/components/legacy/Markdown/templates", - "backend/modelscope_studio/components/legacy/WaterfallGallery/templates", - "/backend/modelscope_studio/components/legacy/Lifecycle/templates", "/backend/modelscope_studio/components/antd/button/templates", "/backend/modelscope_studio/components/antd/card/templates", "/backend/modelscope_studio/components/antd/card/grid/templates", @@ -198,11 +192,6 @@ artifacts = [ "/backend/modelscope_studio/components/antd/upload/dragger/templates", "/backend/modelscope_studio/components/antd/splitter/templates", "/backend/modelscope_studio/components/antd/splitter/panel/templates", - "/backend/modelscope_studio/components/legacy/Chatbot/templates", - "/backend/modelscope_studio/components/legacy/Flow/templates", - "/backend/modelscope_studio/components/legacy/Markdown/templates", - "/backend/modelscope_studio/components/legacy/MultimodalInput/templates", - "/backend/modelscope_studio/components/legacy/WaterfallGallery/templates", "/backend/modelscope_studio/components/antd/form/provider/templates", "/backend/modelscope_studio/components/antd/modal/static/templates", "/backend/modelscope_studio/components/antdx/bubble/templates",