Spaces:
Running
Running
| 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 create_bubble_item(i: int): | |
| is_ai = i % 2 != 0 | |
| content = 'Mock AI content. ' * 20 if is_ai else f'Mock User content `{i}`.' | |
| return { | |
| "role": "ai" if is_ai else "user", | |
| "content": content, | |
| "key": i - 1 | |
| } | |
| def add_bubble(state_value): | |
| history_len = len(state_value["history"]) | |
| state_value["history"].append(create_bubble_item(history_len + 1)) | |
| return gr.update(value=state_value), gr.update( | |
| items=state_value["history"]) | |
| def refresh(state_value, e: gr.EventData): | |
| clicked_key = e._data["component"]["key"] | |
| gr.Info(f"You clicked refresh button, item {clicked_key}") | |
| state_value["history"][clicked_key]["content"] = "Refreshed" | |
| return gr.update(value=state_value), gr.update( | |
| items=state_value["history"]) | |
| def like(state_value, e: gr.EventData): | |
| clicked_key = e._data["component"]["key"] | |
| gr.Info(f"You clicked like button, item {clicked_key}") | |
| state_value["history"][clicked_key]["meta"] = { | |
| "action": "like", | |
| } | |
| return gr.update(value=state_value), gr.update( | |
| items=state_value["history"]) | |
| def dislike(state_value, e: gr.EventData): | |
| clicked_key = e._data["component"]["key"] | |
| gr.Info(f"You clicked dislike button, item {clicked_key}") | |
| state_value["history"][clicked_key]["meta"] = { | |
| "action": "dislike", | |
| } | |
| return gr.update(value=state_value), gr.update( | |
| items=state_value["history"]) | |
| default_history = [ | |
| create_bubble_item(1), | |
| create_bubble_item(2), | |
| create_bubble_item(3) | |
| ] | |
| with gr.Blocks() as demo: | |
| with ms.Application(): | |
| state = gr.State({"history": default_history}) | |
| with antdx.XProvider(): | |
| 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=default_history, | |
| elem_style=dict(maxHeight=500), | |
| elem_id="chatbot") as bubble_list: | |
| # Define Roles | |
| with ms.Slot("roles"): | |
| with antdx.Bubble.List.Role( | |
| role="ai", | |
| placement="start", | |
| typing=dict(step=5, interval=20), | |
| styles=dict(footer=dict(width="100%")), | |
| elem_style=dict(maxWidth=600)): | |
| with ms.Slot("avatar"): | |
| with antd.Avatar(elem_style=dict( | |
| backgroundColor="#fde3cf")): | |
| with ms.Slot("icon"): | |
| antd.Icon("UserOutlined") | |
| # use messageRender to render markdown content | |
| with ms.Slot( | |
| "messageRender", | |
| params_mapping="""content => content"""): | |
| ms.Markdown() | |
| # render footer | |
| with ms.Slot("footer", | |
| params_mapping="""(item) => { | |
| return { copy: { copyable: { text: item.content, tooltips: false } } ,refresh: { key: item.key }, like: { key: item.key, color: item.meta?.action === "like" ? 'primary' : 'default' }, dislike: { key: item.key, color: item.meta?.action === "dislike" ? 'primary' : 'default' } } | |
| }"""): | |
| with antd.Typography.Text( | |
| copyable=dict(tooltips=False), | |
| as_item="copy"): | |
| with ms.Slot("copyable.icon"): | |
| with antd.Button(value=None, | |
| size="small", | |
| color="default", | |
| variant="text"): | |
| with ms.Slot("icon"): | |
| antd.Icon("CopyOutlined") | |
| with antd.Button(value=None, | |
| size="small", | |
| color="default", | |
| variant="text"): | |
| with ms.Slot("icon"): | |
| antd.Icon("CheckOutlined") | |
| with antd.Button( | |
| value=None, | |
| size="small", | |
| color="default", | |
| variant="text", | |
| as_item="refresh") as refresh_btn: | |
| with ms.Slot("icon"): | |
| antd.Icon("SyncOutlined") | |
| refresh_btn.click(fn=refresh, | |
| inputs=[state], | |
| outputs=[state, bubble_list]) | |
| with antd.Button(value=None, | |
| size="small", | |
| variant="text", | |
| as_item="like") as like_btn: | |
| with ms.Slot("icon"): | |
| antd.Icon("SmileOutlined") | |
| like_btn.click(fn=like, | |
| inputs=[state], | |
| outputs=[state, bubble_list]) | |
| with antd.Button( | |
| value=None, | |
| size="small", | |
| variant="text", | |
| as_item="dislike") as dislike_btn: | |
| with ms.Slot("icon"): | |
| antd.Icon("FrownOutlined") | |
| dislike_btn.click(fn=dislike, | |
| inputs=[state], | |
| outputs=[state, bubble_list]) | |
| with antdx.Bubble.List.Role( | |
| role="user", | |
| placement="end", | |
| ): | |
| with ms.Slot("avatar"): | |
| with antd.Avatar(elem_style=dict( | |
| backgroundColor="#87d068")): | |
| with ms.Slot("icon"): | |
| antd.Icon("UserOutlined") | |
| with ms.Slot( | |
| "messageRender", | |
| 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() | |