Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ModelScope Studio 1.0 is out #38

Open
Col0ring opened this issue Dec 18, 2024 · 1 comment
Open

ModelScope Studio 1.0 is out #38

Col0ring opened this issue Dec 18, 2024 · 1 comment

Comments

@Col0ring
Copy link
Collaborator

Col0ring commented Dec 18, 2024

English Version

modelscope_studio is a third-party component library based on Gradio, offers developers more customized interface building capabilities and a richer variety of component usage forms.

In version 1.0, we integrated components from Ant Design and ensure compatibility with most of its APIs. Now you can build your Gradio application with them.

Docs & Demo:

image

Install

pip install modelscope_studio

Usage Example

import gradio as gr

import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms

with gr.Blocks() as demo:
    with ms.Application():
        with antd.ConfigProvider():
            with ms.AutoLoading():
                with antd.Flex(vertical=True, gap="small"):
                    antd.Alert(type="info",
                               message="Welcome",
                               closable=True,
                               description="Welcome to modelscope-studio")
                    with antd.Card(title="ModelScope"):
                          antd.Tag("modelscope", color="purple")
                          antd.Tag("ms-swift", color="magenta")
                          antd.Tag("modelscope-studio", color="geekblue")

demo.queue().launch()

image

Features

Layouts with slots

Different from the layout in Gradio, to make more flexible layouts, modelscope-studio provides a Slot component for developers.

For example, in Ant Design, there are some properties of type ReactNode (which can be simply understood as they accept components as parameters). and these properties cannot be directly passed through Python, they can only be implemented using the Slot component.

If we want to add some additional styles to the top of the Card in the example above:

with antd.Card():
    with ms.Slot("title"):  # corresponds to the prop name of card
        antd.Typography.Text("ModelScope",
                             strong=True,
                             copyable=True)
    with ms.Slot("extra"):
        with antd.Button(
                href=
                "https://github.com/modelscope/modelscope-studio",
                href_target="_blank"):
            ms.Text("GitHub")
            with ms.Slot("icon"):
                antd.Icon("GithubOutlined")
    antd.Tag("modelscope", color="purple")
    antd.Tag("ms-swift", color="magenta")
    antd.Tag("modelscope-studio", color="geekblue")

image

With Slot, we can adjust the page more freely!

Integrating with other Gradio components

modelscope_studio focuses more on page layout and component flexibility. If some features cannot be implemented with the components in modelscope-studio, developers can also easily embed other Gradio components and still use them together with modelscope-studio.

Modify the above code and add the button of Gradio in the upper right corner of the card:

with ms.Slot("extra"):
    gr.Button("Gradio Button", variant="primary")

    with antd.Button(
            href=
            "https://github.com/modelscope/modelscope-studio",
            elem_style=dict(marginLeft=8),
            href_target="_blank"):
        ms.Text("GitHub")
        with ms.Slot("icon"):
            antd.Icon("GithubOutlined")

image

Component context interactivity

modelscope-studio supports interactivity between different components. For example, in a common form submission scenario:

import gradio as gr
import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms

def on_submit(_form):
    print(_form)  # the Form Component will automatically collect the form data

with gr.Blocks() as demo:
    with ms.Application():
        with antd.ConfigProvider():
            with antd.Card(elem_style=dict(width=800, margin="0 auto")):
                with antd.Form(variant="outlined",
                               label_col=dict(span=4),
                               wrapper_col=dict(span=20)) as form:
                    with antd.Form.Item(form_name="username",
                                        label="Username",
                                        tooltip="This is a required field",
                                        rules=[{
                                            "required":
                                            True,
                                            "message":
                                            'Please input your username!'
                                        }]):
                        antd.Input()
                    with antd.Form.Item(form_name="password",
                                        label="Password",
                                        tooltip="This is a required field",
                                        rules=[{
                                            "required":
                                            True,
                                            "message":
                                            'Please input your password!'
                                        }]):
                        antd.Input.Password()
                    with antd.Form.Item(form_name="files", label="Upload"):
                        with antd.Upload.Dragger():
                            with ms.Div(elem_style=dict(fontSize=40,
                                                        color="#1677ff")):
                                antd.Icon("InboxOutlined")
                            antd.Typography.Paragraph(
                                "Click or drag file to this area to upload")
                            antd.Typography.Paragraph(
                                "Support for a single or bulk upload.",
                                type="secondary")

                    with antd.Form.Item(
                            wrapper_col=dict(offset=4, span=20),
                            form_name="remember",
                            value_prop_name="checked",
                    ):
                        with antd.Checkbox():
                            ms.Text("Remember me")
                    with antd.Form.Item(wrapper_col=dict(offset=4, span=20)):
                        submit_btn = antd.Button("Submit",
                                                 type="primary",
                                                 html_type="submit")
                # Fired when a button with html_type of submit is clicked
                form.finish(on_submit, inputs=[form])


demo.launch()

image

The submitted print result is:

{'username': 'modelscope', 'password': 'modelscope-studio', 'remember': True}

In this example, developers can collect form data uniformly through context. (automatic collection can only be triggered by the form component provided by Ant Design)

Custom themes and i18n

Customize themes and i18n by passing theme and locale parameters to the antd.ConfigProvider component.

import gradio as gr

import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms

default_locale = "en_US"
default_direction = 'ltr'
default_color = "#816DF8"
with gr.Blocks() as demo:
    with ms.Application():
        with antd.ConfigProvider(
                locale=default_locale,
                direction=default_direction,
                theme=dict(token=dict(
                    colorPrimary=default_color))) as config_provider:
            with antd.Card():
                with ms.Div(elem_style=dict(marginBottom=16)):
                    ms.Span("change locale of components:",
                            elem_style=dict(marginInlineEnd=16))
                    with antd.Radio.Group(value=default_locale) as locale:
                        with antd.Radio("en_US"):
                            ms.Text("English")
                        with antd.Radio("zh_CN"):
                            ms.Text("中文")
                        with antd.Radio("ja_JP"):
                            ms.Text("日本語")
                        with antd.Radio("ko_KR"):
                            ms.Text("한국어")
                    with antd.Space(wrap=True):
                        antd.DatePicker()
                        antd.DatePicker.RangePicker()
                        antd.TimePicker()
                        antd.TimePicker.RangePicker()
                with ms.Div(elem_style=dict(marginBottom=16)):
                    ms.Span("change direction of components:",
                            elem_style=dict(marginInlineEnd=16))
                    with antd.Radio.Group(
                            value=default_direction) as direction:
                        with antd.Radio.Button("ltr"):
                            ms.Text("LTR")
                        with antd.Radio.Button("rtl"):
                            ms.Text("RTL")
                    antd.Input(placeholder="do something...",
                               elem_style=dict(marginTop=8))
                with ms.Div(elem_style=dict(marginBottom=16)):
                    ms.Span("change theme of components:",
                            elem_style=dict(marginInlineEnd=16))
                    color = antd.ColorPicker(value=default_color)

                    antd.Button("Primary Button",
                                type="primary",
                                block=True,
                                elem_style=dict(marginTop=8))

        locale.change(fn=lambda _locale: gr.update(locale=_locale),
                      inputs=[locale],
                      outputs=[config_provider])
        direction.change(fn=lambda _direction: gr.update(direction=_direction),
                         inputs=[direction],
                         outputs=[config_provider])
        color.change(fn=lambda _color: gr.update(theme=dict(token=dict(
            colorPrimary=_color))),
                     inputs=[color],
                     outputs=[config_provider])

demo.launch()

image
image

中文版

modelscope_studio是一个基于 Gradio 的三方组件库,为开发者提供更定制化的界面搭建能力和更丰富的组件使用形式。

在 1.0 版本中,我们与 Ant Design 中的组件进行了集成,并兼容其中大多数 API。现在你可以使用它们构建你的 Gradio 应用。

文档 & Demo:

image

下载

pip install modelscope_studio

使用示例

import gradio as gr

import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms

with gr.Blocks() as demo:
    with ms.Application():
        with antd.ConfigProvider():
            with ms.AutoLoading():
                with antd.Flex(vertical=True, gap="small"):
                    antd.Alert(type="info",
                               message="Welcome",
                               closable=True,
                               description="Welcome to modelscope-studio")
                    with antd.Card(title="ModelScope"):
                        antd.Tag("modelscope", color="purple")
                        antd.Tag("ms-swift", color="magenta")
                        antd.Tag("modelscope-studio", color="geekblue")

demo.queue().launch()

image

特性

使用插槽布局

与 Gradio 本身的布局机制不同,为了实现更自由的布局,modelscope-studio为开发者提供了 Slot(插槽)组件。

比如在 Ant Design 中,有一些类型为ReactNode的属性(可以简单理解为它们接收的参数是一个个组件),这些属性就无法直接通过 Python 传入,只能通过Slot组件实现。

在上面的示例中,如果我们希望给 Card 的顶部添加一些额外的样式:

with antd.Card():
    with ms.Slot("title"):  # corresponds to the prop name of card
        antd.Typography.Text("ModelScope",
                             strong=True,
                             copyable=True)
    with ms.Slot("extra"):
        with antd.Button(
                href=
                "https://github.com/modelscope/modelscope-studio",
                href_target="_blank"):
            ms.Text("GitHub")
            with ms.Slot("icon"):
                antd.Icon("GithubOutlined")
    antd.Tag("modelscope", color="purple")
    antd.Tag("ms-swift", color="magenta")
    antd.Tag("modelscope-studio", color="geekblue")

image

通过Slot,我们就可以更加自由地对页面进行调整了!

集成其他 Gradio 组件

modelscope-studio更加关注页面布局和组件的灵活性,如果某些功能modelscope-studio中的组件无法实现,开发者也可以很轻松地嵌入其他的 Gradio 组件,并且仍然可以和modelscope-studio一起搭配使用。

修改一下上面的代码,我们在卡片右上角加入 Gradio 自带的按钮:

with ms.Slot("extra"):
    gr.Button("Gradio Button", variant="primary")

    with antd.Button(
            href=
            "https://github.com/modelscope/modelscope-studio",
            elem_style=dict(marginLeft=8),
            href_target="_blank"):
        ms.Text("GitHub")
        with ms.Slot("icon"):
            antd.Icon("GithubOutlined")

image

组件上下文联动

modelscope-studio支持不同组件之间的产生联动,以常见的表单提交场景为例:

import gradio as gr
import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms

def on_submit(_form):
    print(_form)  # the Form Component will automatically collect the form data

with gr.Blocks() as demo:
    with ms.Application():
        with antd.ConfigProvider():
            with antd.Card(elem_style=dict(width=800, margin="0 auto")):
                with antd.Form(variant="outlined",
                               label_col=dict(span=4),
                               wrapper_col=dict(span=20)) as form:
                    with antd.Form.Item(form_name="username",
                                        label="Username",
                                        tooltip="This is a required field",
                                        rules=[{
                                            "required":
                                            True,
                                            "message":
                                            'Please input your username!'
                                        }]):
                        antd.Input()
                    with antd.Form.Item(form_name="password",
                                        label="Password",
                                        tooltip="This is a required field",
                                        rules=[{
                                            "required":
                                            True,
                                            "message":
                                            'Please input your password!'
                                        }]):
                        antd.Input.Password()
                    with antd.Form.Item(form_name="files", label="Upload"):
                        with antd.Upload.Dragger():
                            with ms.Div(elem_style=dict(fontSize=40,
                                                        color="#1677ff")):
                                antd.Icon("InboxOutlined")
                            antd.Typography.Paragraph(
                                "Click or drag file to this area to upload")
                            antd.Typography.Paragraph(
                                "Support for a single or bulk upload.",
                                type="secondary")

                    with antd.Form.Item(
                            wrapper_col=dict(offset=4, span=20),
                            form_name="remember",
                            value_prop_name="checked",
                    ):
                        with antd.Checkbox():
                            ms.Text("Remember me")
                    with antd.Form.Item(wrapper_col=dict(offset=4, span=20)):
                        submit_btn = antd.Button("Submit",
                                                 type="primary",
                                                 html_type="submit")
                # Fired when a button with html_type of submit is clicked
                form.finish(on_submit, inputs=[form])


demo.launch()

image

提交的打印结果为:

{'username': 'modelscope', 'password': 'modelscope-studio', 'remember': True}

在这个示例中,开发者可以通过上下文统一收集表单数据。(自动收集只有 Ant Design 提供的表单组件才能触发哦)

自定义主题与国际化

通过为antd.ConfigProvider组件传递themelocale等参数实现自定义主题和国际化。

import gradio as gr

import modelscope_studio.components.antd as antd
import modelscope_studio.components.base as ms

default_locale = "en_US"
default_direction = 'ltr'
default_color = "#816DF8"
with gr.Blocks() as demo:
    with ms.Application():
        with antd.ConfigProvider(
                locale=default_locale,
                direction=default_direction,
                theme=dict(token=dict(
                    colorPrimary=default_color))) as config_provider:
            with antd.Card():
                with ms.Div(elem_style=dict(marginBottom=16)):
                    ms.Span("change locale of components:",
                            elem_style=dict(marginInlineEnd=16))
                    with antd.Radio.Group(value=default_locale) as locale:
                        with antd.Radio("en_US"):
                            ms.Text("English")
                        with antd.Radio("zh_CN"):
                            ms.Text("中文")
                        with antd.Radio("ja_JP"):
                            ms.Text("日本語")
                        with antd.Radio("ko_KR"):
                            ms.Text("한국어")
                    with antd.Space(wrap=True):
                        antd.DatePicker()
                        antd.DatePicker.RangePicker()
                        antd.TimePicker()
                        antd.TimePicker.RangePicker()
                with ms.Div(elem_style=dict(marginBottom=16)):
                    ms.Span("change direction of components:",
                            elem_style=dict(marginInlineEnd=16))
                    with antd.Radio.Group(
                            value=default_direction) as direction:
                        with antd.Radio.Button("ltr"):
                            ms.Text("LTR")
                        with antd.Radio.Button("rtl"):
                            ms.Text("RTL")
                    antd.Input(placeholder="do something...",
                               elem_style=dict(marginTop=8))
                with ms.Div(elem_style=dict(marginBottom=16)):
                    ms.Span("change theme of components:",
                            elem_style=dict(marginInlineEnd=16))
                    color = antd.ColorPicker(value=default_color)

                    antd.Button("Primary Button",
                                type="primary",
                                block=True,
                                elem_style=dict(marginTop=8))

        locale.change(fn=lambda _locale: gr.update(locale=_locale),
                      inputs=[locale],
                      outputs=[config_provider])
        direction.change(fn=lambda _direction: gr.update(direction=_direction),
                         inputs=[direction],
                         outputs=[config_provider])
        color.change(fn=lambda _color: gr.update(theme=dict(token=dict(
            colorPrimary=_color))),
                     inputs=[color],
                     outputs=[config_provider])

demo.launch()

image
image

@Col0ring Col0ring pinned this issue Dec 18, 2024
@phoenixor
Copy link

期待已久,终于等到生产可用的版本了😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants