From b8b75314bdc5bb0862cbef4aec18066943d8fc45 Mon Sep 17 00:00:00 2001 From: Lingyi Zhang Date: Tue, 6 Aug 2024 10:25:13 -0400 Subject: [PATCH 1/5] add todos --- .../src/vizro_ai/dashboard/_response_models/components.py | 2 ++ vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py | 4 ++++ vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py | 2 ++ 3 files changed, 8 insertions(+) diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py index feb0dfde8..2e5e39ab8 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py @@ -33,6 +33,8 @@ class ComponentPlan(BaseModel): component_id: str = Field( pattern=r"^[a-z]+(_[a-z]+)?$", description="Small snake case description of this component." ) + # TODO: for improvement, we could dynamically create the pydantic model at runtime so that we can + # validate the df_name against the available dataframes df_name: str = Field( ..., description=""" diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py index 43bdcf62f..1d20b427a 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py @@ -16,6 +16,7 @@ logger = logging.getLogger(__name__) +# TODO: make it a callable class def _create_filter_proxy(df_cols, df_schema, controllable_components) -> BaseModel: """Create a filter proxy model.""" @@ -100,6 +101,9 @@ class ControlPlan(BaseModel): to control a specific component, include the relevant component details. """, ) + # TODO: instead of requesting the df_name, we should request the target component name + # replace df_name with target_component_name, then later retrieve the df_name from the controllable components. + # This logic is more aligned with the Vizro usage pattern. df_name: str = Field( ..., description=""" diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py index dbec8b3d6..32d5d6541 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py @@ -41,6 +41,8 @@ def _convert_to_grid(layout_grid_template_areas: List[str], component_ids: List[ class LayoutPlan(BaseModel): """Layout plan model, which only applies to Vizro Components(Graph, AgGrid, Card).""" + # TODO: we shall try validate the layout plan and retry if it fails. + # currently not feasible because the whole dashboard plan creation is a single API call. layout_grid_template_areas: List[str] = Field( [], description=""" From 7ed068551cd3edcc1ef2c77bbbf437a5ebef48d1 Mon Sep 17 00:00:00 2001 From: Lingyi Zhang Date: Fri, 9 Aug 2024 00:35:17 -0400 Subject: [PATCH 2/5] add 4o mini and small improvement --- vizro-ai/docs/pages/user-guides/customize-vizro-ai.md | 7 +++++-- vizro-ai/src/vizro_ai/_llm_models.py | 2 ++ .../src/vizro_ai/dashboard/_graph/dashboard_creation.py | 5 ++++- .../src/vizro_ai/dashboard/_response_models/controls.py | 2 +- vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py | 3 ++- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index e2e65dfda..b4d7a4c08 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -19,6 +19,8 @@ Vizro-AI currently supports the following [OpenAI models](https://platform.opena - gpt-3.5-turbo-1106 - gpt-3.5-turbo-0125 - gpt-4o-2024-05-13 + - gpt-4o-mini + - gpt-4o-mini-2024-07-18 === "Anthropic" @@ -46,8 +48,9 @@ Refer to the [OpenAI documentation for more about model capabilities](https://pl === "OpenAI" - gpt-3.5-turbo `default`: Ideal for smaller requests and simple specifications. However, due to the complexity of dashboard creation, `gpt-3.5-turbo` often produces incomplete responses for larger tasks. - - gpt-4-turbo: Excels in dashboard creation tasks, providing the most stable and complete responses. - - gpt-4o: Similar performance in terms of the quality of generated content. Compared to gpt-4-turbo, gpt-4o is much faster and cheaper. + - gpt-4o: Excels in dashboard creation tasks, providing stable and complete responses. Compared to gpt-4-turbo, gpt-4o is much faster and cheaper. + - gpt-4-turbo: Excels in dashboard creation tasks, providing stable and complete responses. + - gpt-4o-mini: Ideal for smaller requests and simple specifications. Most cost-effective. === "Anthropic" diff --git a/vizro-ai/src/vizro_ai/_llm_models.py b/vizro-ai/src/vizro_ai/_llm_models.py index b9a955a8b..08b4821e8 100644 --- a/vizro-ai/src/vizro_ai/_llm_models.py +++ b/vizro-ai/src/vizro_ai/_llm_models.py @@ -18,6 +18,8 @@ "gpt-3.5-turbo", "gpt-4o-2024-05-13", "gpt-4o", + "gpt-4o-mini", + "gpt-4o-mini-2024-07-18", ], } diff --git a/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py b/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py index e11caf5da..67f6cc00b 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py +++ b/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py @@ -80,7 +80,10 @@ def _store_df_info(state: GraphState, config: RunnableConfig) -> Dict[str, AllDf ).dataset except DebugFailure as e: logger.warning(f"Failed in name generation {e}") - df_name = f"df_{len(current_df_names)}" + df_name = f"df_{len(current_df_names)+1}" + + if df_name in current_df_names: + df_name = f"df_{len(current_df_names)+1}" current_df_names.append(df_name) diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py index 1d20b427a..4d724a64b 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py @@ -101,7 +101,7 @@ class ControlPlan(BaseModel): to control a specific component, include the relevant component details. """, ) - # TODO: instead of requesting the df_name, we should request the target component name + # TODO: instead of requesting the df_name, we should request the target component name # replace df_name with target_component_name, then later retrieve the df_name from the controllable components. # This logic is more aligned with the Vizro usage pattern. df_name: str = Field( diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py index 32d5d6541..407fcac2d 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py @@ -19,7 +19,8 @@ def _convert_to_grid(layout_grid_template_areas: List[str], component_ids: List[ for row in layout_grid_template_areas: grid_row = [] - for cell in row.split(): + for raw_cell in row.split(): + cell = raw_cell.strip("'\"") if cell == ".": grid_row.append(-1) else: From e37963236d5e71a7990fd7f5ab1d67668377c345 Mon Sep 17 00:00:00 2001 From: Lingyi Zhang Date: Fri, 9 Aug 2024 03:32:56 -0400 Subject: [PATCH 3/5] refactor filter proxy and control plan --- .../dashboard/_response_models/components.py | 4 +- .../dashboard/_response_models/controls.py | 178 +++++++++++------- .../dashboard/_response_models/page.py | 1 + 3 files changed, 109 insertions(+), 74 deletions(-) diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py index 2e5e39ab8..d45980eef 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py @@ -54,7 +54,9 @@ def create(self, model, all_df_metadata) -> Union[vm.Card, vm.AgGrid, vm.Figure] return vm.Graph( id=self.component_id, figure=vizro_ai.plot( - df=all_df_metadata.get_df(self.df_name), user_input=self.component_description + df=all_df_metadata.get_df(self.df_name), + user_input=self.component_description, + max_debug_retry=1, ), ) elif self.component_type == "AgGrid": diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py index 4d724a64b..1469b2c6f 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py @@ -1,7 +1,7 @@ """Controls plan model.""" import logging -from typing import List, Optional +from typing import Any, Dict, List, Optional, Type import pandas as pd import vizro.models as vm @@ -16,76 +16,75 @@ logger = logging.getLogger(__name__) -# TODO: make it a callable class -def _create_filter_proxy(df_cols, df_schema, controllable_components) -> BaseModel: - """Create a filter proxy model.""" - - def validate_targets(v): - """Validate the targets.""" - if v not in controllable_components: - raise ValueError(f"targets must be one of {controllable_components}") - return v - - def validate_targets_not_empty(v): - """Validate the targets not empty.""" - if not controllable_components: - raise ValueError( - """ - This might be due to the filter target is not found in the controllable components. - returning default values. - """ - ) - return v - - def validate_column(v): - """Validate the column.""" - if v not in df_cols: - raise ValueError(f"column must be one of {df_cols}") - return v - - @root_validator(allow_reuse=True) - def validate_date_picker_column(cls, values): - """Validate the column for date picker.""" - column = values.get("column") - selector = values.get("selector") - if selector and selector.type == "date_picker": - if not pd.api.types.is_datetime64_any_dtype(df_schema[column]): +class FilterProxyModel: + """Filter proxy model.""" + + @classmethod + def _create_model( + cls, df_cols: List[str], df_schema: Dict[str, Any], controllable_components: List[str] + ) -> Type[BaseModel]: + def validate_targets(v): + if v not in controllable_components: + raise ValueError(f"targets must be one of {controllable_components}") + return v + + def validate_targets_not_empty(v): + if not controllable_components: raise ValueError( - f""" - The column '{column}' is not of datetime type. Selector type 'date_picker' is - not allowed. Use 'dropdown' instead. + """ + This might be due to the filter target is not found in the controllable components. + returning default values. """ ) - return values - - return create_model( - "FilterProxy", - targets=( - List[str], - Field( - ..., - description=f""" - Target component to be affected by filter. - Must be one of {controllable_components}. ALWAYS REQUIRED. - """, + return v + + def validate_column(v): + if v not in df_cols: + raise ValueError(f"column must be one of {df_cols}") + return v + + @root_validator(allow_reuse=True) + def validate_date_picker_column(cls, values): + column = values.get("column") + selector = values.get("selector") + if selector and selector.type == "date_picker": + if not pd.api.types.is_datetime64_any_dtype(df_schema[column]): + raise ValueError( + f""" + The column '{column}' is not of datetime type. Selector type 'date_picker' is + not allowed. Use 'dropdown' instead. + """ + ) + return values + + return create_model( + "FilterProxy", + targets=( + List[str], + Field( + ..., + description=f""" + Target component to be affected by filter. + Must be one of {controllable_components}. ALWAYS REQUIRED. + """, + ), ), - ), - column=(str, Field(..., description="Column name of DataFrame to filter. ALWAYS REQUIRED.")), - __validators__={ - "validator1": validator("targets", pre=True, each_item=True, allow_reuse=True)(validate_targets), - "validator2": validator("column", allow_reuse=True)(validate_column), - "validator3": validator("targets", pre=True, allow_reuse=True)(validate_targets_not_empty), - "validator4": validate_date_picker_column, - }, - __base__=vm.Filter, - ) + column=(str, Field(..., description="Column name of DataFrame to filter. ALWAYS REQUIRED.")), + __validators__={ + "validator1": validator("targets", pre=True, each_item=True, allow_reuse=True)(validate_targets), + "validator2": validator("column", allow_reuse=True)(validate_column), + "validator3": validator("targets", pre=True, allow_reuse=True)(validate_targets_not_empty), + "validator4": validate_date_picker_column, + }, + __base__=vm.Filter, + ) def _create_filter(filter_prompt, model, df_cols, df_schema, controllable_components) -> vm.Filter: - result_proxy = _create_filter_proxy( + FilterProxy = FilterProxyModel._create_model( df_cols=df_cols, df_schema=df_schema, controllable_components=controllable_components ) - proxy = _get_pydantic_model(query=filter_prompt, llm_model=model, response_model=result_proxy, df_info=df_schema) + proxy = _get_pydantic_model(query=filter_prompt, llm_model=model, response_model=FilterProxy, df_info=df_schema) return vm.Filter.parse_obj(proxy.dict(exclude_unset=True)) @@ -101,29 +100,47 @@ class ControlPlan(BaseModel): to control a specific component, include the relevant component details. """, ) - # TODO: instead of requesting the df_name, we should request the target component name + # instead of requesting the df_name, we should request the target component name # replace df_name with target_component_name, then later retrieve the df_name from the controllable components. # This logic is more aligned with the Vizro usage pattern. - df_name: str = Field( + target_components_id: List[str] = Field( ..., description=""" - The name of the dataframe that the target component will use. - If the dataframe is not used, please specify that. + The id of the target components that this control will affect. """, ) - def create(self, model, controllable_components, all_df_metadata) -> Optional[vm.Filter]: + def create(self, model, controllable_components, all_df_metadata, components_plan) -> Optional[vm.Filter]: """Create the control.""" filter_prompt = f""" Create a filter from the following instructions: <{self.control_description}>. Do not make up things that are optional and DO NOT configure actions, action triggers or action chains. If no options are specified, leave them out. """ + + df_name_collection = [] + for component_plan in components_plan: + if component_plan.component_id in set(self.target_components_id) & set(controllable_components): + name = component_plan.df_name + else: + continue + + if name not in df_name_collection: + df_name_collection.append(name) + if len(df_name_collection) > 1: + logger.warning( + f""" +[FALLBACK] Multiple dataframes found in the target components: {df_name_collection}. +Choose one dataframe to build the filter. +""" + ) + df_name = df_name_collection[0] if df_name_collection else None + try: - _df_schema = all_df_metadata.get_df_schema(self.df_name) + _df_schema = all_df_metadata.get_df_schema(df_name) _df_cols = list(_df_schema.keys()) except KeyError: - logger.warning(f"Dataframe {self.df_name} not found in metadata, returning default values.") + logger.warning(f"Dataframe {df_name} not found in metadata, returning default values.") return None try: @@ -151,7 +168,9 @@ def create(self, model, controllable_components, all_df_metadata) -> Optional[vm if __name__ == "__main__": import pandas as pd from dotenv import load_dotenv + from vizro.tables import dash_ag_grid from vizro_ai._llm_models import _get_llm_model + from vizro_ai.dashboard._response_models.components import ComponentPlan from vizro_ai.dashboard.utils import AllDfMetadata, DfMetadata load_dotenv() @@ -159,16 +178,29 @@ def create(self, model, controllable_components, all_df_metadata) -> Optional[vm model = _get_llm_model() all_df_metadata = AllDfMetadata({}) - all_df_metadata.all_df_metadata["gdp_chart"] = DfMetadata( + all_df_metadata.all_df_metadata["world_gdp"] = DfMetadata( df_schema={"a": "int64", "b": "int64"}, df=pd.DataFrame({"a": [1, 2, 3, 4, 5], "b": [4, 5, 6, 7, 8]}), df_sample=pd.DataFrame({"a": [1, 2, 3, 4, 5], "b": [4, 5, 6, 7, 8]}), ) + components_plan = [ + ComponentPlan( + component_type="AgGrid", + component_description="Create a table that shows GDP data.", + component_id="gdp_table", + df_name="world_gdp", + ) + ] + vm.AgGrid(id="gdp_table", figure=dash_ag_grid(data_frame="world_gdp")) control_plan = ControlPlan( control_type="Filter", control_description="Create a filter that filters the data by column 'a'.", - df_name="gdp_chart", + target_components_id=["gdp_table"], ) control = control_plan.create( - model, ["gdp_chart"], all_df_metadata - ) # error: Target gdp_chart not found in model_manager. + model, + ["gdp_table"], + all_df_metadata, + components_plan, + ) + print(control.__repr__()) # noqa: T201 diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/page.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/page.py index de37b7db1..07f19ebae 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/page.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/page.py @@ -135,6 +135,7 @@ def _build_controls(self, model, all_df_metadata): model=model, controllable_components=self._controllable_components(model=model, all_df_metadata=all_df_metadata), all_df_metadata=all_df_metadata, + components_plan=self.components_plan, ) if control: controls.append(control) From 59d8e37dbf7b6fc68527a04cc5c5e09f40bd977d Mon Sep 17 00:00:00 2001 From: Lingyi Zhang Date: Fri, 9 Aug 2024 14:09:19 -0400 Subject: [PATCH 4/5] tidy --- .../dashboard/_response_models/components.py | 2 +- .../dashboard/_response_models/controls.py | 56 +++++++++--------- .../dashboard/_response_models/layout.py | 57 +++++++++---------- 3 files changed, 54 insertions(+), 61 deletions(-) diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py index d45980eef..9ef580af4 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/components.py @@ -56,7 +56,7 @@ def create(self, model, all_df_metadata) -> Union[vm.Card, vm.AgGrid, vm.Figure] figure=vizro_ai.plot( df=all_df_metadata.get_df(self.df_name), user_input=self.component_description, - max_debug_retry=1, + max_debug_retry=2, ), ) elif self.component_type == "AgGrid": diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py index 1469b2c6f..c86a21c62 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/controls.py @@ -80,14 +80,6 @@ def validate_date_picker_column(cls, values): ) -def _create_filter(filter_prompt, model, df_cols, df_schema, controllable_components) -> vm.Filter: - FilterProxy = FilterProxyModel._create_model( - df_cols=df_cols, df_schema=df_schema, controllable_components=controllable_components - ) - proxy = _get_pydantic_model(query=filter_prompt, llm_model=model, response_model=FilterProxy, df_info=df_schema) - return vm.Filter.parse_obj(proxy.dict(exclude_unset=True)) - - class ControlPlan(BaseModel): """Control plan model.""" @@ -100,9 +92,6 @@ class ControlPlan(BaseModel): to control a specific component, include the relevant component details. """, ) - # instead of requesting the df_name, we should request the target component name - # replace df_name with target_component_name, then later retrieve the df_name from the controllable components. - # This logic is more aligned with the Vizro usage pattern. target_components_id: List[str] = Field( ..., description=""" @@ -110,6 +99,31 @@ class ControlPlan(BaseModel): """, ) + def _get_target_df_name(self, components_plan, controllable_components): + target_controllable = set(self.target_components_id) & set(controllable_components) + df_names = { + component_plan.df_name + for component_plan in components_plan + if component_plan.component_id in target_controllable + } + + if len(df_names) > 1: + logger.warning( + f""" +[FALLBACK] Multiple dataframes found in the target components: {df_names}. +Choose one dataframe to build the filter. +""" + ) + + return next(iter(df_names)) if df_names else None + + def _create_filter(self, filter_prompt, model, df_cols, df_schema, controllable_components) -> vm.Filter: + FilterProxy = FilterProxyModel._create_model( + df_cols=df_cols, df_schema=df_schema, controllable_components=controllable_components + ) + proxy = _get_pydantic_model(query=filter_prompt, llm_model=model, response_model=FilterProxy, df_info=df_schema) + return vm.Filter.parse_obj(proxy.dict(exclude_unset=True)) + def create(self, model, controllable_components, all_df_metadata, components_plan) -> Optional[vm.Filter]: """Create the control.""" filter_prompt = f""" @@ -118,23 +132,7 @@ def create(self, model, controllable_components, all_df_metadata, components_pla If no options are specified, leave them out. """ - df_name_collection = [] - for component_plan in components_plan: - if component_plan.component_id in set(self.target_components_id) & set(controllable_components): - name = component_plan.df_name - else: - continue - - if name not in df_name_collection: - df_name_collection.append(name) - if len(df_name_collection) > 1: - logger.warning( - f""" -[FALLBACK] Multiple dataframes found in the target components: {df_name_collection}. -Choose one dataframe to build the filter. -""" - ) - df_name = df_name_collection[0] if df_name_collection else None + df_name = self._get_target_df_name(components_plan, controllable_components) try: _df_schema = all_df_metadata.get_df_schema(df_name) @@ -145,7 +143,7 @@ def create(self, model, controllable_components, all_df_metadata, components_pla try: if self.control_type == "Filter": - res = _create_filter( + res = self._create_filter( filter_prompt=filter_prompt, model=model, df_cols=_df_cols, diff --git a/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py b/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py index 407fcac2d..6516285ca 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py +++ b/vizro-ai/src/vizro_ai/dashboard/_response_models/layout.py @@ -13,37 +13,9 @@ logger = logging.getLogger(__name__) -def _convert_to_grid(layout_grid_template_areas: List[str], component_ids: List[str]) -> List[List[int]]: - component_map = {component: index for index, component in enumerate(component_ids)} - grid = [] - - for row in layout_grid_template_areas: - grid_row = [] - for raw_cell in row.split(): - cell = raw_cell.strip("'\"") - if cell == ".": - grid_row.append(-1) - else: - try: - grid_row.append(component_map[cell]) - except KeyError: - logger.warning( - f""" -[FALLBACK] Component {cell} not found in component_ids: {component_ids}. -Returning default values. -""" - ) - return [] - grid.append(grid_row) - - return grid - - class LayoutPlan(BaseModel): """Layout plan model, which only applies to Vizro Components(Graph, AgGrid, Card).""" - # TODO: we shall try validate the layout plan and retry if it fails. - # currently not feasible because the whole dashboard plan creation is a single API call. layout_grid_template_areas: List[str] = Field( [], description=""" @@ -58,15 +30,38 @@ class LayoutPlan(BaseModel): """, ) + def _convert_to_grid(self, component_ids: List[str]) -> List[List[int]]: + component_map = {component: index for index, component in enumerate(component_ids)} + grid = [] + + for row in self.layout_grid_template_areas: + grid_row = [] + for raw_cell in row.split(): + cell = raw_cell.strip("'\"") + if cell == ".": + grid_row.append(-1) + else: + try: + grid_row.append(component_map[cell]) + except KeyError: + logger.warning( + f""" +[FALLBACK] Component {cell} not found in component_ids: {component_ids}. +Returning default values. +""" + ) + return [] + grid.append(grid_row) + + return grid + def create(self, component_ids: List[str]) -> Optional[vm.Layout]: """Create the layout.""" if not self.layout_grid_template_areas: return None try: - grid = _convert_to_grid( - layout_grid_template_areas=self.layout_grid_template_areas, component_ids=component_ids - ) + grid = self._convert_to_grid(component_ids=component_ids) actual = vm.Layout(grid=grid) except ValidationError as e: logger.warning( From 712f96d45dffb86df2d660a30bc18a272de98fc2 Mon Sep 17 00:00:00 2001 From: Lingyi Zhang Date: Fri, 9 Aug 2024 15:26:49 -0400 Subject: [PATCH 5/5] take out 4o-mini related content --- ..._143449_lingyi_zhang_improve_code_style.md | 48 +++++++++++++++++++ .../pages/user-guides/customize-vizro-ai.md | 7 +-- vizro-ai/src/vizro_ai/_llm_models.py | 2 - .../dashboard/_graph/dashboard_creation.py | 5 +- 4 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 vizro-ai/changelog.d/20240809_143449_lingyi_zhang_improve_code_style.md diff --git a/vizro-ai/changelog.d/20240809_143449_lingyi_zhang_improve_code_style.md b/vizro-ai/changelog.d/20240809_143449_lingyi_zhang_improve_code_style.md new file mode 100644 index 000000000..f1f65e73c --- /dev/null +++ b/vizro-ai/changelog.d/20240809_143449_lingyi_zhang_improve_code_style.md @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index b4d7a4c08..e2e65dfda 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -19,8 +19,6 @@ Vizro-AI currently supports the following [OpenAI models](https://platform.opena - gpt-3.5-turbo-1106 - gpt-3.5-turbo-0125 - gpt-4o-2024-05-13 - - gpt-4o-mini - - gpt-4o-mini-2024-07-18 === "Anthropic" @@ -48,9 +46,8 @@ Refer to the [OpenAI documentation for more about model capabilities](https://pl === "OpenAI" - gpt-3.5-turbo `default`: Ideal for smaller requests and simple specifications. However, due to the complexity of dashboard creation, `gpt-3.5-turbo` often produces incomplete responses for larger tasks. - - gpt-4o: Excels in dashboard creation tasks, providing stable and complete responses. Compared to gpt-4-turbo, gpt-4o is much faster and cheaper. - - gpt-4-turbo: Excels in dashboard creation tasks, providing stable and complete responses. - - gpt-4o-mini: Ideal for smaller requests and simple specifications. Most cost-effective. + - gpt-4-turbo: Excels in dashboard creation tasks, providing the most stable and complete responses. + - gpt-4o: Similar performance in terms of the quality of generated content. Compared to gpt-4-turbo, gpt-4o is much faster and cheaper. === "Anthropic" diff --git a/vizro-ai/src/vizro_ai/_llm_models.py b/vizro-ai/src/vizro_ai/_llm_models.py index 08b4821e8..b9a955a8b 100644 --- a/vizro-ai/src/vizro_ai/_llm_models.py +++ b/vizro-ai/src/vizro_ai/_llm_models.py @@ -18,8 +18,6 @@ "gpt-3.5-turbo", "gpt-4o-2024-05-13", "gpt-4o", - "gpt-4o-mini", - "gpt-4o-mini-2024-07-18", ], } diff --git a/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py b/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py index 67f6cc00b..e11caf5da 100644 --- a/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py +++ b/vizro-ai/src/vizro_ai/dashboard/_graph/dashboard_creation.py @@ -80,10 +80,7 @@ def _store_df_info(state: GraphState, config: RunnableConfig) -> Dict[str, AllDf ).dataset except DebugFailure as e: logger.warning(f"Failed in name generation {e}") - df_name = f"df_{len(current_df_names)+1}" - - if df_name in current_df_names: - df_name = f"df_{len(current_df_names)+1}" + df_name = f"df_{len(current_df_names)}" current_df_names.append(df_name)