From 122e66aba056442ffb6b49d29727843c58792f8a Mon Sep 17 00:00:00 2001 From: inspectorGadget <63583814+Alfred-Onuada@users.noreply.github.com> Date: Tue, 19 Sep 2023 23:54:50 +0000 Subject: [PATCH 1/5] Added support for plotly when using lida.visualize --- lida/components/scaffold.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lida/components/scaffold.py b/lida/components/scaffold.py index 9ca7b1c2a..d340800a6 100644 --- a/lida/components/scaffold.py +++ b/lida/components/scaffold.py @@ -83,6 +83,22 @@ def plot(data: pd.DataFrame): return chart chart = plot(data) # data already contains the data to be plotted. Always include this line. No additional code beyond this line.. """ + + elif library == "plotly": + instructions = { + "role": "system", + "content": mpl_pre, + } + template = \ + """ +import plotly.express as px + +def plot(data: pd.DataFrame): + # only modify this section + return chart +chart = plot(data) # data already contains the data to be plotted. Always include this line. No additional code beyond this line.. +""" + else: raise ValueError( "Unsupported library. Choose from 'matplotlib', 'seaborn', 'plotly', 'bokeh', 'ggplot', 'altair'." From 5b5cb1c81f9a1a6b427501863eed567b16442cac Mon Sep 17 00:00:00 2001 From: inspectorGadget <63583814+Alfred-Onuada@users.noreply.github.com> Date: Wed, 20 Sep 2023 10:05:58 +0000 Subject: [PATCH 2/5] added support for plotly to executor function --- lida/components/executor.py | 41 ++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/lida/components/executor.py b/lida/components/executor.py index e6b10c9c8..f683d73cb 100644 --- a/lida/components/executor.py +++ b/lida/components/executor.py @@ -235,7 +235,46 @@ def execute( ) ) return charts + + elif library == "plotly": + for code in code_specs: + try: + ex_locals = get_globals_dict(code, data) + exec(code, ex_locals) + chart = ex_locals["chart"] + + # Convert Plotly chart to JSON format + chart_json = chart.to_json() + + charts.append( + ChartExecutorResponse( + spec=chart_json, + status=True, + raster=None, # No raster image for Plotly + code=code, + library=library, + ) + ) + except Exception as exception_error: + print(code) + print(traceback.format_exc()) + if return_error: + charts.append( + ChartExecutorResponse( + spec=None, + status=False, + raster=None, + code=code, + library=library, + error={ + "message": str(exception_error), + "traceback": traceback.format_exc(), + }, + ) + ) + return charts + else: raise Exception( - f"Unsupported library. Supported libraries are altair, matplotlib, seaborn, ggplot. You provided {library}" + f"Unsupported library. Supported libraries are altair, matplotlib, seaborn, ggplot, plotly. You provided {library}" ) From 32dc03226c7b87abc4b0ffdaf9d041ab574a07d6 Mon Sep 17 00:00:00 2001 From: inspectorGadget <63583814+Alfred-Onuada@users.noreply.github.com> Date: Wed, 20 Sep 2023 10:24:48 +0000 Subject: [PATCH 3/5] updated plotly prompt to attempt to fix use of non-numeric columns in calculation in lida.visulaize --- lida/components/scaffold.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lida/components/scaffold.py b/lida/components/scaffold.py index d340800a6..65230bc13 100644 --- a/lida/components/scaffold.py +++ b/lida/components/scaffold.py @@ -87,7 +87,7 @@ def plot(data: pd.DataFrame): elif library == "plotly": instructions = { "role": "system", - "content": mpl_pre, + "content": f"If calculating metrics such as mean, median, mode, etc. ALWAYS use the option 'numeric_only=True' when applicable and available, {mpl_pre}", } template = \ """ From 2d2b1c10e1b348806d38e0f681a1504dccd2db1d Mon Sep 17 00:00:00 2001 From: Alfred-Onuada Date: Fri, 22 Sep 2023 21:23:35 +0100 Subject: [PATCH 4/5] update to fix the plotly visualization, now returns raster, charts and works with multiple plot types --- lida/components/executor.py | 22 ++++++++++++---------- lida/components/scaffold.py | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lida/components/executor.py b/lida/components/executor.py index f683d73cb..7be321096 100644 --- a/lida/components/executor.py +++ b/lida/components/executor.py @@ -9,6 +9,7 @@ import matplotlib.pyplot as plt import pandas as pd +import plotly.io as pio from lida.datamodel import ChartExecutorResponse, Summary @@ -243,18 +244,19 @@ def execute( exec(code, ex_locals) chart = ex_locals["chart"] - # Convert Plotly chart to JSON format - chart_json = chart.to_json() + if pio: + chart_bytes = pio.to_image(chart, 'png') + plot_data = base64.b64encode(chart_bytes).decode('utf-8') - charts.append( - ChartExecutorResponse( - spec=chart_json, - status=True, - raster=None, # No raster image for Plotly - code=code, - library=library, + charts.append( + ChartExecutorResponse( + spec=None, + status=True, + raster=plot_data, + code=code, + library=library, + ) ) - ) except Exception as exception_error: print(code) print(traceback.format_exc()) diff --git a/lida/components/scaffold.py b/lida/components/scaffold.py index 65230bc13..776d4fe08 100644 --- a/lida/components/scaffold.py +++ b/lida/components/scaffold.py @@ -87,7 +87,7 @@ def plot(data: pd.DataFrame): elif library == "plotly": instructions = { "role": "system", - "content": f"If calculating metrics such as mean, median, mode, etc. ALWAYS use the option 'numeric_only=True' when applicable and available, {mpl_pre}", + "content": f"If calculating metrics such as mean, median, mode, etc. ALWAYS use the option 'numeric_only=True' when applicable and available, AVOID visualizations that require nbformat library, ALWAYS return the chart object {mpl_pre}", } template = \ """ From 74473b3371a864932e951a9b08e6bff0a92f3c60 Mon Sep 17 00:00:00 2001 From: Alfred-Onuada Date: Sun, 24 Sep 2023 08:18:14 +0100 Subject: [PATCH 5/5] updates to include kaleido in pyproject.toml --- lida/components/scaffold.py | 1 + pyproject.toml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lida/components/scaffold.py b/lida/components/scaffold.py index 776d4fe08..9a9568fa6 100644 --- a/lida/components/scaffold.py +++ b/lida/components/scaffold.py @@ -95,6 +95,7 @@ def plot(data: pd.DataFrame): def plot(data: pd.DataFrame): # only modify this section + fig.show() return chart chart = plot(data) # data already contains the data to be plotted. Always include this line. No additional code beyond this line.. """ diff --git a/pyproject.toml b/pyproject.toml index 27b7759d8..8ed52c85d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,8 @@ dependencies = [ "networkx", "geopandas", "matplotlib-venn", - "wordcloud", + "wordcloud", + "kaleido" ] optional-dependencies = {web = ["fastapi", "uvicorn"], transformers = ["llmx[transformers]"], tools=["geopy", "basemap", "basemap-data-hires"], infographics=["peacasso"]}