Spaces:
Running
Running
| """VizroAI UI dashboard configuration.""" | |
| import json | |
| import black | |
| import dash | |
| import dash_bootstrap_components as dbc | |
| import pandas as pd | |
| import plotly.graph_objects as go | |
| import plotly.io as pio | |
| import vizro.models as vm | |
| import vizro.plotly.express as px | |
| from actions import data_upload_action, display_filename, run_vizro_ai, update_table | |
| from components import ( | |
| CodeClipboard, | |
| CustomDashboard, | |
| DropdownMenu, | |
| HeaderComponent, | |
| Icon, | |
| Modal, | |
| MyDropdown, | |
| OffCanvas, | |
| ToggleSwitch, | |
| UserPromptTextArea, | |
| UserUpload, | |
| custom_table, | |
| ) | |
| from dash import Input, Output, State, callback, ctx, dcc, get_asset_url, html | |
| from vizro import Vizro | |
| try: | |
| from langchain_anthropic import ChatAnthropic | |
| except ImportError: | |
| ChatAnthropic = None | |
| try: | |
| from langchain_mistralai import ChatMistralAI | |
| except ImportError: | |
| ChatMistralAI = None | |
| vm.Container.add_type("components", UserUpload) | |
| vm.Container.add_type("components", MyDropdown) | |
| vm.Container.add_type("components", OffCanvas) | |
| vm.Container.add_type("components", CodeClipboard) | |
| vm.Container.add_type("components", Icon) | |
| vm.Container.add_type("components", Modal) | |
| vm.Container.add_type("components", ToggleSwitch) | |
| vm.Container.add_type("components", UserPromptTextArea) | |
| vm.Container.add_type("components", DropdownMenu) | |
| vm.Container.add_type("components", HeaderComponent) | |
| vm.Page.add_type("components", UserUpload) | |
| vm.Page.add_type("components", MyDropdown) | |
| vm.Page.add_type("components", OffCanvas) | |
| vm.Page.add_type("components", CodeClipboard) | |
| vm.Page.add_type("components", Icon) | |
| vm.Page.add_type("components", Modal) | |
| SUPPORTED_MODELS = { | |
| "OpenAI": [ | |
| "gpt-4o-mini", | |
| "gpt-4o", | |
| "gpt-4-turbo", | |
| ], | |
| "Anthropic": [ | |
| "claude-3-opus-latest", | |
| "claude-3-5-sonnet-latest", | |
| "claude-3-sonnet-20240229", | |
| "claude-3-haiku-20240307", | |
| ], | |
| "Mistral": ["mistral-large-latest", "open-mistral-nemo", "codestral-latest"], | |
| "xAI": ["grok-beta"], | |
| } | |
| plot_page = vm.Page( | |
| id="vizro_ai_plot_page", | |
| title="Vizro-AI - create interactive charts with Plotly and Vizro", | |
| layout=vm.Layout( | |
| grid=[ | |
| [4, 4, 4, 4], | |
| [2, 2, 1, 1], | |
| [2, 2, 1, 1], | |
| [3, 3, 1, 1], | |
| [3, 3, 1, 1], | |
| [3, 3, 1, 1], | |
| *[[0, 0, 1, 1]] * 8, | |
| ] | |
| ), | |
| components=[ | |
| vm.Container( | |
| title="", | |
| components=[CodeClipboard(id="plot"), ToggleSwitch(id="toggle-id")], | |
| layout=vm.Layout( | |
| grid=[*[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] * 7, [-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1]], | |
| row_gap="12px", | |
| col_gap="12px", | |
| ), | |
| ), | |
| vm.Container( | |
| title="", | |
| layout=vm.Layout( | |
| grid=[ | |
| *[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] * 10, | |
| [-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1], | |
| ] | |
| ), | |
| components=[ | |
| vm.Graph(id="graph-id", figure=px.scatter(pd.DataFrame())), | |
| DropdownMenu(id="dropdown-menu"), | |
| ], | |
| ), | |
| vm.Container( | |
| id="upload-data-container", | |
| title="Turn your data into visuals — just upload, describe, and see your chart in action", | |
| layout=vm.Layout( | |
| grid=[ | |
| [1], | |
| [0], | |
| ], | |
| row_gap="0px", | |
| # row_min_height="40px", | |
| ), | |
| components=[ | |
| UserUpload( | |
| id="data-upload-id", | |
| actions=[ | |
| vm.Action( | |
| function=data_upload_action(), | |
| inputs=["data-upload-id.contents", "data-upload-id.filename"], | |
| outputs=["data-store-id.data", "modal-table-icon.style", "modal-table-tooltip.style"], | |
| ), | |
| vm.Action( | |
| function=display_filename(), | |
| inputs=["data-store-id.data"], | |
| outputs=["upload-message-id.children"], | |
| ), | |
| vm.Action( | |
| function=update_table(), | |
| inputs=["data-store-id.data"], | |
| outputs=["modal-table.children", "modal-title.children"], | |
| ), | |
| ], | |
| ), | |
| vm.Figure(id="show-data-component", figure=custom_table(data_frame=pd.DataFrame())), | |
| ], | |
| ), | |
| vm.Container( | |
| title="", | |
| layout=vm.Layout( | |
| grid=[ | |
| [3, 3, 3, 3, 3, 3, 3, 3, 3], | |
| [3, 3, 3, 3, 3, 3, 3, 3, 3], | |
| [3, 3, 3, 3, 3, 3, 3, 3, 3], | |
| [2, -1, -1, -1, -1, 1, 1, 0, 0], | |
| ], | |
| row_gap="10px", | |
| col_gap="4px", | |
| ), | |
| components=[ | |
| vm.Button( | |
| id="trigger-button-id", | |
| text="Run Vizro-AI", | |
| actions=[ | |
| vm.Action( | |
| function=run_vizro_ai(), | |
| inputs=[ | |
| "text-area-id.value", | |
| "trigger-button-id.n_clicks", | |
| "data-store-id.data", | |
| "model-dropdown-id.value", | |
| "settings-api-key.value", | |
| "settings-api-base.value", | |
| "settings-dropdown.value", | |
| ], | |
| outputs=["plot-code-markdown.children", "graph-id.figure", "code-output-store-id.data"], | |
| ), | |
| ], | |
| ), | |
| MyDropdown( | |
| options=SUPPORTED_MODELS["OpenAI"], value="gpt-4o-mini", multi=False, id="model-dropdown-id" | |
| ), | |
| OffCanvas( | |
| id="settings", | |
| options=["OpenAI", "Anthropic", "Mistral", "xAI"], | |
| value="OpenAI", | |
| ), | |
| UserPromptTextArea(id="text-area-id"), | |
| # Modal(id="modal"), | |
| ], | |
| ), | |
| vm.Container( | |
| title="", | |
| components=[HeaderComponent()], | |
| ), | |
| ], | |
| ) | |
| dashboard = CustomDashboard(pages=[plot_page]) | |
| # pure dash callbacks | |
| def open_settings(n_clicks, is_open): | |
| """Callback for opening and closing offcanvas settings component.""" | |
| return not is_open if n_clicks else is_open | |
| def show_api_key(value): | |
| """Callback to show api key.""" | |
| return "text" if value else "password" | |
| def show_api_base(value): | |
| """Callback to show api base.""" | |
| return "text" if value else "password" | |
| def toggle_code(value, data): | |
| """Callback for switching between vizro and plotly code.""" | |
| if not data: | |
| return dash.no_update | |
| ai_code = data["ai_outputs"]["vizro"]["code"] if value else data["ai_outputs"]["plotly"]["code"] | |
| formatted_code = black.format_str(ai_code, mode=black.Mode(line_length=100)) | |
| ai_response = "\n".join(["```python", formatted_code, "```"]) | |
| return ai_response | |
| def open_modal(n_clicks, is_open, data): | |
| """Callback for opening modal component.""" | |
| if not data: | |
| return dash.no_update | |
| if n_clicks: | |
| return not is_open | |
| return is_open | |
| def download_fig(n_clicks_html, n_clicks_json, data): | |
| """Callback for downloading vizro fig.""" | |
| if not data: | |
| return dash.no_update | |
| if not (n_clicks_html or n_clicks_json): | |
| return dash.no_update | |
| button_clicked = ctx.triggered_id | |
| if button_clicked == "dropdown-menu-html": | |
| vizro_json = json.loads(data["ai_outputs"]["vizro"]["fig"]) | |
| fig = go.Figure(vizro_json) | |
| graphs_html = pio.to_html(fig) | |
| return dcc.send_string(graphs_html, filename="vizro_fig.html") | |
| if button_clicked == "dropdown-menu-json": | |
| plotly_json = data["ai_outputs"]["plotly"]["fig"] | |
| return dcc.send_string(plotly_json, "plotly_fig.json") | |
| def update_model_dropdown(value): | |
| """Callback for updating available models.""" | |
| available_models = SUPPORTED_MODELS[value] | |
| default_model = available_models[0] | |
| return available_models, default_model | |
| app = Vizro().build(dashboard) | |
| app.dash.layout.children.append( | |
| html.Div( | |
| [ | |
| html.Div( | |
| [ | |
| "Made using ", | |
| html.Img(src=get_asset_url("logo.svg"), id="banner", alt="Vizro logo"), | |
| dbc.NavLink("vizro", href="https://github.com/mckinsey/vizro", target="_blank", external_link=True), | |
| ], | |
| style={"display": "flex", "flexDirection": "row"}, | |
| ), | |
| ], | |
| className="anchor-container", | |
| ) | |
| ) | |
| server = app.dash.server | |
| if __name__ == "__main__": | |
| app.run() | |